s4-netlogon: honnor DS_RETURN_DNS_NAME flag
[garming/samba-autobuild/.git] / source4 / rpc_server / netlogon / dcerpc_netlogon.c
1 /*
2    Unix SMB/CIFS implementation.
3
4    endpoint server for the netlogon pipe
5
6    Copyright (C) Andrew Bartlett <abartlet@samba.org> 2004-2008
7    Copyright (C) Stefan Metzmacher <metze@samba.org>  2005
8    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         netlogon_creds_decrypt_samlogon_logon(creds,
633                                               r->in.logon_level,
634                                               r->in.logon);
635
636         switch (r->in.logon_level) {
637         case NetlogonInteractiveInformation:
638         case NetlogonServiceInformation:
639         case NetlogonInteractiveTransitiveInformation:
640         case NetlogonServiceTransitiveInformation:
641
642                 /* TODO: we need to deny anonymous access here */
643                 nt_status = auth_context_create(mem_ctx,
644                                                 dce_call->event_ctx, dce_call->msg_ctx,
645                                                 dce_call->conn->dce_ctx->lp_ctx,
646                                                 &auth_context);
647                 NT_STATUS_NOT_OK_RETURN(nt_status);
648
649                 user_info->logon_parameters = r->in.logon->password->identity_info.parameter_control;
650                 user_info->client.account_name = r->in.logon->password->identity_info.account_name.string;
651                 user_info->client.domain_name = r->in.logon->password->identity_info.domain_name.string;
652                 user_info->workstation_name = r->in.logon->password->identity_info.workstation.string;
653
654                 user_info->flags |= USER_INFO_INTERACTIVE_LOGON;
655                 user_info->password_state = AUTH_PASSWORD_HASH;
656
657                 user_info->password.hash.lanman = talloc(user_info, struct samr_Password);
658                 NT_STATUS_HAVE_NO_MEMORY(user_info->password.hash.lanman);
659                 *user_info->password.hash.lanman = r->in.logon->password->lmpassword;
660
661                 user_info->password.hash.nt = talloc(user_info, struct samr_Password);
662                 NT_STATUS_HAVE_NO_MEMORY(user_info->password.hash.nt);
663                 *user_info->password.hash.nt = r->in.logon->password->ntpassword;
664
665                 break;
666         case NetlogonNetworkInformation:
667         case NetlogonNetworkTransitiveInformation:
668
669                 /* TODO: we need to deny anonymous access here */
670                 nt_status = auth_context_create(mem_ctx,
671                                                 dce_call->event_ctx, dce_call->msg_ctx,
672                                                 dce_call->conn->dce_ctx->lp_ctx,
673                                                 &auth_context);
674                 NT_STATUS_NOT_OK_RETURN(nt_status);
675
676                 nt_status = auth_context_set_challenge(auth_context, r->in.logon->network->challenge, "netr_LogonSamLogonWithFlags");
677                 NT_STATUS_NOT_OK_RETURN(nt_status);
678
679                 user_info->logon_parameters = r->in.logon->network->identity_info.parameter_control;
680                 user_info->client.account_name = r->in.logon->network->identity_info.account_name.string;
681                 user_info->client.domain_name = r->in.logon->network->identity_info.domain_name.string;
682                 user_info->workstation_name = r->in.logon->network->identity_info.workstation.string;
683
684                 user_info->password_state = AUTH_PASSWORD_RESPONSE;
685                 user_info->password.response.lanman = data_blob_talloc(mem_ctx, r->in.logon->network->lm.data, r->in.logon->network->lm.length);
686                 user_info->password.response.nt = data_blob_talloc(mem_ctx, r->in.logon->network->nt.data, r->in.logon->network->nt.length);
687
688                 break;
689
690
691         case NetlogonGenericInformation:
692         {
693                 if (creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
694                         /* OK */
695                 } else if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
696                         /* OK */
697                 } else {
698                         /* Using DES to verify kerberos tickets makes no sense */
699                         return NT_STATUS_INVALID_PARAMETER;
700                 }
701
702                 if (strcmp(r->in.logon->generic->package_name.string, "Kerberos") == 0) {
703                         NTSTATUS status;
704                         struct dcerpc_binding_handle *irpc_handle;
705                         struct kdc_check_generic_kerberos check;
706                         struct netr_GenericInfo2 *generic = talloc_zero(mem_ctx, struct netr_GenericInfo2);
707                         NT_STATUS_HAVE_NO_MEMORY(generic);
708                         *r->out.authoritative = 1;
709
710                         /* TODO: Describe and deal with these flags */
711                         *r->out.flags = 0;
712
713                         r->out.validation->generic = generic;
714
715                         irpc_handle = irpc_binding_handle_by_name(mem_ctx,
716                                                                   dce_call->msg_ctx,
717                                                                   "kdc_server",
718                                                                   &ndr_table_irpc);
719                         if (irpc_handle == NULL) {
720                                 return NT_STATUS_NO_LOGON_SERVERS;
721                         }
722
723                         check.in.generic_request =
724                                 data_blob_const(r->in.logon->generic->data,
725                                                 r->in.logon->generic->length);
726
727                         status = dcerpc_kdc_check_generic_kerberos_r(irpc_handle,
728                                                                      mem_ctx,
729                                                                      &check);
730                         if (!NT_STATUS_IS_OK(status)) {
731                                 return status;
732                         }
733                         generic->length = check.out.generic_reply.length;
734                         generic->data = check.out.generic_reply.data;
735                         return NT_STATUS_OK;
736                 }
737
738                 /* Until we get an implemetnation of these other packages */
739                 return NT_STATUS_INVALID_PARAMETER;
740         }
741         default:
742                 return NT_STATUS_INVALID_PARAMETER;
743         }
744
745         nt_status = auth_check_password(auth_context, mem_ctx, user_info, &user_info_dc);
746         /* TODO: set *r->out.authoritative = 0 on specific errors */
747         NT_STATUS_NOT_OK_RETURN(nt_status);
748
749         switch (r->in.validation_level) {
750         case 2:
751                 nt_status = auth_convert_user_info_dc_sambaseinfo(mem_ctx, user_info_dc, &sam);
752                 NT_STATUS_NOT_OK_RETURN(nt_status);
753
754                 sam2 = talloc_zero(mem_ctx, struct netr_SamInfo2);
755                 NT_STATUS_HAVE_NO_MEMORY(sam2);
756                 sam2->base = *sam;
757
758                 /* And put into the talloc tree */
759                 talloc_steal(sam2, sam);
760                 r->out.validation->sam2 = sam2;
761
762                 sam = &sam2->base;
763                 break;
764
765         case 3:
766                 nt_status = auth_convert_user_info_dc_saminfo3(mem_ctx,
767                                                               user_info_dc,
768                                                               &sam3);
769                 NT_STATUS_NOT_OK_RETURN(nt_status);
770
771                 r->out.validation->sam3 = sam3;
772
773                 sam = &sam3->base;
774                 break;
775
776         case 6:
777                 nt_status = auth_convert_user_info_dc_saminfo3(mem_ctx,
778                                                            user_info_dc,
779                                                            &sam3);
780                 NT_STATUS_NOT_OK_RETURN(nt_status);
781
782                 sam6 = talloc_zero(mem_ctx, struct netr_SamInfo6);
783                 NT_STATUS_HAVE_NO_MEMORY(sam6);
784                 sam6->base = sam3->base;
785                 sam = &sam6->base;
786                 sam6->sidcount = sam3->sidcount;
787                 sam6->sids = sam3->sids;
788
789                 sam6->dns_domainname.string = lpcfg_dnsdomain(dce_call->conn->dce_ctx->lp_ctx);
790                 sam6->principle.string = talloc_asprintf(mem_ctx, "%s@%s",
791                                                          sam->account_name.string, sam6->dns_domainname.string);
792                 NT_STATUS_HAVE_NO_MEMORY(sam6->principle.string);
793                 /* And put into the talloc tree */
794                 talloc_steal(sam6, sam3);
795
796                 r->out.validation->sam6 = sam6;
797                 break;
798
799         default:
800                 return NT_STATUS_INVALID_INFO_CLASS;
801         }
802
803         netlogon_creds_encrypt_samlogon_validation(creds,
804                                                    r->in.validation_level,
805                                                    r->out.validation);
806
807         /* TODO: Describe and deal with these flags */
808         *r->out.flags = 0;
809
810         return NT_STATUS_OK;
811 }
812
813 static NTSTATUS dcesrv_netr_LogonSamLogonEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
814                                      struct netr_LogonSamLogonEx *r)
815 {
816         NTSTATUS nt_status;
817         struct netlogon_creds_CredentialState *creds;
818
819         *r->out.authoritative = 1;
820
821         nt_status = dcesrv_netr_LogonSamLogon_check(r);
822         if (!NT_STATUS_IS_OK(nt_status)) {
823                 return nt_status;
824         }
825
826         nt_status = schannel_get_creds_state(mem_ctx,
827                                              dce_call->conn->dce_ctx->lp_ctx,
828                                              r->in.computer_name, &creds);
829         if (!NT_STATUS_IS_OK(nt_status)) {
830                 return nt_status;
831         }
832
833         if (!dce_call->conn->auth_state.auth_info ||
834             dce_call->conn->auth_state.auth_info->auth_type != DCERPC_AUTH_TYPE_SCHANNEL) {
835                 return NT_STATUS_ACCESS_DENIED;
836         }
837         return dcesrv_netr_LogonSamLogon_base(dce_call, mem_ctx, r, creds);
838 }
839
840 /*
841   netr_LogonSamLogonWithFlags
842
843 */
844 static NTSTATUS dcesrv_netr_LogonSamLogonWithFlags(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
845                                             struct netr_LogonSamLogonWithFlags *r)
846 {
847         NTSTATUS nt_status;
848         struct netlogon_creds_CredentialState *creds;
849         struct netr_LogonSamLogonEx r2;
850
851         struct netr_Authenticator *return_authenticator;
852
853         ZERO_STRUCT(r2);
854
855         r2.in.server_name       = r->in.server_name;
856         r2.in.computer_name     = r->in.computer_name;
857         r2.in.logon_level       = r->in.logon_level;
858         r2.in.logon             = r->in.logon;
859         r2.in.validation_level  = r->in.validation_level;
860         r2.in.flags             = r->in.flags;
861         r2.out.validation       = r->out.validation;
862         r2.out.authoritative    = r->out.authoritative;
863         r2.out.flags            = r->out.flags;
864
865         *r->out.authoritative = 1;
866
867         nt_status = dcesrv_netr_LogonSamLogon_check(&r2);
868         if (!NT_STATUS_IS_OK(nt_status)) {
869                 return nt_status;
870         }
871
872         return_authenticator = talloc(mem_ctx, struct netr_Authenticator);
873         NT_STATUS_HAVE_NO_MEMORY(return_authenticator);
874
875         nt_status = dcesrv_netr_creds_server_step_check(dce_call,
876                                                         mem_ctx,
877                                                         r->in.computer_name,
878                                                         r->in.credential, return_authenticator,
879                                                         &creds);
880         NT_STATUS_NOT_OK_RETURN(nt_status);
881
882         nt_status = dcesrv_netr_LogonSamLogon_base(dce_call, mem_ctx, &r2, creds);
883
884         r->out.return_authenticator     = return_authenticator;
885
886         return nt_status;
887 }
888
889 /*
890   netr_LogonSamLogon
891 */
892 static NTSTATUS dcesrv_netr_LogonSamLogon(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
893                                    struct netr_LogonSamLogon *r)
894 {
895         struct netr_LogonSamLogonWithFlags r2;
896         uint32_t flags = 0;
897         NTSTATUS status;
898
899         ZERO_STRUCT(r2);
900
901         r2.in.server_name = r->in.server_name;
902         r2.in.computer_name = r->in.computer_name;
903         r2.in.credential  = r->in.credential;
904         r2.in.return_authenticator = r->in.return_authenticator;
905         r2.in.logon_level = r->in.logon_level;
906         r2.in.logon = r->in.logon;
907         r2.in.validation_level = r->in.validation_level;
908         r2.in.flags = &flags;
909         r2.out.validation = r->out.validation;
910         r2.out.authoritative = r->out.authoritative;
911         r2.out.flags = &flags;
912
913         status = dcesrv_netr_LogonSamLogonWithFlags(dce_call, mem_ctx, &r2);
914
915         r->out.return_authenticator = r2.out.return_authenticator;
916
917         return status;
918 }
919
920
921 /*
922   netr_LogonSamLogoff
923 */
924 static NTSTATUS dcesrv_netr_LogonSamLogoff(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
925                        struct netr_LogonSamLogoff *r)
926 {
927         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
928 }
929
930
931
932 /*
933   netr_DatabaseDeltas
934 */
935 static NTSTATUS dcesrv_netr_DatabaseDeltas(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
936                        struct netr_DatabaseDeltas *r)
937 {
938         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
939 }
940
941
942 /*
943   netr_DatabaseSync2
944 */
945 static NTSTATUS dcesrv_netr_DatabaseSync2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
946                        struct netr_DatabaseSync2 *r)
947 {
948         /* win2k3 native mode returns  "NOT IMPLEMENTED" for this call */
949         return NT_STATUS_NOT_IMPLEMENTED;
950 }
951
952
953 /*
954   netr_DatabaseSync
955 */
956 static NTSTATUS dcesrv_netr_DatabaseSync(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
957                        struct netr_DatabaseSync *r)
958 {
959         struct netr_DatabaseSync2 r2;
960         NTSTATUS status;
961
962         ZERO_STRUCT(r2);
963
964         r2.in.logon_server = r->in.logon_server;
965         r2.in.computername = r->in.computername;
966         r2.in.credential = r->in.credential;
967         r2.in.database_id = r->in.database_id;
968         r2.in.restart_state = SYNCSTATE_NORMAL_STATE;
969         r2.in.sync_context = r->in.sync_context;
970         r2.out.sync_context = r->out.sync_context;
971         r2.out.delta_enum_array = r->out.delta_enum_array;
972         r2.in.preferredmaximumlength = r->in.preferredmaximumlength;
973
974         status = dcesrv_netr_DatabaseSync2(dce_call, mem_ctx, &r2);
975
976         return status;
977 }
978
979
980 /*
981   netr_AccountDeltas
982 */
983 static NTSTATUS dcesrv_netr_AccountDeltas(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
984                        struct netr_AccountDeltas *r)
985 {
986         /* w2k3 returns "NOT IMPLEMENTED" for this call */
987         return NT_STATUS_NOT_IMPLEMENTED;
988 }
989
990
991 /*
992   netr_AccountSync
993 */
994 static NTSTATUS dcesrv_netr_AccountSync(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
995                        struct netr_AccountSync *r)
996 {
997         /* w2k3 returns "NOT IMPLEMENTED" for this call */
998         return NT_STATUS_NOT_IMPLEMENTED;
999 }
1000
1001
1002 /*
1003   netr_GetDcName
1004 */
1005 static WERROR dcesrv_netr_GetDcName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1006                        struct netr_GetDcName *r)
1007 {
1008         const char * const attrs[] = { NULL };
1009         struct ldb_context *sam_ctx;
1010         struct ldb_message **res;
1011         struct ldb_dn *domain_dn;
1012         int ret;
1013         const char *dcname;
1014
1015         /*
1016          * [MS-NRPC] 3.5.5.3.4 NetrGetDCName says
1017          * that the domainname needs to be a valid netbios domain
1018          * name, if it is not NULL.
1019          */
1020         if (r->in.domainname) {
1021                 const char *dot = strchr(r->in.domainname, '.');
1022                 size_t len = strlen(r->in.domainname);
1023
1024                 if (dot || len > 15) {
1025                         return WERR_DCNOTFOUND;
1026                 }
1027
1028                 /*
1029                  * TODO: Should we also varify that only valid
1030                  *       netbios name characters are used?
1031                  */
1032         }
1033
1034         sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx,
1035                                 dce_call->conn->dce_ctx->lp_ctx,
1036                                 dce_call->conn->auth_state.session_info, 0);
1037         if (sam_ctx == NULL) {
1038                 return WERR_DS_UNAVAILABLE;
1039         }
1040
1041         domain_dn = samdb_domain_to_dn(sam_ctx, mem_ctx,
1042                                        r->in.domainname);
1043         if (domain_dn == NULL) {
1044                 return WERR_NO_SUCH_DOMAIN;
1045         }
1046
1047         ret = gendb_search_dn(sam_ctx, mem_ctx,
1048                               domain_dn, &res, attrs);
1049         if (ret != 1) {
1050                 return WERR_NO_SUCH_DOMAIN;
1051         }
1052
1053         /* TODO: - return real IP address
1054          *       - check all r->in.* parameters (server_unc is ignored by w2k3!)
1055          */
1056         dcname = talloc_asprintf(mem_ctx, "\\\\%s",
1057                                  lpcfg_netbios_name(dce_call->conn->dce_ctx->lp_ctx));
1058         W_ERROR_HAVE_NO_MEMORY(dcname);
1059
1060         *r->out.dcname = dcname;
1061         return WERR_OK;
1062 }
1063
1064
1065 /*
1066   netr_LogonControl2Ex
1067 */
1068 static WERROR dcesrv_netr_LogonControl2Ex(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1069                        struct netr_LogonControl2Ex *r)
1070 {
1071         return WERR_NOT_SUPPORTED;
1072 }
1073
1074
1075 /*
1076   netr_LogonControl
1077 */
1078 static WERROR dcesrv_netr_LogonControl(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1079                        struct netr_LogonControl *r)
1080 {
1081         struct netr_LogonControl2Ex r2;
1082         WERROR werr;
1083
1084         if (r->in.level == 0x00000001) {
1085                 ZERO_STRUCT(r2);
1086
1087                 r2.in.logon_server = r->in.logon_server;
1088                 r2.in.function_code = r->in.function_code;
1089                 r2.in.level = r->in.level;
1090                 r2.in.data = NULL;
1091                 r2.out.query = r->out.query;
1092
1093                 werr = dcesrv_netr_LogonControl2Ex(dce_call, mem_ctx, &r2);
1094         } else if (r->in.level == 0x00000002) {
1095                 werr = WERR_NOT_SUPPORTED;
1096         } else {
1097                 werr = WERR_UNKNOWN_LEVEL;
1098         }
1099
1100         return werr;
1101 }
1102
1103
1104 /*
1105   netr_LogonControl2
1106 */
1107 static WERROR dcesrv_netr_LogonControl2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1108                        struct netr_LogonControl2 *r)
1109 {
1110         struct netr_LogonControl2Ex r2;
1111         WERROR werr;
1112
1113         ZERO_STRUCT(r2);
1114
1115         r2.in.logon_server = r->in.logon_server;
1116         r2.in.function_code = r->in.function_code;
1117         r2.in.level = r->in.level;
1118         r2.in.data = r->in.data;
1119         r2.out.query = r->out.query;
1120
1121         werr = dcesrv_netr_LogonControl2Ex(dce_call, mem_ctx, &r2);
1122
1123         return werr;
1124 }
1125
1126 static WERROR fill_trusted_domains_array(TALLOC_CTX *mem_ctx,
1127                                          struct ldb_context *sam_ctx,
1128                                          struct netr_DomainTrustList *trusts,
1129                                          uint32_t trust_flags);
1130
1131 /*
1132   netr_GetAnyDCName
1133 */
1134 static WERROR dcesrv_netr_GetAnyDCName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1135                        struct netr_GetAnyDCName *r)
1136 {
1137         struct netr_DomainTrustList *trusts;
1138         struct ldb_context *sam_ctx;
1139         struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1140         uint32_t i;
1141         WERROR werr;
1142
1143         *r->out.dcname = NULL;
1144
1145         if ((r->in.domainname == NULL) || (r->in.domainname[0] == '\0')) {
1146                 /* if the domainname parameter wasn't set assume our domain */
1147                 r->in.domainname = lpcfg_workgroup(lp_ctx);
1148         }
1149
1150         sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1151                                 dce_call->conn->auth_state.session_info, 0);
1152         if (sam_ctx == NULL) {
1153                 return WERR_DS_UNAVAILABLE;
1154         }
1155
1156         if (strcasecmp(r->in.domainname, lpcfg_workgroup(lp_ctx)) == 0) {
1157                 /* well we asked for a DC of our own domain */
1158                 if (samdb_is_pdc(sam_ctx)) {
1159                         /* we are the PDC of the specified domain */
1160                         return WERR_NO_SUCH_DOMAIN;
1161                 }
1162
1163                 *r->out.dcname = talloc_asprintf(mem_ctx, "\\%s",
1164                                                 lpcfg_netbios_name(lp_ctx));
1165                 W_ERROR_HAVE_NO_MEMORY(*r->out.dcname);
1166
1167                 return WERR_OK;
1168         }
1169
1170         /* Okay, now we have to consider the trusted domains */
1171
1172         trusts = talloc_zero(mem_ctx, struct netr_DomainTrustList);
1173         W_ERROR_HAVE_NO_MEMORY(trusts);
1174
1175         trusts->count = 0;
1176
1177         werr = fill_trusted_domains_array(mem_ctx, sam_ctx, trusts,
1178                                           NETR_TRUST_FLAG_INBOUND
1179                                           | NETR_TRUST_FLAG_OUTBOUND);
1180         W_ERROR_NOT_OK_RETURN(werr);
1181
1182         for (i = 0; i < trusts->count; i++) {
1183                 if (strcasecmp(r->in.domainname, trusts->array[i].netbios_name) == 0) {
1184                         /* FIXME: Here we need to find a DC for the specified
1185                          * trusted domain. */
1186
1187                         /* return WERR_OK; */
1188                         return WERR_NO_SUCH_DOMAIN;
1189                 }
1190         }
1191
1192         return WERR_NO_SUCH_DOMAIN;
1193 }
1194
1195
1196 /*
1197   netr_DatabaseRedo
1198 */
1199 static NTSTATUS dcesrv_netr_DatabaseRedo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1200                        struct netr_DatabaseRedo *r)
1201 {
1202         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1203 }
1204
1205
1206 /*
1207   netr_NetrEnumerateTrustedDomains
1208 */
1209 static NTSTATUS dcesrv_netr_NetrEnumerateTrustedDomains(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1210                        struct netr_NetrEnumerateTrustedDomains *r)
1211 {
1212         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1213 }
1214
1215
1216 /*
1217   netr_LogonGetCapabilities
1218 */
1219 static NTSTATUS dcesrv_netr_LogonGetCapabilities(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1220                        struct netr_LogonGetCapabilities *r)
1221 {
1222         struct netlogon_creds_CredentialState *creds;
1223         NTSTATUS status;
1224
1225         status = dcesrv_netr_creds_server_step_check(dce_call,
1226                                                      mem_ctx,
1227                                                      r->in.computer_name,
1228                                                      r->in.credential,
1229                                                      r->out.return_authenticator,
1230                                                      &creds);
1231         if (!NT_STATUS_IS_OK(status)) {
1232                 DEBUG(0,(__location__ " Bad credentials - error\n"));
1233         }
1234         NT_STATUS_NOT_OK_RETURN(status);
1235
1236         if (r->in.query_level != 1) {
1237                 return NT_STATUS_NOT_SUPPORTED;
1238         }
1239
1240         r->out.capabilities->server_capabilities = creds->negotiate_flags;
1241
1242         return NT_STATUS_OK;
1243 }
1244
1245
1246 /*
1247   netr_NETRLOGONSETSERVICEBITS
1248 */
1249 static WERROR dcesrv_netr_NETRLOGONSETSERVICEBITS(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1250                        struct netr_NETRLOGONSETSERVICEBITS *r)
1251 {
1252         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1253 }
1254
1255
1256 /*
1257   netr_LogonGetTrustRid
1258 */
1259 static WERROR dcesrv_netr_LogonGetTrustRid(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1260                        struct netr_LogonGetTrustRid *r)
1261 {
1262         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1263 }
1264
1265
1266 /*
1267   netr_NETRLOGONCOMPUTESERVERDIGEST
1268 */
1269 static WERROR dcesrv_netr_NETRLOGONCOMPUTESERVERDIGEST(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1270                        struct netr_NETRLOGONCOMPUTESERVERDIGEST *r)
1271 {
1272         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1273 }
1274
1275
1276 /*
1277   netr_NETRLOGONCOMPUTECLIENTDIGEST
1278 */
1279 static WERROR dcesrv_netr_NETRLOGONCOMPUTECLIENTDIGEST(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1280                        struct netr_NETRLOGONCOMPUTECLIENTDIGEST *r)
1281 {
1282         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1283 }
1284
1285
1286
1287 /*
1288   netr_DsRGetSiteName
1289 */
1290 static WERROR dcesrv_netr_DsRGetSiteName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1291                                   struct netr_DsRGetSiteName *r)
1292 {
1293         struct ldb_context *sam_ctx;
1294         struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1295
1296         sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1297                                 dce_call->conn->auth_state.session_info, 0);
1298         if (sam_ctx == NULL) {
1299                 return WERR_DS_UNAVAILABLE;
1300         }
1301
1302         /*
1303          * We assume to be a DC when we get called over NETLOGON. Hence we
1304          * get our site name always by using "samdb_server_site_name()"
1305          * and not "samdb_client_site_name()".
1306          */
1307         *r->out.site = samdb_server_site_name(sam_ctx, mem_ctx);
1308         W_ERROR_HAVE_NO_MEMORY(*r->out.site);
1309
1310         return WERR_OK;
1311 }
1312
1313
1314 /*
1315   fill in a netr_OneDomainInfo from a ldb search result
1316 */
1317 static NTSTATUS fill_one_domain_info(TALLOC_CTX *mem_ctx,
1318                                      struct loadparm_context *lp_ctx,
1319                                      struct ldb_context *sam_ctx,
1320                                      struct ldb_message *res,
1321                                      struct netr_OneDomainInfo *info,
1322                                      bool is_local, bool is_trust_list)
1323 {
1324         ZERO_STRUCTP(info);
1325
1326         if (is_trust_list) {
1327                 /* w2k8 only fills this on trusted domains */
1328                 info->trust_extension.info = talloc_zero(mem_ctx, struct netr_trust_extension);
1329                 info->trust_extension.length = 16;
1330                 info->trust_extension.info->flags =
1331                         NETR_TRUST_FLAG_TREEROOT |
1332                         NETR_TRUST_FLAG_IN_FOREST |
1333                         NETR_TRUST_FLAG_PRIMARY |
1334                         NETR_TRUST_FLAG_NATIVE;
1335
1336                 info->trust_extension.info->parent_index = 0; /* should be index into array
1337                                                                  of parent */
1338                 info->trust_extension.info->trust_type = LSA_TRUST_TYPE_UPLEVEL; /* should be based on ldb search for trusts */
1339                 info->trust_extension.info->trust_attributes = 0; /*    TODO: base on ldb search? */
1340         }
1341
1342         if (is_trust_list) {
1343                 /* MS-NRPC 3.5.4.3.9 - must be set to NULL for trust list */
1344                 info->dns_forestname.string = NULL;
1345         } else {
1346                 info->dns_forestname.string = samdb_forest_name(sam_ctx, mem_ctx);
1347                 NT_STATUS_HAVE_NO_MEMORY(info->dns_forestname.string);
1348                 info->dns_forestname.string = talloc_asprintf(mem_ctx, "%s.", info->dns_forestname.string);
1349                 NT_STATUS_HAVE_NO_MEMORY(info->dns_forestname.string);
1350         }
1351
1352         if (is_local) {
1353                 info->domainname.string = lpcfg_workgroup(lp_ctx);
1354                 info->dns_domainname.string = lpcfg_dnsdomain(lp_ctx);
1355                 info->domain_guid = samdb_result_guid(res, "objectGUID");
1356                 info->domain_sid = samdb_result_dom_sid(mem_ctx, res, "objectSid");
1357         } else {
1358                 info->domainname.string = ldb_msg_find_attr_as_string(res, "flatName", NULL);
1359                 info->dns_domainname.string = ldb_msg_find_attr_as_string(res, "trustPartner", NULL);
1360                 info->domain_guid = samdb_result_guid(res, "objectGUID");
1361                 info->domain_sid = samdb_result_dom_sid(mem_ctx, res, "securityIdentifier");
1362         }
1363         if (!is_trust_list) {
1364                 info->dns_domainname.string = talloc_asprintf(mem_ctx, "%s.", info->dns_domainname.string);
1365         }
1366
1367         return NT_STATUS_OK;
1368 }
1369
1370 /*
1371   netr_LogonGetDomainInfo
1372   this is called as part of the ADS domain logon procedure.
1373
1374   It has an important role in convaying details about the client, such
1375   as Operating System, Version, Service Pack etc.
1376 */
1377 static NTSTATUS dcesrv_netr_LogonGetDomainInfo(struct dcesrv_call_state *dce_call,
1378         TALLOC_CTX *mem_ctx, struct netr_LogonGetDomainInfo *r)
1379 {
1380         struct netlogon_creds_CredentialState *creds;
1381         const char * const attrs[] = { "objectSid", "objectGUID", "flatName",
1382                 "securityIdentifier", "trustPartner", NULL };
1383         const char * const attrs2[] = { "sAMAccountName", "dNSHostName",
1384                 "msDS-SupportedEncryptionTypes", NULL };
1385         const char *sam_account_name, *old_dns_hostname, *prefix1, *prefix2;
1386         struct ldb_context *sam_ctx;
1387         struct ldb_message **res1, **res2, **res3, *new_msg;
1388         struct ldb_dn *workstation_dn;
1389         struct netr_DomainInformation *domain_info;
1390         struct netr_LsaPolicyInformation *lsa_policy_info;
1391         uint32_t default_supported_enc_types = 0xFFFFFFFF;
1392         bool update_dns_hostname = true;
1393         int ret, ret3, i;
1394         NTSTATUS status;
1395
1396         status = dcesrv_netr_creds_server_step_check(dce_call,
1397                                                      mem_ctx,
1398                                                      r->in.computer_name,
1399                                                      r->in.credential,
1400                                                      r->out.return_authenticator,
1401                                                      &creds);
1402         if (!NT_STATUS_IS_OK(status)) {
1403                 DEBUG(0,(__location__ " Bad credentials - error\n"));
1404         }
1405         NT_STATUS_NOT_OK_RETURN(status);
1406
1407         sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx,
1408                                 dce_call->conn->dce_ctx->lp_ctx,
1409                                 system_session(dce_call->conn->dce_ctx->lp_ctx), 0);
1410         if (sam_ctx == NULL) {
1411                 return NT_STATUS_INVALID_SYSTEM_SERVICE;
1412         }
1413
1414         switch (r->in.level) {
1415         case 1: /* Domain information */
1416
1417                 if (r->in.query->workstation_info == NULL) {
1418                         return NT_STATUS_INVALID_PARAMETER;
1419                 }
1420
1421                 /* Prepares the workstation DN */
1422                 workstation_dn = ldb_dn_new_fmt(mem_ctx, sam_ctx, "<SID=%s>",
1423                                                 dom_sid_string(mem_ctx, creds->sid));
1424                 NT_STATUS_HAVE_NO_MEMORY(workstation_dn);
1425
1426                 /* Lookup for attributes in workstation object */
1427                 ret = gendb_search_dn(sam_ctx, mem_ctx, workstation_dn, &res1,
1428                                       attrs2);
1429                 if (ret != 1) {
1430                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
1431                 }
1432
1433                 /* Gets the sam account name which is checked against the DNS
1434                  * hostname parameter. */
1435                 sam_account_name = ldb_msg_find_attr_as_string(res1[0],
1436                                                                "sAMAccountName",
1437                                                                NULL);
1438                 if (sam_account_name == NULL) {
1439                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
1440                 }
1441
1442                 /*
1443                  * Checks that the sam account name without a possible "$"
1444                  * matches as prefix with the DNS hostname in the workstation
1445                  * info structure.
1446                  */
1447                 prefix1 = talloc_strndup(mem_ctx, sam_account_name,
1448                                          strcspn(sam_account_name, "$"));
1449                 NT_STATUS_HAVE_NO_MEMORY(prefix1);
1450                 if (r->in.query->workstation_info->dns_hostname != NULL) {
1451                         prefix2 = talloc_strndup(mem_ctx,
1452                                                  r->in.query->workstation_info->dns_hostname,
1453                                                  strcspn(r->in.query->workstation_info->dns_hostname, "."));
1454                         NT_STATUS_HAVE_NO_MEMORY(prefix2);
1455
1456                         if (strcasecmp(prefix1, prefix2) != 0) {
1457                                 update_dns_hostname = false;
1458                         }
1459                 } else {
1460                         update_dns_hostname = false;
1461                 }
1462
1463                 /* Gets the old DNS hostname */
1464                 old_dns_hostname = ldb_msg_find_attr_as_string(res1[0],
1465                                                                "dNSHostName",
1466                                                                NULL);
1467
1468                 /*
1469                  * Updates the DNS hostname when the client wishes that the
1470                  * server should handle this for him
1471                  * ("NETR_WS_FLAG_HANDLES_SPN_UPDATE" not set). And this is
1472                  * obviously only checked when we do already have a
1473                  * "dNSHostName".
1474                  * See MS-NRPC section 3.5.4.3.9
1475                  */
1476                 if ((old_dns_hostname != NULL) &&
1477                     (r->in.query->workstation_info->workstation_flags
1478                     & NETR_WS_FLAG_HANDLES_SPN_UPDATE) != 0) {
1479                         update_dns_hostname = false;
1480                 }
1481
1482                 /* Gets host information and put them into our directory */
1483
1484                 new_msg = ldb_msg_new(mem_ctx);
1485                 NT_STATUS_HAVE_NO_MEMORY(new_msg);
1486
1487                 new_msg->dn = workstation_dn;
1488
1489                 /* Sets the OS name */
1490
1491                 if (r->in.query->workstation_info->os_name.string == NULL) {
1492                         return NT_STATUS_INVALID_PARAMETER;
1493                 }
1494
1495                 ret = ldb_msg_add_string(new_msg, "operatingSystem",
1496                                          r->in.query->workstation_info->os_name.string);
1497                 if (ret != LDB_SUCCESS) {
1498                         return NT_STATUS_NO_MEMORY;
1499                 }
1500
1501                 /*
1502                  * Sets information from "os_version". On an empty structure
1503                  * the values are cleared.
1504                  */
1505                 if (r->in.query->workstation_info->os_version.os != NULL) {
1506                         struct netr_OsVersionInfoEx *os_version;
1507                         const char *os_version_str;
1508
1509                         os_version = &r->in.query->workstation_info->os_version.os->os;
1510
1511                         if (os_version->CSDVersion == NULL) {
1512                                 return NT_STATUS_INVALID_PARAMETER;
1513                         }
1514
1515                         os_version_str = talloc_asprintf(new_msg, "%u.%u (%u)",
1516                                                          os_version->MajorVersion,
1517                                                          os_version->MinorVersion,
1518                                                          os_version->BuildNumber);
1519                         NT_STATUS_HAVE_NO_MEMORY(os_version_str);
1520
1521                         ret = ldb_msg_add_string(new_msg,
1522                                                  "operatingSystemServicePack",
1523                                                  os_version->CSDVersion);
1524                         if (ret != LDB_SUCCESS) {
1525                                 return NT_STATUS_NO_MEMORY;
1526                         }
1527
1528                         ret = ldb_msg_add_string(new_msg,
1529                                                  "operatingSystemVersion",
1530                                                  os_version_str);
1531                         if (ret != LDB_SUCCESS) {
1532                                 return NT_STATUS_NO_MEMORY;
1533                         }
1534                 } else {
1535                         ret = samdb_msg_add_delete(sam_ctx, mem_ctx, new_msg,
1536                                                    "operatingSystemServicePack");
1537                         if (ret != LDB_SUCCESS) {
1538                                 return NT_STATUS_NO_MEMORY;
1539                         }
1540
1541                         ret = samdb_msg_add_delete(sam_ctx, mem_ctx, new_msg,
1542                                                    "operatingSystemVersion");
1543                         if (ret != LDB_SUCCESS) {
1544                                 return NT_STATUS_NO_MEMORY;
1545                         }
1546                 }
1547
1548                 /*
1549                  * If the boolean "update_dns_hostname" remained true, then we
1550                  * are fine to start the update.
1551                  */
1552                 if (update_dns_hostname) {
1553                         ret = ldb_msg_add_string(new_msg,
1554                                                  "dNSHostname",
1555                                                  r->in.query->workstation_info->dns_hostname);
1556                         if (ret != LDB_SUCCESS) {
1557                                 return NT_STATUS_NO_MEMORY;
1558                         }
1559
1560                         /* This manual "servicePrincipalName" generation is
1561                          * still needed! Since the update in the samldb LDB
1562                          * module does only work if the entries already exist
1563                          * which isn't always the case. */
1564                         ret = ldb_msg_add_string(new_msg,
1565                                                  "servicePrincipalName",
1566                                                  talloc_asprintf(new_msg, "HOST/%s",
1567                                                  r->in.computer_name));
1568                         if (ret != LDB_SUCCESS) {
1569                                 return NT_STATUS_NO_MEMORY;
1570                         }
1571
1572                         ret = ldb_msg_add_string(new_msg,
1573                                                  "servicePrincipalName",
1574                                                  talloc_asprintf(new_msg, "HOST/%s",
1575                                                  r->in.query->workstation_info->dns_hostname));
1576                         if (ret != LDB_SUCCESS) {
1577                                 return NT_STATUS_NO_MEMORY;
1578                         }
1579                 }
1580
1581                 if (dsdb_replace(sam_ctx, new_msg, 0) != LDB_SUCCESS) {
1582                         DEBUG(3,("Impossible to update samdb: %s\n",
1583                                 ldb_errstring(sam_ctx)));
1584                 }
1585
1586                 talloc_free(new_msg);
1587
1588                 /* Writes back the domain information */
1589
1590                 /* We need to do two searches. The first will pull our primary
1591                    domain and the second will pull any trusted domains. Our
1592                    primary domain is also a "trusted" domain, so we need to
1593                    put the primary domain into the lists of returned trusts as
1594                    well. */
1595                 ret = gendb_search_dn(sam_ctx, mem_ctx, ldb_get_default_basedn(sam_ctx),
1596                         &res2, attrs);
1597                 if (ret != 1) {
1598                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
1599                 }
1600
1601                 ret3 = gendb_search(sam_ctx, mem_ctx, NULL, &res3, attrs,
1602                         "(objectClass=trustedDomain)");
1603                 if (ret3 == -1) {
1604                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
1605                 }
1606
1607                 domain_info = talloc(mem_ctx, struct netr_DomainInformation);
1608                 NT_STATUS_HAVE_NO_MEMORY(domain_info);
1609
1610                 ZERO_STRUCTP(domain_info);
1611
1612                 /* Informations about the local and trusted domains */
1613
1614                 status = fill_one_domain_info(mem_ctx,
1615                         dce_call->conn->dce_ctx->lp_ctx,
1616                         sam_ctx, res2[0], &domain_info->primary_domain,
1617                         true, false);
1618                 NT_STATUS_NOT_OK_RETURN(status);
1619
1620                 domain_info->trusted_domain_count = ret3 + 1;
1621                 domain_info->trusted_domains = talloc_array(mem_ctx,
1622                         struct netr_OneDomainInfo,
1623                         domain_info->trusted_domain_count);
1624                 NT_STATUS_HAVE_NO_MEMORY(domain_info->trusted_domains);
1625
1626                 for (i=0;i<ret3;i++) {
1627                         status = fill_one_domain_info(mem_ctx,
1628                                 dce_call->conn->dce_ctx->lp_ctx,
1629                                 sam_ctx, res3[i],
1630                                 &domain_info->trusted_domains[i],
1631                                 false, true);
1632                         NT_STATUS_NOT_OK_RETURN(status);
1633                 }
1634
1635                 status = fill_one_domain_info(mem_ctx,
1636                         dce_call->conn->dce_ctx->lp_ctx, sam_ctx, res2[0],
1637                         &domain_info->trusted_domains[i], true, true);
1638                 NT_STATUS_NOT_OK_RETURN(status);
1639
1640                 /* Sets the supported encryption types */
1641                 domain_info->supported_enc_types = ldb_msg_find_attr_as_uint(res1[0],
1642                         "msDS-SupportedEncryptionTypes",
1643                         default_supported_enc_types);
1644
1645                 /* Other host domain information */
1646
1647                 lsa_policy_info = talloc(mem_ctx,
1648                         struct netr_LsaPolicyInformation);
1649                 NT_STATUS_HAVE_NO_MEMORY(lsa_policy_info);
1650                 ZERO_STRUCTP(lsa_policy_info);
1651
1652                 domain_info->lsa_policy = *lsa_policy_info;
1653
1654                 /* The DNS hostname is only returned back when there is a chance
1655                  * for a change. */
1656                 if ((r->in.query->workstation_info->workstation_flags
1657                     & NETR_WS_FLAG_HANDLES_SPN_UPDATE) != 0) {
1658                         domain_info->dns_hostname.string = old_dns_hostname;
1659                 } else {
1660                         domain_info->dns_hostname.string = NULL;
1661                 }
1662
1663                 domain_info->workstation_flags =
1664                         r->in.query->workstation_info->workstation_flags & (
1665                         NETR_WS_FLAG_HANDLES_SPN_UPDATE | NETR_WS_FLAG_HANDLES_INBOUND_TRUSTS);
1666
1667                 r->out.info->domain_info = domain_info;
1668         break;
1669         case 2: /* LSA policy information - not used at the moment */
1670                 lsa_policy_info = talloc(mem_ctx,
1671                         struct netr_LsaPolicyInformation);
1672                 NT_STATUS_HAVE_NO_MEMORY(lsa_policy_info);
1673                 ZERO_STRUCTP(lsa_policy_info);
1674
1675                 r->out.info->lsa_policy_info = lsa_policy_info;
1676         break;
1677         default:
1678                 return NT_STATUS_INVALID_LEVEL;
1679         break;
1680         }
1681
1682         return NT_STATUS_OK;
1683 }
1684
1685
1686 /*
1687   netr_ServerPasswordGet
1688 */
1689 static WERROR dcesrv_netr_ServerPasswordGet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1690                        struct netr_ServerPasswordGet *r)
1691 {
1692         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1693 }
1694
1695
1696 /*
1697   netr_NETRLOGONSENDTOSAM
1698 */
1699 static WERROR dcesrv_netr_NETRLOGONSENDTOSAM(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1700                        struct netr_NETRLOGONSENDTOSAM *r)
1701 {
1702         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1703 }
1704
1705
1706 /*
1707   netr_DsRGetDCNameEx2
1708 */
1709 static WERROR dcesrv_netr_DsRGetDCNameEx2(struct dcesrv_call_state *dce_call,
1710                                           TALLOC_CTX *mem_ctx,
1711                                           struct netr_DsRGetDCNameEx2 *r)
1712 {
1713         struct ldb_context *sam_ctx;
1714         struct netr_DsRGetDCNameInfo *info;
1715         struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1716         const struct tsocket_address *remote_address;
1717         char *addr = NULL;
1718         const char *server_site_name;
1719         char *guid_str;
1720         struct netlogon_samlogon_response response;
1721         NTSTATUS status;
1722         const char *dc_name = NULL;
1723         const char *domain_name = NULL;
1724         struct interface *ifaces;
1725         const char *pdc_ip;
1726
1727         ZERO_STRUCTP(r->out.info);
1728
1729         sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1730                                 dce_call->conn->auth_state.session_info, 0);
1731         if (sam_ctx == NULL) {
1732                 return WERR_DS_UNAVAILABLE;
1733         }
1734
1735         remote_address = dcesrv_connection_get_remote_address(dce_call->conn);
1736         if (tsocket_address_is_inet(remote_address, "ip")) {
1737                 addr = tsocket_address_inet_addr_string(remote_address, mem_ctx);
1738                 W_ERROR_HAVE_NO_MEMORY(addr);
1739         }
1740
1741         /* "server_unc" is ignored by w2k3 */
1742
1743         if (r->in.flags & ~(DSGETDC_VALID_FLAGS)) {
1744                 return WERR_INVALID_FLAGS;
1745         }
1746
1747         if (r->in.flags & DS_GC_SERVER_REQUIRED &&
1748             r->in.flags & DS_PDC_REQUIRED &&
1749             r->in.flags & DS_KDC_REQUIRED) {
1750                 return WERR_INVALID_FLAGS;
1751         }
1752         if (r->in.flags & DS_IS_FLAT_NAME &&
1753             r->in.flags & DS_IS_DNS_NAME) {
1754                 return WERR_INVALID_FLAGS;
1755         }
1756         if (r->in.flags & DS_RETURN_DNS_NAME &&
1757             r->in.flags & DS_RETURN_FLAT_NAME) {
1758                 return WERR_INVALID_FLAGS;
1759         }
1760         if (r->in.flags & DS_DIRECTORY_SERVICE_REQUIRED &&
1761             r->in.flags & DS_DIRECTORY_SERVICE_6_REQUIRED) {
1762                 return WERR_INVALID_FLAGS;
1763         }
1764
1765         if (r->in.flags & DS_GOOD_TIMESERV_PREFERRED &&
1766             r->in.flags &
1767             (DS_DIRECTORY_SERVICE_REQUIRED |
1768              DS_DIRECTORY_SERVICE_PREFERRED |
1769              DS_GC_SERVER_REQUIRED |
1770              DS_PDC_REQUIRED |
1771              DS_KDC_REQUIRED)) {
1772                 return WERR_INVALID_FLAGS;
1773         }
1774
1775         if (r->in.flags & DS_TRY_NEXTCLOSEST_SITE &&
1776             r->in.site_name) {
1777                 return WERR_INVALID_FLAGS;
1778         }
1779
1780         /* Proof server site parameter "site_name" if it was specified */
1781         server_site_name = samdb_server_site_name(sam_ctx, mem_ctx);
1782         W_ERROR_HAVE_NO_MEMORY(server_site_name);
1783         if ((r->in.site_name != NULL) && (strcasecmp(r->in.site_name,
1784                                                      server_site_name) != 0)) {
1785                 return WERR_NO_SUCH_DOMAIN;
1786         }
1787
1788         guid_str = r->in.domain_guid != NULL ?
1789                  GUID_string(mem_ctx, r->in.domain_guid) : NULL;
1790
1791         status = fill_netlogon_samlogon_response(sam_ctx, mem_ctx,
1792                                                  r->in.domain_name,
1793                                                  r->in.domain_name,
1794                                                  NULL, guid_str,
1795                                                  r->in.client_account,
1796                                                  r->in.mask, addr,
1797                                                  NETLOGON_NT_VERSION_5EX_WITH_IP,
1798                                                  lp_ctx, &response, true);
1799         if (!NT_STATUS_IS_OK(status)) {
1800                 return ntstatus_to_werror(status);
1801         }
1802
1803         /*
1804          * According to MS-NRPC 2.2.1.2.1 we should set the "DS_DNS_FOREST_ROOT"
1805          * (O) flag when the returned forest name is in DNS format. This is here
1806          * always the case (see below).
1807          */
1808         response.data.nt5_ex.server_type |= DS_DNS_FOREST_ROOT;
1809
1810         if (r->in.flags & DS_RETURN_DNS_NAME) {
1811                 dc_name = response.data.nt5_ex.pdc_dns_name;
1812                 domain_name = response.data.nt5_ex.dns_domain;
1813                 /*
1814                  * According to MS-NRPC 2.2.1.2.1 we should set the
1815                  * "DS_DNS_CONTROLLER" (M) and "DS_DNS_DOMAIN" (N) flags when
1816                  * the returned information is in DNS form.
1817                  */
1818                 response.data.nt5_ex.server_type |=
1819                         DS_DNS_CONTROLLER | DS_DNS_DOMAIN;
1820         } else if (r->in.flags & DS_RETURN_FLAT_NAME) {
1821                 dc_name = response.data.nt5_ex.pdc_name;
1822                 domain_name = response.data.nt5_ex.domain_name;
1823         } else {
1824
1825                 /*
1826                  * TODO: autodetect what we need to return
1827                  * based on the given arguments
1828                  */
1829                 dc_name = response.data.nt5_ex.pdc_name;
1830                 domain_name = response.data.nt5_ex.domain_name;
1831         }
1832
1833         if (!dc_name || !dc_name[0]) {
1834                 return WERR_NO_SUCH_DOMAIN;
1835         }
1836
1837         if (!domain_name || !domain_name[0]) {
1838                 return WERR_NO_SUCH_DOMAIN;
1839         }
1840
1841         info = talloc(mem_ctx, struct netr_DsRGetDCNameInfo);
1842         W_ERROR_HAVE_NO_MEMORY(info);
1843         info->dc_unc = talloc_asprintf(mem_ctx, "%s%s",
1844                         dc_name[0] == '\\'? "\\\\":"",
1845                         talloc_strdup(mem_ctx, dc_name));
1846         W_ERROR_HAVE_NO_MEMORY(info->dc_unc);
1847
1848         load_interface_list(mem_ctx, lp_ctx, &ifaces);
1849         pdc_ip = iface_list_best_ip(ifaces, addr);
1850         if (pdc_ip == NULL) {
1851                 pdc_ip = "127.0.0.1";
1852         }
1853         info->dc_address = talloc_asprintf(mem_ctx, "\\\\%s", pdc_ip);
1854         W_ERROR_HAVE_NO_MEMORY(info->dc_address);
1855         info->dc_address_type  = DS_ADDRESS_TYPE_INET;
1856         info->domain_guid      = response.data.nt5_ex.domain_uuid;
1857         info->domain_name      = domain_name;
1858         info->forest_name      = response.data.nt5_ex.forest;
1859         info->dc_flags         = response.data.nt5_ex.server_type;
1860         if (r->in.flags & DS_RETURN_DNS_NAME) {
1861                 /* As MS-NRPC.pdf in 2.2.1.2.1 the DS_DNS_CONTROLLER flag should be
1862                  * returned if we are returning info->dc_unc containing a FQDN.
1863                  * This attribute is called DomainControllerName in the specs,
1864                  * it seems that we decide to return FQDN or netbios depending on
1865                  * DS_RETURN_DNS_NAME.
1866                  */
1867                 info->dc_flags |= DS_DNS_CONTROLLER;
1868         }
1869         info->dc_site_name     = response.data.nt5_ex.server_site;
1870         info->client_site_name = response.data.nt5_ex.client_site;
1871
1872         *r->out.info = info;
1873
1874         return WERR_OK;
1875 }
1876
1877 /*
1878   netr_DsRGetDCNameEx
1879 */
1880 static WERROR dcesrv_netr_DsRGetDCNameEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1881                                   struct netr_DsRGetDCNameEx *r)
1882 {
1883         struct netr_DsRGetDCNameEx2 r2;
1884         WERROR werr;
1885
1886         ZERO_STRUCT(r2);
1887
1888         r2.in.server_unc = r->in.server_unc;
1889         r2.in.client_account = NULL;
1890         r2.in.mask = 0;
1891         r2.in.domain_guid = r->in.domain_guid;
1892         r2.in.domain_name = r->in.domain_name;
1893         r2.in.site_name = r->in.site_name;
1894         r2.in.flags = r->in.flags;
1895         r2.out.info = r->out.info;
1896
1897         werr = dcesrv_netr_DsRGetDCNameEx2(dce_call, mem_ctx, &r2);
1898
1899         return werr;
1900 }
1901
1902 /*
1903   netr_DsRGetDCName
1904 */
1905 static WERROR dcesrv_netr_DsRGetDCName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1906                                 struct netr_DsRGetDCName *r)
1907 {
1908         struct netr_DsRGetDCNameEx2 r2;
1909         WERROR werr;
1910
1911         ZERO_STRUCT(r2);
1912
1913         r2.in.server_unc = r->in.server_unc;
1914         r2.in.client_account = NULL;
1915         r2.in.mask = 0;
1916         r2.in.domain_name = r->in.domain_name;
1917         r2.in.domain_guid = r->in.domain_guid;
1918
1919         r2.in.site_name = NULL; /* this is correct, we should ignore site GUID */
1920         r2.in.flags = r->in.flags;
1921         r2.out.info = r->out.info;
1922
1923         werr = dcesrv_netr_DsRGetDCNameEx2(dce_call, mem_ctx, &r2);
1924
1925         return werr;
1926 }
1927 /*
1928   netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN
1929 */
1930 static WERROR dcesrv_netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1931                        struct netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN *r)
1932 {
1933         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1934 }
1935
1936
1937 /*
1938   netr_NetrEnumerateTrustedDomainsEx
1939 */
1940 static WERROR dcesrv_netr_NetrEnumerateTrustedDomainsEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1941                        struct netr_NetrEnumerateTrustedDomainsEx *r)
1942 {
1943         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1944 }
1945
1946
1947 /*
1948   netr_DsRAddressToSitenamesExW
1949 */
1950 static WERROR dcesrv_netr_DsRAddressToSitenamesExW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1951                                                    struct netr_DsRAddressToSitenamesExW *r)
1952 {
1953         struct ldb_context *sam_ctx;
1954         struct netr_DsRAddressToSitenamesExWCtr *ctr;
1955         struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1956         sa_family_t sin_family;
1957         struct sockaddr_in *addr;
1958 #ifdef HAVE_IPV6
1959         struct sockaddr_in6 *addr6;
1960         char addr_str[INET6_ADDRSTRLEN];
1961 #else
1962         char addr_str[INET_ADDRSTRLEN];
1963 #endif
1964         char *subnet_name;
1965         const char *res;
1966         uint32_t i;
1967
1968         sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1969                                 dce_call->conn->auth_state.session_info, 0);
1970         if (sam_ctx == NULL) {
1971                 return WERR_DS_UNAVAILABLE;
1972         }
1973
1974         ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesExWCtr);
1975         W_ERROR_HAVE_NO_MEMORY(ctr);
1976
1977         *r->out.ctr = ctr;
1978
1979         ctr->count = r->in.count;
1980         ctr->sitename = talloc_array(ctr, struct lsa_String, ctr->count);
1981         W_ERROR_HAVE_NO_MEMORY(ctr->sitename);
1982         ctr->subnetname = talloc_array(ctr, struct lsa_String, ctr->count);
1983         W_ERROR_HAVE_NO_MEMORY(ctr->subnetname);
1984
1985         for (i=0; i<ctr->count; i++) {
1986                 ctr->sitename[i].string = NULL;
1987                 ctr->subnetname[i].string = NULL;
1988
1989                 if (r->in.addresses[i].size < sizeof(sa_family_t)) {
1990                         continue;
1991                 }
1992                 /* The first two byte of the buffer are reserved for the
1993                  * "sin_family" but for now only the first one is used. */
1994                 sin_family = r->in.addresses[i].buffer[0];
1995
1996                 switch (sin_family) {
1997                 case AF_INET:
1998                         if (r->in.addresses[i].size < sizeof(struct sockaddr_in)) {
1999                                 continue;
2000                         }
2001                         addr = (struct sockaddr_in *) r->in.addresses[i].buffer;
2002                         res = inet_ntop(AF_INET, &addr->sin_addr,
2003                                         addr_str, sizeof(addr_str));
2004                         break;
2005 #ifdef HAVE_IPV6
2006                 case AF_INET6:
2007                         if (r->in.addresses[i].size < sizeof(struct sockaddr_in6)) {
2008                                 continue;
2009                         }
2010                         addr6 = (struct sockaddr_in6 *) r->in.addresses[i].buffer;
2011                         res = inet_ntop(AF_INET6, &addr6->sin6_addr,
2012                                         addr_str, sizeof(addr_str));
2013                         break;
2014 #endif
2015                 default:
2016                         continue;
2017                 }
2018
2019                 if (res == NULL) {
2020                         continue;
2021                 }
2022
2023                 ctr->sitename[i].string   = samdb_client_site_name(sam_ctx,
2024                                                                    mem_ctx,
2025                                                                    addr_str,
2026                                                                    &subnet_name);
2027                 W_ERROR_HAVE_NO_MEMORY(ctr->sitename[i].string);
2028                 ctr->subnetname[i].string = subnet_name;
2029         }
2030
2031         return WERR_OK;
2032 }
2033
2034
2035 /*
2036   netr_DsRAddressToSitenamesW
2037 */
2038 static WERROR dcesrv_netr_DsRAddressToSitenamesW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2039                        struct netr_DsRAddressToSitenamesW *r)
2040 {
2041         struct netr_DsRAddressToSitenamesExW r2;
2042         struct netr_DsRAddressToSitenamesWCtr *ctr;
2043         uint32_t i;
2044         WERROR werr;
2045
2046         ZERO_STRUCT(r2);
2047
2048         r2.in.server_name = r->in.server_name;
2049         r2.in.count = r->in.count;
2050         r2.in.addresses = r->in.addresses;
2051
2052         r2.out.ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesExWCtr *);
2053         W_ERROR_HAVE_NO_MEMORY(r2.out.ctr);
2054
2055         ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesWCtr);
2056         W_ERROR_HAVE_NO_MEMORY(ctr);
2057
2058         *r->out.ctr = ctr;
2059
2060         ctr->count = r->in.count;
2061         ctr->sitename = talloc_array(ctr, struct lsa_String, ctr->count);
2062         W_ERROR_HAVE_NO_MEMORY(ctr->sitename);
2063
2064         werr = dcesrv_netr_DsRAddressToSitenamesExW(dce_call, mem_ctx, &r2);
2065
2066         for (i=0; i<ctr->count; i++) {
2067                 ctr->sitename[i].string   = (*r2.out.ctr)->sitename[i].string;
2068         }
2069
2070         return werr;
2071 }
2072
2073
2074 /*
2075   netr_DsrGetDcSiteCoverageW
2076 */
2077 static WERROR dcesrv_netr_DsrGetDcSiteCoverageW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2078                        struct netr_DsrGetDcSiteCoverageW *r)
2079 {
2080         struct ldb_context *sam_ctx;
2081         struct DcSitesCtr *ctr;
2082         struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2083
2084         sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2085                                 dce_call->conn->auth_state.session_info, 0);
2086         if (sam_ctx == NULL) {
2087                 return WERR_DS_UNAVAILABLE;
2088         }
2089
2090         ctr = talloc(mem_ctx, struct DcSitesCtr);
2091         W_ERROR_HAVE_NO_MEMORY(ctr);
2092
2093         *r->out.ctr = ctr;
2094
2095         /* For now only return our default site */
2096         ctr->num_sites = 1;
2097         ctr->sites = talloc_array(ctr, struct lsa_String, ctr->num_sites);
2098         W_ERROR_HAVE_NO_MEMORY(ctr->sites);
2099         ctr->sites[0].string = samdb_server_site_name(sam_ctx, mem_ctx);
2100         W_ERROR_HAVE_NO_MEMORY(ctr->sites[0].string);
2101
2102         return WERR_OK;
2103 }
2104
2105
2106 static WERROR fill_trusted_domains_array(TALLOC_CTX *mem_ctx,
2107                                          struct ldb_context *sam_ctx,
2108                                          struct netr_DomainTrustList *trusts,
2109                                          uint32_t trust_flags)
2110 {
2111         struct ldb_dn *system_dn;
2112         struct ldb_message **dom_res = NULL;
2113         const char *trust_attrs[] = { "flatname", "trustPartner",
2114                                       "securityIdentifier", "trustDirection",
2115                                       "trustType", "trustAttributes", NULL };
2116         uint32_t n;
2117         int i;
2118         int ret;
2119
2120         if (!(trust_flags & (NETR_TRUST_FLAG_INBOUND |
2121                              NETR_TRUST_FLAG_OUTBOUND))) {
2122                 return WERR_INVALID_FLAGS;
2123         }
2124
2125         system_dn = samdb_search_dn(sam_ctx, mem_ctx,
2126                                     ldb_get_default_basedn(sam_ctx),
2127                                     "(&(objectClass=container)(cn=System))");
2128         if (!system_dn) {
2129                 return WERR_GENERAL_FAILURE;
2130         }
2131
2132         ret = gendb_search(sam_ctx, mem_ctx, system_dn,
2133                            &dom_res, trust_attrs,
2134                            "(objectclass=trustedDomain)");
2135
2136         for (i = 0; i < ret; i++) {
2137                 unsigned int trust_dir;
2138                 uint32_t flags = 0;
2139
2140                 trust_dir = ldb_msg_find_attr_as_uint(dom_res[i],
2141                                                       "trustDirection", 0);
2142
2143                 if (trust_dir & LSA_TRUST_DIRECTION_INBOUND) {
2144                         flags |= NETR_TRUST_FLAG_INBOUND;
2145                 }
2146                 if (trust_dir & LSA_TRUST_DIRECTION_OUTBOUND) {
2147                         flags |= NETR_TRUST_FLAG_OUTBOUND;
2148                 }
2149
2150                 if (!(flags & trust_flags)) {
2151                         /* this trust direction was not requested */
2152                         continue;
2153                 }
2154
2155                 n = trusts->count;
2156                 trusts->array = talloc_realloc(trusts, trusts->array,
2157                                                struct netr_DomainTrust,
2158                                                n + 1);
2159                 W_ERROR_HAVE_NO_MEMORY(trusts->array);
2160
2161                 trusts->array[n].netbios_name = talloc_steal(trusts->array, ldb_msg_find_attr_as_string(dom_res[i], "flatname", NULL));
2162                 if (!trusts->array[n].netbios_name) {
2163                         DEBUG(0, ("DB Error, TrustedDomain entry (%s) "
2164                                   "without flatname\n", 
2165                                   ldb_dn_get_linearized(dom_res[i]->dn)));
2166                 }
2167
2168                 trusts->array[n].dns_name = talloc_steal(trusts->array, ldb_msg_find_attr_as_string(dom_res[i], "trustPartner", NULL));
2169
2170                 trusts->array[n].trust_flags = flags;
2171                 if ((trust_flags & NETR_TRUST_FLAG_IN_FOREST) &&
2172                     !(flags & NETR_TRUST_FLAG_TREEROOT)) {
2173                         /* TODO: find if we have parent in the list */
2174                         trusts->array[n].parent_index = 0;
2175                 }
2176
2177                 trusts->array[n].trust_type =
2178                                 ldb_msg_find_attr_as_uint(dom_res[i],
2179                                                   "trustType", 0);
2180                 trusts->array[n].trust_attributes =
2181                                 ldb_msg_find_attr_as_uint(dom_res[i],
2182                                                   "trustAttributes", 0);
2183
2184                 if ((trusts->array[n].trust_type == NETR_TRUST_TYPE_MIT) ||
2185                     (trusts->array[n].trust_type == NETR_TRUST_TYPE_DCE)) {
2186                         struct dom_sid zero_sid;
2187                         ZERO_STRUCT(zero_sid);
2188                         trusts->array[n].sid =
2189                                 dom_sid_dup(trusts, &zero_sid);
2190                 } else {
2191                         trusts->array[n].sid =
2192                                 samdb_result_dom_sid(trusts, dom_res[i],
2193                                                      "securityIdentifier");
2194                 }
2195                 trusts->array[n].guid = GUID_zero();
2196
2197                 trusts->count = n + 1;
2198         }
2199
2200         talloc_free(dom_res);
2201         return WERR_OK;
2202 }
2203
2204 /*
2205   netr_DsrEnumerateDomainTrusts
2206 */
2207 static WERROR dcesrv_netr_DsrEnumerateDomainTrusts(struct dcesrv_call_state *dce_call,
2208                                                    TALLOC_CTX *mem_ctx,
2209                                                    struct netr_DsrEnumerateDomainTrusts *r)
2210 {
2211         struct netr_DomainTrustList *trusts;
2212         struct ldb_context *sam_ctx;
2213         int ret;
2214         struct ldb_message **dom_res;
2215         const char * const dom_attrs[] = { "objectSid", "objectGUID", NULL };
2216         struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2217         const char *dnsdomain = lpcfg_dnsdomain(lp_ctx);
2218         const char *p;
2219         WERROR werr;
2220
2221         if (r->in.trust_flags & 0xFFFFFE00) {
2222                 return WERR_INVALID_FLAGS;
2223         }
2224
2225         /* TODO: turn to hard check once we are sure this is 100% correct */
2226         if (!r->in.server_name) {
2227                 DEBUG(3, ("Invalid domain! Expected name in domain [%s]. "
2228                           "But received NULL!\n", dnsdomain));
2229         } else {
2230                 p = strchr(r->in.server_name, '.');
2231                 if (!p) {
2232                         DEBUG(3, ("Invalid domain! Expected name in domain "
2233                                   "[%s]. But received [%s]!\n",
2234                                   dnsdomain, r->in.server_name));
2235                         p = r->in.server_name;
2236                 } else {
2237                         p++;
2238                 }
2239                 if (strcasecmp(p, dnsdomain)) {
2240                         DEBUG(3, ("Invalid domain! Expected name in domain "
2241                                   "[%s]. But received [%s]!\n",
2242                                   dnsdomain, r->in.server_name));
2243                 }
2244         }
2245
2246         trusts = talloc_zero(mem_ctx, struct netr_DomainTrustList);
2247         W_ERROR_HAVE_NO_MEMORY(trusts);
2248
2249         trusts->count = 0;
2250         r->out.trusts = trusts;
2251
2252         sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2253                                 dce_call->conn->auth_state.session_info, 0);
2254         if (sam_ctx == NULL) {
2255                 return WERR_GENERAL_FAILURE;
2256         }
2257
2258         if ((r->in.trust_flags & NETR_TRUST_FLAG_INBOUND) ||
2259             (r->in.trust_flags & NETR_TRUST_FLAG_OUTBOUND)) {
2260
2261                 werr = fill_trusted_domains_array(mem_ctx, sam_ctx,
2262                                                   trusts, r->in.trust_flags);
2263                 W_ERROR_NOT_OK_RETURN(werr);
2264         }
2265
2266         /* NOTE: we currently are always the root of the forest */
2267         if (r->in.trust_flags & NETR_TRUST_FLAG_IN_FOREST) {
2268                 uint32_t n = trusts->count;
2269
2270                 ret = gendb_search_dn(sam_ctx, mem_ctx, NULL,
2271                                       &dom_res, dom_attrs);
2272                 if (ret != 1) {
2273                         return WERR_GENERAL_FAILURE;
2274                 }
2275
2276                 trusts->count = n + 1;
2277                 trusts->array = talloc_realloc(trusts, trusts->array,
2278                                                struct netr_DomainTrust,
2279                                                trusts->count);
2280                 W_ERROR_HAVE_NO_MEMORY(trusts->array);
2281
2282                 trusts->array[n].netbios_name = lpcfg_workgroup(lp_ctx);
2283                 trusts->array[n].dns_name = lpcfg_dnsdomain(lp_ctx);
2284                 trusts->array[n].trust_flags =
2285                         NETR_TRUST_FLAG_NATIVE |
2286                         NETR_TRUST_FLAG_TREEROOT |
2287                         NETR_TRUST_FLAG_IN_FOREST |
2288                         NETR_TRUST_FLAG_PRIMARY;
2289                 /* we are always the root domain for now */
2290                 trusts->array[n].parent_index = 0;
2291                 trusts->array[n].trust_type = NETR_TRUST_TYPE_UPLEVEL;
2292                 trusts->array[n].trust_attributes = 0;
2293                 trusts->array[n].sid = samdb_result_dom_sid(mem_ctx,
2294                                                             dom_res[0],
2295                                                             "objectSid");
2296                 trusts->array[n].guid = samdb_result_guid(dom_res[0],
2297                                                           "objectGUID");
2298                 talloc_free(dom_res);
2299         }
2300
2301         return WERR_OK;
2302 }
2303
2304
2305 /*
2306   netr_DsrDeregisterDNSHostRecords
2307 */
2308 static WERROR dcesrv_netr_DsrDeregisterDNSHostRecords(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2309                        struct netr_DsrDeregisterDNSHostRecords *r)
2310 {
2311         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2312 }
2313
2314
2315 /*
2316   netr_ServerTrustPasswordsGet
2317 */
2318 static NTSTATUS dcesrv_netr_ServerTrustPasswordsGet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2319                        struct netr_ServerTrustPasswordsGet *r)
2320 {
2321         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2322 }
2323
2324
2325 static WERROR fill_forest_trust_array(TALLOC_CTX *mem_ctx,
2326                                       struct ldb_context *sam_ctx,
2327                                       struct loadparm_context *lp_ctx,
2328                                       struct lsa_ForestTrustInformation *info)
2329 {
2330         struct lsa_ForestTrustDomainInfo *domain_info;
2331         struct lsa_ForestTrustRecord *e;
2332         struct ldb_message **dom_res;
2333         const char * const dom_attrs[] = { "objectSid", NULL };
2334         int ret;
2335
2336         /* we need to provide 2 entries:
2337          * 1. the Root Forest name
2338          * 2. the Domain Information
2339          */
2340
2341         info->count = 2;
2342         info->entries = talloc_array(info, struct lsa_ForestTrustRecord *, 2);
2343         W_ERROR_HAVE_NO_MEMORY(info->entries);
2344
2345         /* Forest root info */
2346         e = talloc(info, struct lsa_ForestTrustRecord);
2347         W_ERROR_HAVE_NO_MEMORY(e);
2348
2349         e->flags = 0;
2350         e->type = LSA_FOREST_TRUST_TOP_LEVEL_NAME;
2351         e->time = 0; /* so far always 0 in trces. */
2352         e->forest_trust_data.top_level_name.string = samdb_forest_name(sam_ctx,
2353                                                                        mem_ctx);
2354         W_ERROR_HAVE_NO_MEMORY(e->forest_trust_data.top_level_name.string);
2355
2356         info->entries[0] = e;
2357
2358         /* Domain info */
2359         e = talloc(info, struct lsa_ForestTrustRecord);
2360         W_ERROR_HAVE_NO_MEMORY(e);
2361
2362         /* get our own domain info */
2363         ret = gendb_search_dn(sam_ctx, mem_ctx, NULL, &dom_res, dom_attrs);
2364         if (ret != 1) {
2365                 return WERR_GENERAL_FAILURE;
2366         }
2367
2368         /* TODO: check if disabled and set flags accordingly */
2369         e->flags = 0;
2370         e->type = LSA_FOREST_TRUST_DOMAIN_INFO;
2371         e->time = 0; /* so far always 0 in traces. */
2372
2373         domain_info = &e->forest_trust_data.domain_info;
2374         domain_info->domain_sid = samdb_result_dom_sid(info, dom_res[0],
2375                                                        "objectSid");
2376         domain_info->dns_domain_name.string = lpcfg_dnsdomain(lp_ctx);
2377         domain_info->netbios_domain_name.string = lpcfg_workgroup(lp_ctx);
2378
2379         info->entries[1] = e;
2380
2381         talloc_free(dom_res);
2382
2383         return WERR_OK;
2384 }
2385
2386 /*
2387   netr_DsRGetForestTrustInformation
2388 */
2389 static WERROR dcesrv_netr_DsRGetForestTrustInformation(struct dcesrv_call_state *dce_call,
2390                                                        TALLOC_CTX *mem_ctx,
2391                                                        struct netr_DsRGetForestTrustInformation *r)
2392 {
2393         struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2394         struct lsa_ForestTrustInformation *info, **info_ptr;
2395         struct ldb_context *sam_ctx;
2396         WERROR werr;
2397
2398         if (r->in.flags & 0xFFFFFFFE) {
2399                 return WERR_INVALID_FLAGS;
2400         }
2401
2402         sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2403                                 dce_call->conn->auth_state.session_info, 0);
2404         if (sam_ctx == NULL) {
2405                 return WERR_GENERAL_FAILURE;
2406         }
2407
2408         if (r->in.flags & DS_GFTI_UPDATE_TDO) {
2409                 if (!samdb_is_pdc(sam_ctx)) {
2410                         return WERR_NERR_NOTPRIMARY;
2411                 }
2412
2413                 if (r->in.trusted_domain_name == NULL) {
2414                         return WERR_INVALID_FLAGS;
2415                 }
2416
2417                 /* TODO: establish an schannel connection with
2418                  * r->in.trusted_domain_name and perform a
2419                  * netr_GetForestTrustInformation call against it */
2420
2421                 /* for now return not implementd */
2422                 return WERR_CALL_NOT_IMPLEMENTED;
2423         }
2424
2425         /* TODO: check r->in.server_name is our name */
2426
2427         info_ptr = talloc(mem_ctx, struct lsa_ForestTrustInformation *);
2428         W_ERROR_HAVE_NO_MEMORY(info_ptr);
2429
2430         info = talloc_zero(info_ptr, struct lsa_ForestTrustInformation);
2431         W_ERROR_HAVE_NO_MEMORY(info);
2432
2433         werr = fill_forest_trust_array(mem_ctx, sam_ctx, lp_ctx, info);
2434         W_ERROR_NOT_OK_RETURN(werr);
2435
2436         *info_ptr = info;
2437         r->out.forest_trust_info = info_ptr;
2438
2439         return WERR_OK;
2440 }
2441
2442
2443 /*
2444   netr_GetForestTrustInformation
2445 */
2446 static NTSTATUS dcesrv_netr_GetForestTrustInformation(struct dcesrv_call_state *dce_call,
2447                                                       TALLOC_CTX *mem_ctx,
2448                                                       struct netr_GetForestTrustInformation *r)
2449 {
2450         struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2451         struct netlogon_creds_CredentialState *creds;
2452         struct lsa_ForestTrustInformation *info, **info_ptr;
2453         struct ldb_context *sam_ctx;
2454         NTSTATUS status;
2455         WERROR werr;
2456
2457         status = dcesrv_netr_creds_server_step_check(dce_call,
2458                                                      mem_ctx,
2459                                                      r->in.computer_name,
2460                                                      r->in.credential,
2461                                                      r->out.return_authenticator,
2462                                                      &creds);
2463         if (!NT_STATUS_IS_OK(status)) {
2464                 return status;
2465         }
2466
2467         if ((creds->secure_channel_type != SEC_CHAN_DNS_DOMAIN) &&
2468             (creds->secure_channel_type != SEC_CHAN_DOMAIN)) {
2469                 return NT_STATUS_NOT_IMPLEMENTED;
2470         }
2471
2472         sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2473                                 dce_call->conn->auth_state.session_info, 0);
2474         if (sam_ctx == NULL) {
2475                 return NT_STATUS_INTERNAL_ERROR;
2476         }
2477
2478         /* TODO: check r->in.server_name is our name */
2479
2480         info_ptr = talloc(mem_ctx, struct lsa_ForestTrustInformation *);
2481         if (!info_ptr) {
2482                 return NT_STATUS_NO_MEMORY;
2483         }
2484         info = talloc_zero(info_ptr, struct lsa_ForestTrustInformation);
2485         if (!info) {
2486                 return NT_STATUS_NO_MEMORY;
2487         }
2488
2489         werr = fill_forest_trust_array(mem_ctx, sam_ctx, lp_ctx, info);
2490         if (!W_ERROR_IS_OK(werr)) {
2491                 return werror_to_ntstatus(werr);
2492         }
2493
2494         *info_ptr = info;
2495         r->out.forest_trust_info = info_ptr;
2496
2497         return NT_STATUS_OK;
2498 }
2499
2500
2501 /*
2502   netr_ServerGetTrustInfo
2503 */
2504 static NTSTATUS dcesrv_netr_ServerGetTrustInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2505                        struct netr_ServerGetTrustInfo *r)
2506 {
2507         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2508 }
2509
2510 /*
2511   netr_Unused47
2512 */
2513 static NTSTATUS dcesrv_netr_Unused47(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2514                                      struct netr_Unused47 *r)
2515 {
2516         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2517 }
2518
2519
2520 struct netr_dnsupdate_RODC_state {
2521         struct dcesrv_call_state *dce_call;
2522         struct netr_DsrUpdateReadOnlyServerDnsRecords *r;
2523         struct dnsupdate_RODC *r2;
2524 };
2525
2526 /*
2527   called when the forwarded RODC dns update request is finished
2528  */
2529 static void netr_dnsupdate_RODC_callback(struct tevent_req *subreq)
2530 {
2531         struct netr_dnsupdate_RODC_state *st =
2532                 tevent_req_callback_data(subreq,
2533                                          struct netr_dnsupdate_RODC_state);
2534         NTSTATUS status;
2535
2536         status = dcerpc_dnsupdate_RODC_r_recv(subreq, st->dce_call);
2537         TALLOC_FREE(subreq);
2538         if (!NT_STATUS_IS_OK(status)) {
2539                 DEBUG(0,(__location__ ": IRPC callback failed %s\n", nt_errstr(status)));
2540                 st->dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
2541         }
2542
2543         st->r->out.dns_names = talloc_steal(st->dce_call, st->r2->out.dns_names);
2544
2545         status = dcesrv_reply(st->dce_call);
2546         if (!NT_STATUS_IS_OK(status)) {
2547                 DEBUG(0,(__location__ ": dcesrv_reply() failed - %s\n", nt_errstr(status)));
2548         }
2549 }
2550
2551 /*
2552   netr_DsrUpdateReadOnlyServerDnsRecords
2553 */
2554 static NTSTATUS dcesrv_netr_DsrUpdateReadOnlyServerDnsRecords(struct dcesrv_call_state *dce_call,
2555                                                               TALLOC_CTX *mem_ctx,
2556                                                               struct netr_DsrUpdateReadOnlyServerDnsRecords *r)
2557 {
2558         struct netlogon_creds_CredentialState *creds;
2559         NTSTATUS nt_status;
2560         struct dcerpc_binding_handle *binding_handle;
2561         struct netr_dnsupdate_RODC_state *st;
2562         struct tevent_req *subreq;
2563
2564         nt_status = dcesrv_netr_creds_server_step_check(dce_call,
2565                                                         mem_ctx,
2566                                                         r->in.computer_name,
2567                                                         r->in.credential,
2568                                                         r->out.return_authenticator,
2569                                                         &creds);
2570         NT_STATUS_NOT_OK_RETURN(nt_status);
2571
2572         if (creds->secure_channel_type != SEC_CHAN_RODC) {
2573                 return NT_STATUS_ACCESS_DENIED;
2574         }
2575
2576         st = talloc_zero(mem_ctx, struct netr_dnsupdate_RODC_state);
2577         NT_STATUS_HAVE_NO_MEMORY(st);
2578
2579         st->dce_call = dce_call;
2580         st->r = r;
2581         st->r2 = talloc_zero(st, struct dnsupdate_RODC);
2582         NT_STATUS_HAVE_NO_MEMORY(st->r2);
2583
2584         st->r2->in.dom_sid = creds->sid;
2585         st->r2->in.site_name = r->in.site_name;
2586         st->r2->in.dns_ttl = r->in.dns_ttl;
2587         st->r2->in.dns_names = r->in.dns_names;
2588         st->r2->out.dns_names = r->out.dns_names;
2589
2590         binding_handle = irpc_binding_handle_by_name(st, dce_call->msg_ctx,
2591                                                      "dnsupdate", &ndr_table_irpc);
2592         if (binding_handle == NULL) {
2593                 DEBUG(0,("Failed to get binding_handle for dnsupdate task\n"));
2594                 dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
2595                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2596         }
2597
2598         /* forward the call */
2599         subreq = dcerpc_dnsupdate_RODC_r_send(st, dce_call->event_ctx,
2600                                               binding_handle, st->r2);
2601         NT_STATUS_HAVE_NO_MEMORY(subreq);
2602
2603         dce_call->state_flags |= DCESRV_CALL_STATE_FLAG_ASYNC;
2604
2605         /* setup the callback */
2606         tevent_req_set_callback(subreq, netr_dnsupdate_RODC_callback, st);
2607
2608         return NT_STATUS_OK;
2609 }
2610
2611
2612 /* include the generated boilerplate */
2613 #include "librpc/gen_ndr/ndr_netlogon_s.c"