5cc3b34dbf33ca6556ada17defe78662df2de01c
[mat/samba.git] / source4 / rpc_server / netlogon / dcerpc_netlogon.c
1 /*
2    Unix SMB/CIFS implementation.
3
4    endpoint server for the netlogon pipe
5
6    Copyright (C) Andrew Bartlett <abartlet@samba.org> 2004-2008
7    Copyright (C) Stefan Metzmacher <metze@samba.org>  2005
8    Copyright (C) Matthias Dieter Wallnöfer            2009-2010
9
10    This program is free software; you can redistribute it and/or modify
11    it under the terms of the GNU General Public License as published by
12    the Free Software Foundation; either version 3 of the License, or
13    (at your option) any later version.
14
15    This program is distributed in the hope that it will be useful,
16    but WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18    GNU General Public License for more details.
19
20    You should have received a copy of the GNU General Public License
21    along with this program.  If not, see <http://www.gnu.org/licenses/>.
22 */
23
24 #include "includes.h"
25 #include "rpc_server/dcerpc_server.h"
26 #include "auth/auth.h"
27 #include "auth/auth_sam_reply.h"
28 #include "dsdb/samdb/samdb.h"
29 #include "../lib/util/util_ldb.h"
30 #include "../libcli/auth/schannel.h"
31 #include "libcli/security/security.h"
32 #include "param/param.h"
33 #include "lib/messaging/irpc.h"
34 #include "librpc/gen_ndr/ndr_irpc_c.h"
35 #include "../libcli/ldap/ldap_ndr.h"
36 #include "cldap_server/cldap_server.h"
37 #include "lib/tsocket/tsocket.h"
38 #include "librpc/gen_ndr/ndr_netlogon.h"
39 #include "librpc/gen_ndr/ndr_irpc.h"
40 #include "lib/socket/netif.h"
41
42 struct netlogon_server_pipe_state {
43         struct netr_Credential client_challenge;
44         struct netr_Credential server_challenge;
45 };
46
47 static NTSTATUS dcesrv_netr_ServerReqChallenge(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
48                                         struct netr_ServerReqChallenge *r)
49 {
50         struct netlogon_server_pipe_state *pipe_state =
51                 talloc_get_type(dce_call->context->private_data, struct netlogon_server_pipe_state);
52
53         ZERO_STRUCTP(r->out.return_credentials);
54
55         /* destroyed on pipe shutdown */
56
57         if (pipe_state) {
58                 talloc_free(pipe_state);
59                 dce_call->context->private_data = NULL;
60         }
61
62         pipe_state = talloc(dce_call->context, struct netlogon_server_pipe_state);
63         NT_STATUS_HAVE_NO_MEMORY(pipe_state);
64
65         pipe_state->client_challenge = *r->in.credentials;
66
67         generate_random_buffer(pipe_state->server_challenge.data,
68                                sizeof(pipe_state->server_challenge.data));
69
70         *r->out.return_credentials = pipe_state->server_challenge;
71
72         dce_call->context->private_data = pipe_state;
73
74         return NT_STATUS_OK;
75 }
76
77 static NTSTATUS dcesrv_netr_ServerAuthenticate3(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
78                                          struct netr_ServerAuthenticate3 *r)
79 {
80         struct netlogon_server_pipe_state *pipe_state =
81                 talloc_get_type(dce_call->context->private_data, struct netlogon_server_pipe_state);
82         struct netlogon_creds_CredentialState *creds;
83         struct ldb_context *sam_ctx;
84         struct samr_Password *mach_pwd;
85         uint32_t user_account_control;
86         int num_records;
87         struct ldb_message **msgs;
88         NTSTATUS nt_status;
89         const char *attrs[] = {"unicodePwd", "userAccountControl",
90                                "objectSid", NULL};
91
92         const char *trust_dom_attrs[] = {"flatname", NULL};
93         const char *account_name;
94         uint32_t negotiate_flags = 0;
95
96         ZERO_STRUCTP(r->out.return_credentials);
97         *r->out.rid = 0;
98
99         negotiate_flags = NETLOGON_NEG_ACCOUNT_LOCKOUT |
100                           NETLOGON_NEG_PERSISTENT_SAMREPL |
101                           NETLOGON_NEG_ARCFOUR |
102                           NETLOGON_NEG_PROMOTION_COUNT |
103                           NETLOGON_NEG_CHANGELOG_BDC |
104                           NETLOGON_NEG_FULL_SYNC_REPL |
105                           NETLOGON_NEG_MULTIPLE_SIDS |
106                           NETLOGON_NEG_REDO |
107                           NETLOGON_NEG_PASSWORD_CHANGE_REFUSAL |
108                           NETLOGON_NEG_SEND_PASSWORD_INFO_PDC |
109                           NETLOGON_NEG_GENERIC_PASSTHROUGH |
110                           NETLOGON_NEG_CONCURRENT_RPC |
111                           NETLOGON_NEG_AVOID_ACCOUNT_DB_REPL |
112                           NETLOGON_NEG_AVOID_SECURITYAUTH_DB_REPL |
113                           NETLOGON_NEG_TRANSITIVE_TRUSTS |
114                           NETLOGON_NEG_DNS_DOMAIN_TRUSTS |
115                           NETLOGON_NEG_PASSWORD_SET2 |
116                           NETLOGON_NEG_GETDOMAININFO |
117                           NETLOGON_NEG_CROSS_FOREST_TRUSTS |
118                           NETLOGON_NEG_NEUTRALIZE_NT4_EMULATION |
119                           NETLOGON_NEG_RODC_PASSTHROUGH |
120                           NETLOGON_NEG_AUTHENTICATED_RPC_LSASS |
121                           NETLOGON_NEG_AUTHENTICATED_RPC;
122
123         if (*r->in.negotiate_flags & NETLOGON_NEG_STRONG_KEYS) {
124                 negotiate_flags |= NETLOGON_NEG_STRONG_KEYS;
125         }
126
127         if (*r->in.negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
128                 negotiate_flags |= NETLOGON_NEG_SUPPORTS_AES;
129         }
130
131         /*
132          * According to Microsoft (see bugid #6099)
133          * Windows 7 looks at the negotiate_flags
134          * returned in this structure *even if the
135          * call fails with access denied!
136          */
137         *r->out.negotiate_flags = negotiate_flags;
138
139         switch (r->in.secure_channel_type) {
140         case SEC_CHAN_WKSTA:
141         case SEC_CHAN_DNS_DOMAIN:
142         case SEC_CHAN_DOMAIN:
143         case SEC_CHAN_BDC:
144         case SEC_CHAN_RODC:
145                 break;
146         default:
147                 DEBUG(1, ("Client asked for an invalid secure channel type: %d\n",
148                           r->in.secure_channel_type));
149                 return NT_STATUS_INVALID_PARAMETER;
150         }
151
152         sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx,
153                                 system_session(dce_call->conn->dce_ctx->lp_ctx), 0);
154         if (sam_ctx == NULL) {
155                 return NT_STATUS_INVALID_SYSTEM_SERVICE;
156         }
157
158         if (r->in.secure_channel_type == SEC_CHAN_DNS_DOMAIN) {
159                 char *encoded_account = ldb_binary_encode_string(mem_ctx, r->in.account_name);
160                 const char *flatname;
161                 if (!encoded_account) {
162                         return NT_STATUS_NO_MEMORY;
163                 }
164
165                 /* Kill the trailing dot */
166                 if (encoded_account[strlen(encoded_account)-1] == '.') {
167                         encoded_account[strlen(encoded_account)-1] = '\0';
168                 }
169
170                 /* pull the user attributes */
171                 num_records = gendb_search(sam_ctx, mem_ctx, NULL, &msgs,
172                                            trust_dom_attrs,
173                                            "(&(trustPartner=%s)(objectclass=trustedDomain))",
174                                            encoded_account);
175
176                 if (num_records == 0) {
177                         DEBUG(3,("Couldn't find trust [%s] in samdb.\n",
178                                  encoded_account));
179                         return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
180                 }
181
182                 if (num_records > 1) {
183                         DEBUG(0,("Found %d records matching user [%s]\n", num_records, r->in.account_name));
184                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
185                 }
186
187                 flatname = ldb_msg_find_attr_as_string(msgs[0], "flatname", NULL);
188                 if (!flatname) {
189                         /* No flatname for this trust - we can't proceed */
190                         return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
191                 }
192                 account_name = talloc_asprintf(mem_ctx, "%s$", flatname);
193
194                 if (!account_name) {
195                         return NT_STATUS_NO_MEMORY;
196                 }
197
198         } else {
199                 account_name = r->in.account_name;
200         }
201
202         /* pull the user attributes */
203         num_records = gendb_search(sam_ctx, mem_ctx, NULL, &msgs, attrs,
204                                    "(&(sAMAccountName=%s)(objectclass=user))",
205                                    ldb_binary_encode_string(mem_ctx, account_name));
206
207         if (num_records == 0) {
208                 DEBUG(3,("Couldn't find user [%s] in samdb.\n",
209                          r->in.account_name));
210                 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
211         }
212
213         if (num_records > 1) {
214                 DEBUG(0,("Found %d records matching user [%s]\n", num_records, r->in.account_name));
215                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
216         }
217
218         user_account_control = ldb_msg_find_attr_as_uint(msgs[0], "userAccountControl", 0);
219
220         if (user_account_control & UF_ACCOUNTDISABLE) {
221                 DEBUG(1, ("Account [%s] is disabled\n", r->in.account_name));
222                 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
223         }
224
225         if (r->in.secure_channel_type == SEC_CHAN_WKSTA) {
226                 if (!(user_account_control & UF_WORKSTATION_TRUST_ACCOUNT)) {
227                         DEBUG(1, ("Client asked for a workstation secure channel, but is not a workstation (member server) acb flags: 0x%x\n", user_account_control));
228                         return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
229                 }
230         } else if (r->in.secure_channel_type == SEC_CHAN_DOMAIN ||
231                    r->in.secure_channel_type == SEC_CHAN_DNS_DOMAIN) {
232                 if (!(user_account_control & UF_INTERDOMAIN_TRUST_ACCOUNT)) {
233                         DEBUG(1, ("Client asked for a trusted domain secure channel, but is not a trusted domain: acb flags: 0x%x\n", user_account_control));
234
235                         return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
236                 }
237         } else if (r->in.secure_channel_type == SEC_CHAN_BDC) {
238                 if (!(user_account_control & UF_SERVER_TRUST_ACCOUNT)) {
239                         DEBUG(1, ("Client asked for a server secure channel, but is not a server (domain controller): acb flags: 0x%x\n", user_account_control));
240                         return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
241                 }
242         } else if (r->in.secure_channel_type == SEC_CHAN_RODC) {
243                 if (!(user_account_control & UF_PARTIAL_SECRETS_ACCOUNT)) {
244                         DEBUG(1, ("Client asked for a RODC secure channel, but is not a RODC: acb flags: 0x%x\n", user_account_control));
245                         return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
246                 }
247         } else {
248                 /* we should never reach this */
249                 return NT_STATUS_INTERNAL_ERROR;
250         }
251
252         *r->out.rid = samdb_result_rid_from_sid(mem_ctx, msgs[0],
253                                                 "objectSid", 0);
254
255         mach_pwd = samdb_result_hash(mem_ctx, msgs[0], "unicodePwd");
256         if (mach_pwd == NULL) {
257                 return NT_STATUS_ACCESS_DENIED;
258         }
259
260         if (!pipe_state) {
261                 DEBUG(1, ("No challenge requested by client, cannot authenticate\n"));
262                 return NT_STATUS_ACCESS_DENIED;
263         }
264
265         creds = netlogon_creds_server_init(mem_ctx,
266                                            r->in.account_name,
267                                            r->in.computer_name,
268                                            r->in.secure_channel_type,
269                                            &pipe_state->client_challenge,
270                                            &pipe_state->server_challenge,
271                                            mach_pwd,
272                                            r->in.credentials,
273                                            r->out.return_credentials,
274                                            negotiate_flags);
275         if (!creds) {
276                 return NT_STATUS_ACCESS_DENIED;
277         }
278
279         creds->sid = samdb_result_dom_sid(creds, msgs[0], "objectSid");
280
281         nt_status = schannel_save_creds_state(mem_ctx,
282                                               dce_call->conn->dce_ctx->lp_ctx,
283                                               creds);
284
285         return nt_status;
286 }
287
288 static NTSTATUS dcesrv_netr_ServerAuthenticate(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
289                                         struct netr_ServerAuthenticate *r)
290 {
291         struct netr_ServerAuthenticate3 a;
292         uint32_t rid;
293         /* TODO:
294          * negotiate_flags is used as an [in] parameter
295          * so it need to be initialised.
296          *
297          * (I think ... = 0; seems wrong here --metze)
298          */
299         uint32_t negotiate_flags_in = 0;
300         uint32_t negotiate_flags_out = 0;
301
302         a.in.server_name                = r->in.server_name;
303         a.in.account_name               = r->in.account_name;
304         a.in.secure_channel_type        = r->in.secure_channel_type;
305         a.in.computer_name              = r->in.computer_name;
306         a.in.credentials                = r->in.credentials;
307         a.in.negotiate_flags            = &negotiate_flags_in;
308
309         a.out.return_credentials        = r->out.return_credentials;
310         a.out.rid                       = &rid;
311         a.out.negotiate_flags           = &negotiate_flags_out;
312
313         return dcesrv_netr_ServerAuthenticate3(dce_call, mem_ctx, &a);
314 }
315
316 static NTSTATUS dcesrv_netr_ServerAuthenticate2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
317                                          struct netr_ServerAuthenticate2 *r)
318 {
319         struct netr_ServerAuthenticate3 r3;
320         uint32_t rid = 0;
321
322         r3.in.server_name = r->in.server_name;
323         r3.in.account_name = r->in.account_name;
324         r3.in.secure_channel_type = r->in.secure_channel_type;
325         r3.in.computer_name = r->in.computer_name;
326         r3.in.credentials = r->in.credentials;
327         r3.out.return_credentials = r->out.return_credentials;
328         r3.in.negotiate_flags = r->in.negotiate_flags;
329         r3.out.negotiate_flags = r->out.negotiate_flags;
330         r3.out.rid = &rid;
331
332         return dcesrv_netr_ServerAuthenticate3(dce_call, mem_ctx, &r3);
333 }
334
335 /*
336  * NOTE: The following functions are nearly identical to the ones available in
337  * source3/rpc_server/srv_nelog_nt.c
338  * The reason we keep 2 copies is that they use different structures to
339  * represent the auth_info and the decrpc pipes.
340  */
341
342 /*
343  * If schannel is required for this call test that it actually is available.
344  */
345 static NTSTATUS schannel_check_required(struct dcerpc_auth *auth_info,
346                                         const char *computer_name,
347                                         bool integrity, bool privacy)
348 {
349
350         if (auth_info && auth_info->auth_type == DCERPC_AUTH_TYPE_SCHANNEL) {
351                 if (!privacy && !integrity) {
352                         return NT_STATUS_OK;
353                 }
354
355                 if ((!privacy && integrity) &&
356                     auth_info->auth_level == DCERPC_AUTH_LEVEL_INTEGRITY) {
357                         return NT_STATUS_OK;
358                 }
359
360                 if ((privacy || integrity) &&
361                     auth_info->auth_level == DCERPC_AUTH_LEVEL_PRIVACY) {
362                         return NT_STATUS_OK;
363                 }
364         }
365
366         /* test didn't pass */
367         DEBUG(0, ("schannel_check_required: [%s] is not using schannel\n",
368                   computer_name));
369
370         return NT_STATUS_ACCESS_DENIED;
371 }
372
373 static NTSTATUS dcesrv_netr_creds_server_step_check(struct dcesrv_call_state *dce_call,
374                                                     TALLOC_CTX *mem_ctx,
375                                                     const char *computer_name,
376                                                     struct netr_Authenticator *received_authenticator,
377                                                     struct netr_Authenticator *return_authenticator,
378                                                     struct netlogon_creds_CredentialState **creds_out)
379 {
380         NTSTATUS nt_status;
381         struct dcerpc_auth *auth_info = dce_call->conn->auth_state.auth_info;
382         bool schannel_global_required = false; /* Should be lpcfg_schannel_server() == true */
383
384         if (schannel_global_required) {
385                 nt_status = schannel_check_required(auth_info,
386                                                     computer_name,
387                                                     true, false);
388                 if (!NT_STATUS_IS_OK(nt_status)) {
389                         return nt_status;
390                 }
391         }
392
393         nt_status = schannel_check_creds_state(mem_ctx,
394                                                dce_call->conn->dce_ctx->lp_ctx,
395                                                computer_name,
396                                                received_authenticator,
397                                                return_authenticator,
398                                                creds_out);
399         return nt_status;
400 }
401
402 /*
403   Change the machine account password for the currently connected
404   client.  Supplies only the NT#.
405 */
406
407 static NTSTATUS dcesrv_netr_ServerPasswordSet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
408                                        struct netr_ServerPasswordSet *r)
409 {
410         struct netlogon_creds_CredentialState *creds;
411         struct ldb_context *sam_ctx;
412         const char * const attrs[] = { "unicodePwd", NULL };
413         struct ldb_message **res;
414         struct samr_Password *oldNtHash;
415         NTSTATUS nt_status;
416         int ret;
417
418         nt_status = dcesrv_netr_creds_server_step_check(dce_call,
419                                                         mem_ctx,
420                                                         r->in.computer_name,
421                                                         r->in.credential, r->out.return_authenticator,
422                                                         &creds);
423         NT_STATUS_NOT_OK_RETURN(nt_status);
424
425         sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx, system_session(dce_call->conn->dce_ctx->lp_ctx), 0);
426         if (sam_ctx == NULL) {
427                 return NT_STATUS_INVALID_SYSTEM_SERVICE;
428         }
429
430         netlogon_creds_des_decrypt(creds, r->in.new_password);
431
432         /* fetch the old password hashes (the NT hash has to exist) */
433
434         ret = gendb_search(sam_ctx, mem_ctx, NULL, &res, attrs,
435                            "(&(objectClass=user)(objectSid=%s))",
436                            ldap_encode_ndr_dom_sid(mem_ctx, creds->sid));
437         if (ret != 1) {
438                 return NT_STATUS_WRONG_PASSWORD;
439         }
440
441         nt_status = samdb_result_passwords(mem_ctx,
442                                            dce_call->conn->dce_ctx->lp_ctx,
443                                            res[0], NULL, &oldNtHash);
444         if (!NT_STATUS_IS_OK(nt_status) || !oldNtHash) {
445                 return NT_STATUS_WRONG_PASSWORD;
446         }
447
448         /* Using the sid for the account as the key, set the password */
449         nt_status = samdb_set_password_sid(sam_ctx, mem_ctx,
450                                            creds->sid,
451                                            NULL, /* Don't have plaintext */
452                                            NULL, r->in.new_password,
453                                            NULL, oldNtHash, /* Password change */
454                                            NULL, NULL);
455         return nt_status;
456 }
457
458 /*
459   Change the machine account password for the currently connected
460   client.  Supplies new plaintext.
461 */
462 static NTSTATUS dcesrv_netr_ServerPasswordSet2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
463                                        struct netr_ServerPasswordSet2 *r)
464 {
465         struct netlogon_creds_CredentialState *creds;
466         struct ldb_context *sam_ctx;
467         const char * const attrs[] = { "dBCSPwd", "unicodePwd", NULL };
468         struct ldb_message **res;
469         struct samr_Password *oldLmHash, *oldNtHash;
470         NTSTATUS nt_status;
471         DATA_BLOB new_password;
472         int ret;
473
474         struct samr_CryptPassword password_buf;
475
476         nt_status = dcesrv_netr_creds_server_step_check(dce_call,
477                                                         mem_ctx,
478                                                         r->in.computer_name,
479                                                         r->in.credential, r->out.return_authenticator,
480                                                         &creds);
481         NT_STATUS_NOT_OK_RETURN(nt_status);
482
483         sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx, system_session(dce_call->conn->dce_ctx->lp_ctx), 0);
484         if (sam_ctx == NULL) {
485                 return NT_STATUS_INVALID_SYSTEM_SERVICE;
486         }
487
488         memcpy(password_buf.data, r->in.new_password->data, 512);
489         SIVAL(password_buf.data, 512, r->in.new_password->length);
490
491         if (creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
492                 netlogon_creds_aes_decrypt(creds, password_buf.data, 516);
493         } else {
494                 netlogon_creds_arcfour_crypt(creds, password_buf.data, 516);
495         }
496
497         if (!extract_pw_from_buffer(mem_ctx, password_buf.data, &new_password)) {
498                 DEBUG(3,("samr: failed to decode password buffer\n"));
499                 return NT_STATUS_WRONG_PASSWORD;
500         }
501
502         /* fetch the old password hashes (at least one of both has to exist) */
503
504         ret = gendb_search(sam_ctx, mem_ctx, NULL, &res, attrs,
505                            "(&(objectClass=user)(objectSid=%s))",
506                            ldap_encode_ndr_dom_sid(mem_ctx, creds->sid));
507         if (ret != 1) {
508                 return NT_STATUS_WRONG_PASSWORD;
509         }
510
511         nt_status = samdb_result_passwords(mem_ctx,
512                                            dce_call->conn->dce_ctx->lp_ctx,
513                                            res[0], &oldLmHash, &oldNtHash);
514         if (!NT_STATUS_IS_OK(nt_status) || (!oldLmHash && !oldNtHash)) {
515                 return NT_STATUS_WRONG_PASSWORD;
516         }
517
518         /* Using the sid for the account as the key, set the password */
519         nt_status = samdb_set_password_sid(sam_ctx, mem_ctx,
520                                            creds->sid,
521                                            &new_password, /* we have plaintext */
522                                            NULL, NULL,
523                                            oldLmHash, oldNtHash, /* Password change */
524                                            NULL, NULL);
525         return nt_status;
526 }
527
528
529 /*
530   netr_LogonUasLogon
531 */
532 static WERROR dcesrv_netr_LogonUasLogon(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
533                                  struct netr_LogonUasLogon *r)
534 {
535         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
536 }
537
538
539 /*
540   netr_LogonUasLogoff
541 */
542 static WERROR dcesrv_netr_LogonUasLogoff(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
543                        struct netr_LogonUasLogoff *r)
544 {
545         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
546 }
547
548
549 static NTSTATUS dcesrv_netr_LogonSamLogon_check(const struct netr_LogonSamLogonEx *r)
550 {
551         switch (r->in.logon_level) {
552         case NetlogonInteractiveInformation:
553         case NetlogonServiceInformation:
554         case NetlogonInteractiveTransitiveInformation:
555         case NetlogonServiceTransitiveInformation:
556                 if (r->in.logon->password == NULL) {
557                         return NT_STATUS_INVALID_PARAMETER;
558                 }
559
560                 switch (r->in.validation_level) {
561                 case NetlogonValidationSamInfo:  /* 2 */
562                 case NetlogonValidationSamInfo2: /* 3 */
563                 case NetlogonValidationSamInfo4: /* 6 */
564                         break;
565                 default:
566                         return NT_STATUS_INVALID_INFO_CLASS;
567                 }
568
569                 break;
570         case NetlogonNetworkInformation:
571         case NetlogonNetworkTransitiveInformation:
572                 if (r->in.logon->network == NULL) {
573                         return NT_STATUS_INVALID_PARAMETER;
574                 }
575
576                 switch (r->in.validation_level) {
577                 case NetlogonValidationSamInfo:  /* 2 */
578                 case NetlogonValidationSamInfo2: /* 3 */
579                 case NetlogonValidationSamInfo4: /* 6 */
580                         break;
581                 default:
582                         return NT_STATUS_INVALID_INFO_CLASS;
583                 }
584
585                 break;
586
587         case NetlogonGenericInformation:
588                 if (r->in.logon->generic == NULL) {
589                         return NT_STATUS_INVALID_PARAMETER;
590                 }
591
592                 switch (r->in.validation_level) {
593                 /* TODO: case NetlogonValidationGenericInfo: 4 */
594                 case NetlogonValidationGenericInfo2: /* 5 */
595                         break;
596                 default:
597                         return NT_STATUS_INVALID_INFO_CLASS;
598                 }
599
600                 break;
601         default:
602                 return NT_STATUS_INVALID_PARAMETER;
603         }
604
605         return NT_STATUS_OK;
606 }
607
608 /*
609   netr_LogonSamLogon_base
610
611   This version of the function allows other wrappers to say 'do not check the credentials'
612
613   We can't do the traditional 'wrapping' format completly, as this function must only run under schannel
614 */
615 static NTSTATUS dcesrv_netr_LogonSamLogon_base(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
616                                         struct netr_LogonSamLogonEx *r, struct netlogon_creds_CredentialState *creds)
617 {
618         struct auth4_context *auth_context;
619         struct auth_usersupplied_info *user_info;
620         struct auth_user_info_dc *user_info_dc;
621         NTSTATUS nt_status;
622         struct netr_SamBaseInfo *sam;
623         struct netr_SamInfo2 *sam2;
624         struct netr_SamInfo3 *sam3;
625         struct netr_SamInfo6 *sam6;
626
627         *r->out.authoritative = 1;
628
629         user_info = talloc_zero(mem_ctx, struct auth_usersupplied_info);
630         NT_STATUS_HAVE_NO_MEMORY(user_info);
631
632         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", dc_name);
1844         W_ERROR_HAVE_NO_MEMORY(info->dc_unc);
1845
1846         load_interface_list(mem_ctx, lp_ctx, &ifaces);
1847         pdc_ip = iface_list_best_ip(ifaces, addr);
1848         if (pdc_ip == NULL) {
1849                 pdc_ip = "127.0.0.1";
1850         }
1851         info->dc_address = talloc_asprintf(mem_ctx, "\\\\%s", pdc_ip);
1852         W_ERROR_HAVE_NO_MEMORY(info->dc_address);
1853         info->dc_address_type  = DS_ADDRESS_TYPE_INET;
1854         info->domain_guid      = response.data.nt5_ex.domain_uuid;
1855         info->domain_name      = domain_name;
1856         info->forest_name      = response.data.nt5_ex.forest;
1857         info->dc_flags         = response.data.nt5_ex.server_type;
1858         info->dc_site_name     = response.data.nt5_ex.server_site;
1859         info->client_site_name = response.data.nt5_ex.client_site;
1860
1861         *r->out.info = info;
1862
1863         return WERR_OK;
1864 }
1865
1866 /*
1867   netr_DsRGetDCNameEx
1868 */
1869 static WERROR dcesrv_netr_DsRGetDCNameEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1870                                   struct netr_DsRGetDCNameEx *r)
1871 {
1872         struct netr_DsRGetDCNameEx2 r2;
1873         WERROR werr;
1874
1875         ZERO_STRUCT(r2);
1876
1877         r2.in.server_unc = r->in.server_unc;
1878         r2.in.client_account = NULL;
1879         r2.in.mask = 0;
1880         r2.in.domain_guid = r->in.domain_guid;
1881         r2.in.domain_name = r->in.domain_name;
1882         r2.in.site_name = r->in.site_name;
1883         r2.in.flags = r->in.flags;
1884         r2.out.info = r->out.info;
1885
1886         werr = dcesrv_netr_DsRGetDCNameEx2(dce_call, mem_ctx, &r2);
1887
1888         return werr;
1889 }
1890
1891 /*
1892   netr_DsRGetDCName
1893 */
1894 static WERROR dcesrv_netr_DsRGetDCName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1895                                 struct netr_DsRGetDCName *r)
1896 {
1897         struct netr_DsRGetDCNameEx2 r2;
1898         WERROR werr;
1899
1900         ZERO_STRUCT(r2);
1901
1902         r2.in.server_unc = r->in.server_unc;
1903         r2.in.client_account = NULL;
1904         r2.in.mask = 0;
1905         r2.in.domain_name = r->in.domain_name;
1906         r2.in.domain_guid = r->in.domain_guid;
1907
1908         r2.in.site_name = NULL; /* this is correct, we should ignore site GUID */
1909         r2.in.flags = r->in.flags;
1910         r2.out.info = r->out.info;
1911
1912         werr = dcesrv_netr_DsRGetDCNameEx2(dce_call, mem_ctx, &r2);
1913
1914         return werr;
1915 }
1916 /*
1917   netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN
1918 */
1919 static WERROR dcesrv_netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1920                        struct netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN *r)
1921 {
1922         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1923 }
1924
1925
1926 /*
1927   netr_NetrEnumerateTrustedDomainsEx
1928 */
1929 static WERROR dcesrv_netr_NetrEnumerateTrustedDomainsEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1930                        struct netr_NetrEnumerateTrustedDomainsEx *r)
1931 {
1932         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1933 }
1934
1935
1936 /*
1937   netr_DsRAddressToSitenamesExW
1938 */
1939 static WERROR dcesrv_netr_DsRAddressToSitenamesExW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1940                                                    struct netr_DsRAddressToSitenamesExW *r)
1941 {
1942         struct ldb_context *sam_ctx;
1943         struct netr_DsRAddressToSitenamesExWCtr *ctr;
1944         struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1945         sa_family_t sin_family;
1946         struct sockaddr_in *addr;
1947 #ifdef HAVE_IPV6
1948         struct sockaddr_in6 *addr6;
1949         char addr_str[INET6_ADDRSTRLEN];
1950 #else
1951         char addr_str[INET_ADDRSTRLEN];
1952 #endif
1953         char *subnet_name;
1954         const char *res;
1955         uint32_t i;
1956
1957         sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1958                                 dce_call->conn->auth_state.session_info, 0);
1959         if (sam_ctx == NULL) {
1960                 return WERR_DS_UNAVAILABLE;
1961         }
1962
1963         ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesExWCtr);
1964         W_ERROR_HAVE_NO_MEMORY(ctr);
1965
1966         *r->out.ctr = ctr;
1967
1968         ctr->count = r->in.count;
1969         ctr->sitename = talloc_array(ctr, struct lsa_String, ctr->count);
1970         W_ERROR_HAVE_NO_MEMORY(ctr->sitename);
1971         ctr->subnetname = talloc_array(ctr, struct lsa_String, ctr->count);
1972         W_ERROR_HAVE_NO_MEMORY(ctr->subnetname);
1973
1974         for (i=0; i<ctr->count; i++) {
1975                 ctr->sitename[i].string = NULL;
1976                 ctr->subnetname[i].string = NULL;
1977
1978                 if (r->in.addresses[i].size < sizeof(sa_family_t)) {
1979                         continue;
1980                 }
1981                 /* The first two byte of the buffer are reserved for the
1982                  * "sin_family" but for now only the first one is used. */
1983                 sin_family = r->in.addresses[i].buffer[0];
1984
1985                 switch (sin_family) {
1986                 case AF_INET:
1987                         if (r->in.addresses[i].size < sizeof(struct sockaddr_in)) {
1988                                 continue;
1989                         }
1990                         addr = (struct sockaddr_in *) r->in.addresses[i].buffer;
1991                         res = inet_ntop(AF_INET, &addr->sin_addr,
1992                                         addr_str, sizeof(addr_str));
1993                         break;
1994 #ifdef HAVE_IPV6
1995                 case AF_INET6:
1996                         if (r->in.addresses[i].size < sizeof(struct sockaddr_in6)) {
1997                                 continue;
1998                         }
1999                         addr6 = (struct sockaddr_in6 *) r->in.addresses[i].buffer;
2000                         res = inet_ntop(AF_INET6, &addr6->sin6_addr,
2001                                         addr_str, sizeof(addr_str));
2002                         break;
2003 #endif
2004                 default:
2005                         continue;
2006                 }
2007
2008                 if (res == NULL) {
2009                         continue;
2010                 }
2011
2012                 ctr->sitename[i].string   = samdb_client_site_name(sam_ctx,
2013                                                                    mem_ctx,
2014                                                                    addr_str,
2015                                                                    &subnet_name);
2016                 W_ERROR_HAVE_NO_MEMORY(ctr->sitename[i].string);
2017                 ctr->subnetname[i].string = subnet_name;
2018         }
2019
2020         return WERR_OK;
2021 }
2022
2023
2024 /*
2025   netr_DsRAddressToSitenamesW
2026 */
2027 static WERROR dcesrv_netr_DsRAddressToSitenamesW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2028                        struct netr_DsRAddressToSitenamesW *r)
2029 {
2030         struct netr_DsRAddressToSitenamesExW r2;
2031         struct netr_DsRAddressToSitenamesWCtr *ctr;
2032         uint32_t i;
2033         WERROR werr;
2034
2035         ZERO_STRUCT(r2);
2036
2037         r2.in.server_name = r->in.server_name;
2038         r2.in.count = r->in.count;
2039         r2.in.addresses = r->in.addresses;
2040
2041         r2.out.ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesExWCtr *);
2042         W_ERROR_HAVE_NO_MEMORY(r2.out.ctr);
2043
2044         ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesWCtr);
2045         W_ERROR_HAVE_NO_MEMORY(ctr);
2046
2047         *r->out.ctr = ctr;
2048
2049         ctr->count = r->in.count;
2050         ctr->sitename = talloc_array(ctr, struct lsa_String, ctr->count);
2051         W_ERROR_HAVE_NO_MEMORY(ctr->sitename);
2052
2053         werr = dcesrv_netr_DsRAddressToSitenamesExW(dce_call, mem_ctx, &r2);
2054
2055         for (i=0; i<ctr->count; i++) {
2056                 ctr->sitename[i].string   = (*r2.out.ctr)->sitename[i].string;
2057         }
2058
2059         return werr;
2060 }
2061
2062
2063 /*
2064   netr_DsrGetDcSiteCoverageW
2065 */
2066 static WERROR dcesrv_netr_DsrGetDcSiteCoverageW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2067                        struct netr_DsrGetDcSiteCoverageW *r)
2068 {
2069         struct ldb_context *sam_ctx;
2070         struct DcSitesCtr *ctr;
2071         struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2072
2073         sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2074                                 dce_call->conn->auth_state.session_info, 0);
2075         if (sam_ctx == NULL) {
2076                 return WERR_DS_UNAVAILABLE;
2077         }
2078
2079         ctr = talloc(mem_ctx, struct DcSitesCtr);
2080         W_ERROR_HAVE_NO_MEMORY(ctr);
2081
2082         *r->out.ctr = ctr;
2083
2084         /* For now only return our default site */
2085         ctr->num_sites = 1;
2086         ctr->sites = talloc_array(ctr, struct lsa_String, ctr->num_sites);
2087         W_ERROR_HAVE_NO_MEMORY(ctr->sites);
2088         ctr->sites[0].string = samdb_server_site_name(sam_ctx, mem_ctx);
2089         W_ERROR_HAVE_NO_MEMORY(ctr->sites[0].string);
2090
2091         return WERR_OK;
2092 }
2093
2094
2095 static WERROR fill_trusted_domains_array(TALLOC_CTX *mem_ctx,
2096                                          struct ldb_context *sam_ctx,
2097                                          struct netr_DomainTrustList *trusts,
2098                                          uint32_t trust_flags)
2099 {
2100         struct ldb_dn *system_dn;
2101         struct ldb_message **dom_res = NULL;
2102         const char *trust_attrs[] = { "flatname", "trustPartner",
2103                                       "securityIdentifier", "trustDirection",
2104                                       "trustType", "trustAttributes", NULL };
2105         uint32_t n;
2106         int i;
2107         int ret;
2108
2109         if (!(trust_flags & (NETR_TRUST_FLAG_INBOUND |
2110                              NETR_TRUST_FLAG_OUTBOUND))) {
2111                 return WERR_INVALID_FLAGS;
2112         }
2113
2114         system_dn = samdb_search_dn(sam_ctx, mem_ctx,
2115                                     ldb_get_default_basedn(sam_ctx),
2116                                     "(&(objectClass=container)(cn=System))");
2117         if (!system_dn) {
2118                 return WERR_GENERAL_FAILURE;
2119         }
2120
2121         ret = gendb_search(sam_ctx, mem_ctx, system_dn,
2122                            &dom_res, trust_attrs,
2123                            "(objectclass=trustedDomain)");
2124
2125         for (i = 0; i < ret; i++) {
2126                 unsigned int trust_dir;
2127                 uint32_t flags = 0;
2128
2129                 trust_dir = ldb_msg_find_attr_as_uint(dom_res[i],
2130                                                       "trustDirection", 0);
2131
2132                 if (trust_dir & LSA_TRUST_DIRECTION_INBOUND) {
2133                         flags |= NETR_TRUST_FLAG_INBOUND;
2134                 }
2135                 if (trust_dir & LSA_TRUST_DIRECTION_OUTBOUND) {
2136                         flags |= NETR_TRUST_FLAG_OUTBOUND;
2137                 }
2138
2139                 if (!(flags & trust_flags)) {
2140                         /* this trust direction was not requested */
2141                         continue;
2142                 }
2143
2144                 n = trusts->count;
2145                 trusts->array = talloc_realloc(trusts, trusts->array,
2146                                                struct netr_DomainTrust,
2147                                                n + 1);
2148                 W_ERROR_HAVE_NO_MEMORY(trusts->array);
2149
2150                 trusts->array[n].netbios_name = talloc_steal(trusts->array, ldb_msg_find_attr_as_string(dom_res[i], "flatname", NULL));
2151                 if (!trusts->array[n].netbios_name) {
2152                         DEBUG(0, ("DB Error, TrustedDomain entry (%s) "
2153                                   "without flatname\n", 
2154                                   ldb_dn_get_linearized(dom_res[i]->dn)));
2155                 }
2156
2157                 trusts->array[n].dns_name = talloc_steal(trusts->array, ldb_msg_find_attr_as_string(dom_res[i], "trustPartner", NULL));
2158
2159                 trusts->array[n].trust_flags = flags;
2160                 if ((trust_flags & NETR_TRUST_FLAG_IN_FOREST) &&
2161                     !(flags & NETR_TRUST_FLAG_TREEROOT)) {
2162                         /* TODO: find if we have parent in the list */
2163                         trusts->array[n].parent_index = 0;
2164                 }
2165
2166                 trusts->array[n].trust_type =
2167                                 ldb_msg_find_attr_as_uint(dom_res[i],
2168                                                   "trustType", 0);
2169                 trusts->array[n].trust_attributes =
2170                                 ldb_msg_find_attr_as_uint(dom_res[i],
2171                                                   "trustAttributes", 0);
2172
2173                 if ((trusts->array[n].trust_type == NETR_TRUST_TYPE_MIT) ||
2174                     (trusts->array[n].trust_type == NETR_TRUST_TYPE_DCE)) {
2175                         struct dom_sid zero_sid;
2176                         ZERO_STRUCT(zero_sid);
2177                         trusts->array[n].sid =
2178                                 dom_sid_dup(trusts, &zero_sid);
2179                 } else {
2180                         trusts->array[n].sid =
2181                                 samdb_result_dom_sid(trusts, dom_res[i],
2182                                                      "securityIdentifier");
2183                 }
2184                 trusts->array[n].guid = GUID_zero();
2185
2186                 trusts->count = n + 1;
2187         }
2188
2189         talloc_free(dom_res);
2190         return WERR_OK;
2191 }
2192
2193 /*
2194   netr_DsrEnumerateDomainTrusts
2195 */
2196 static WERROR dcesrv_netr_DsrEnumerateDomainTrusts(struct dcesrv_call_state *dce_call,
2197                                                    TALLOC_CTX *mem_ctx,
2198                                                    struct netr_DsrEnumerateDomainTrusts *r)
2199 {
2200         struct netr_DomainTrustList *trusts;
2201         struct ldb_context *sam_ctx;
2202         int ret;
2203         struct ldb_message **dom_res;
2204         const char * const dom_attrs[] = { "objectSid", "objectGUID", NULL };
2205         struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2206         const char *dnsdomain = lpcfg_dnsdomain(lp_ctx);
2207         const char *p;
2208         WERROR werr;
2209
2210         if (r->in.trust_flags & 0xFFFFFE00) {
2211                 return WERR_INVALID_FLAGS;
2212         }
2213
2214         /* TODO: turn to hard check once we are sure this is 100% correct */
2215         if (!r->in.server_name) {
2216                 DEBUG(3, ("Invalid domain! Expected name in domain [%s]. "
2217                           "But received NULL!\n", dnsdomain));
2218         } else {
2219                 p = strchr(r->in.server_name, '.');
2220                 if (!p) {
2221                         DEBUG(3, ("Invalid domain! Expected name in domain "
2222                                   "[%s]. But received [%s]!\n",
2223                                   dnsdomain, r->in.server_name));
2224                         p = r->in.server_name;
2225                 } else {
2226                         p++;
2227                 }
2228                 if (strcasecmp(p, dnsdomain)) {
2229                         DEBUG(3, ("Invalid domain! Expected name in domain "
2230                                   "[%s]. But received [%s]!\n",
2231                                   dnsdomain, r->in.server_name));
2232                 }
2233         }
2234
2235         trusts = talloc_zero(mem_ctx, struct netr_DomainTrustList);
2236         W_ERROR_HAVE_NO_MEMORY(trusts);
2237
2238         trusts->count = 0;
2239         r->out.trusts = trusts;
2240
2241         sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2242                                 dce_call->conn->auth_state.session_info, 0);
2243         if (sam_ctx == NULL) {
2244                 return WERR_GENERAL_FAILURE;
2245         }
2246
2247         if ((r->in.trust_flags & NETR_TRUST_FLAG_INBOUND) ||
2248             (r->in.trust_flags & NETR_TRUST_FLAG_OUTBOUND)) {
2249
2250                 werr = fill_trusted_domains_array(mem_ctx, sam_ctx,
2251                                                   trusts, r->in.trust_flags);
2252                 W_ERROR_NOT_OK_RETURN(werr);
2253         }
2254
2255         /* NOTE: we currently are always the root of the forest */
2256         if (r->in.trust_flags & NETR_TRUST_FLAG_IN_FOREST) {
2257                 uint32_t n = trusts->count;
2258
2259                 ret = gendb_search_dn(sam_ctx, mem_ctx, NULL,
2260                                       &dom_res, dom_attrs);
2261                 if (ret != 1) {
2262                         return WERR_GENERAL_FAILURE;
2263                 }
2264
2265                 trusts->count = n + 1;
2266                 trusts->array = talloc_realloc(trusts, trusts->array,
2267                                                struct netr_DomainTrust,
2268                                                trusts->count);
2269                 W_ERROR_HAVE_NO_MEMORY(trusts->array);
2270
2271                 trusts->array[n].netbios_name = lpcfg_workgroup(lp_ctx);
2272                 trusts->array[n].dns_name = lpcfg_dnsdomain(lp_ctx);
2273                 trusts->array[n].trust_flags =
2274                         NETR_TRUST_FLAG_NATIVE |
2275                         NETR_TRUST_FLAG_TREEROOT |
2276                         NETR_TRUST_FLAG_IN_FOREST |
2277                         NETR_TRUST_FLAG_PRIMARY;
2278                 /* we are always the root domain for now */
2279                 trusts->array[n].parent_index = 0;
2280                 trusts->array[n].trust_type = NETR_TRUST_TYPE_UPLEVEL;
2281                 trusts->array[n].trust_attributes = 0;
2282                 trusts->array[n].sid = samdb_result_dom_sid(mem_ctx,
2283                                                             dom_res[0],
2284                                                             "objectSid");
2285                 trusts->array[n].guid = samdb_result_guid(dom_res[0],
2286                                                           "objectGUID");
2287                 talloc_free(dom_res);
2288         }
2289
2290         return WERR_OK;
2291 }
2292
2293
2294 /*
2295   netr_DsrDeregisterDNSHostRecords
2296 */
2297 static WERROR dcesrv_netr_DsrDeregisterDNSHostRecords(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2298                        struct netr_DsrDeregisterDNSHostRecords *r)
2299 {
2300         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2301 }
2302
2303
2304 /*
2305   netr_ServerTrustPasswordsGet
2306 */
2307 static NTSTATUS dcesrv_netr_ServerTrustPasswordsGet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2308                        struct netr_ServerTrustPasswordsGet *r)
2309 {
2310         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2311 }
2312
2313
2314 static WERROR fill_forest_trust_array(TALLOC_CTX *mem_ctx,
2315                                       struct ldb_context *sam_ctx,
2316                                       struct loadparm_context *lp_ctx,
2317                                       struct lsa_ForestTrustInformation *info)
2318 {
2319         struct lsa_ForestTrustDomainInfo *domain_info;
2320         struct lsa_ForestTrustRecord *e;
2321         struct ldb_message **dom_res;
2322         const char * const dom_attrs[] = { "objectSid", NULL };
2323         int ret;
2324
2325         /* we need to provide 2 entries:
2326          * 1. the Root Forest name
2327          * 2. the Domain Information
2328          */
2329
2330         info->count = 2;
2331         info->entries = talloc_array(info, struct lsa_ForestTrustRecord *, 2);
2332         W_ERROR_HAVE_NO_MEMORY(info->entries);
2333
2334         /* Forest root info */
2335         e = talloc(info, struct lsa_ForestTrustRecord);
2336         W_ERROR_HAVE_NO_MEMORY(e);
2337
2338         e->flags = 0;
2339         e->type = LSA_FOREST_TRUST_TOP_LEVEL_NAME;
2340         e->time = 0; /* so far always 0 in trces. */
2341         e->forest_trust_data.top_level_name.string = samdb_forest_name(sam_ctx,
2342                                                                        mem_ctx);
2343         W_ERROR_HAVE_NO_MEMORY(e->forest_trust_data.top_level_name.string);
2344
2345         info->entries[0] = e;
2346
2347         /* Domain info */
2348         e = talloc(info, struct lsa_ForestTrustRecord);
2349         W_ERROR_HAVE_NO_MEMORY(e);
2350
2351         /* get our own domain info */
2352         ret = gendb_search_dn(sam_ctx, mem_ctx, NULL, &dom_res, dom_attrs);
2353         if (ret != 1) {
2354                 return WERR_GENERAL_FAILURE;
2355         }
2356
2357         /* TODO: check if disabled and set flags accordingly */
2358         e->flags = 0;
2359         e->type = LSA_FOREST_TRUST_DOMAIN_INFO;
2360         e->time = 0; /* so far always 0 in traces. */
2361
2362         domain_info = &e->forest_trust_data.domain_info;
2363         domain_info->domain_sid = samdb_result_dom_sid(info, dom_res[0],
2364                                                        "objectSid");
2365         domain_info->dns_domain_name.string = lpcfg_dnsdomain(lp_ctx);
2366         domain_info->netbios_domain_name.string = lpcfg_workgroup(lp_ctx);
2367
2368         info->entries[1] = e;
2369
2370         talloc_free(dom_res);
2371
2372         return WERR_OK;
2373 }
2374
2375 /*
2376   netr_DsRGetForestTrustInformation
2377 */
2378 static WERROR dcesrv_netr_DsRGetForestTrustInformation(struct dcesrv_call_state *dce_call,
2379                                                        TALLOC_CTX *mem_ctx,
2380                                                        struct netr_DsRGetForestTrustInformation *r)
2381 {
2382         struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2383         struct lsa_ForestTrustInformation *info, **info_ptr;
2384         struct ldb_context *sam_ctx;
2385         WERROR werr;
2386
2387         if (r->in.flags & 0xFFFFFFFE) {
2388                 return WERR_INVALID_FLAGS;
2389         }
2390
2391         sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2392                                 dce_call->conn->auth_state.session_info, 0);
2393         if (sam_ctx == NULL) {
2394                 return WERR_GENERAL_FAILURE;
2395         }
2396
2397         if (r->in.flags & DS_GFTI_UPDATE_TDO) {
2398                 if (!samdb_is_pdc(sam_ctx)) {
2399                         return WERR_NERR_NOTPRIMARY;
2400                 }
2401
2402                 if (r->in.trusted_domain_name == NULL) {
2403                         return WERR_INVALID_FLAGS;
2404                 }
2405
2406                 /* TODO: establish an schannel connection with
2407                  * r->in.trusted_domain_name and perform a
2408                  * netr_GetForestTrustInformation call against it */
2409
2410                 /* for now return not implementd */
2411                 return WERR_CALL_NOT_IMPLEMENTED;
2412         }
2413
2414         /* TODO: check r->in.server_name is our name */
2415
2416         info_ptr = talloc(mem_ctx, struct lsa_ForestTrustInformation *);
2417         W_ERROR_HAVE_NO_MEMORY(info_ptr);
2418
2419         info = talloc_zero(info_ptr, struct lsa_ForestTrustInformation);
2420         W_ERROR_HAVE_NO_MEMORY(info);
2421
2422         werr = fill_forest_trust_array(mem_ctx, sam_ctx, lp_ctx, info);
2423         W_ERROR_NOT_OK_RETURN(werr);
2424
2425         *info_ptr = info;
2426         r->out.forest_trust_info = info_ptr;
2427
2428         return WERR_OK;
2429 }
2430
2431
2432 /*
2433   netr_GetForestTrustInformation
2434 */
2435 static NTSTATUS dcesrv_netr_GetForestTrustInformation(struct dcesrv_call_state *dce_call,
2436                                                       TALLOC_CTX *mem_ctx,
2437                                                       struct netr_GetForestTrustInformation *r)
2438 {
2439         struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2440         struct netlogon_creds_CredentialState *creds;
2441         struct lsa_ForestTrustInformation *info, **info_ptr;
2442         struct ldb_context *sam_ctx;
2443         NTSTATUS status;
2444         WERROR werr;
2445
2446         status = dcesrv_netr_creds_server_step_check(dce_call,
2447                                                      mem_ctx,
2448                                                      r->in.computer_name,
2449                                                      r->in.credential,
2450                                                      r->out.return_authenticator,
2451                                                      &creds);
2452         if (!NT_STATUS_IS_OK(status)) {
2453                 return status;
2454         }
2455
2456         if ((creds->secure_channel_type != SEC_CHAN_DNS_DOMAIN) &&
2457             (creds->secure_channel_type != SEC_CHAN_DOMAIN)) {
2458                 return NT_STATUS_NOT_IMPLEMENTED;
2459         }
2460
2461         sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2462                                 dce_call->conn->auth_state.session_info, 0);
2463         if (sam_ctx == NULL) {
2464                 return NT_STATUS_INTERNAL_ERROR;
2465         }
2466
2467         /* TODO: check r->in.server_name is our name */
2468
2469         info_ptr = talloc(mem_ctx, struct lsa_ForestTrustInformation *);
2470         if (!info_ptr) {
2471                 return NT_STATUS_NO_MEMORY;
2472         }
2473         info = talloc_zero(info_ptr, struct lsa_ForestTrustInformation);
2474         if (!info) {
2475                 return NT_STATUS_NO_MEMORY;
2476         }
2477
2478         werr = fill_forest_trust_array(mem_ctx, sam_ctx, lp_ctx, info);
2479         if (!W_ERROR_IS_OK(werr)) {
2480                 return werror_to_ntstatus(werr);
2481         }
2482
2483         *info_ptr = info;
2484         r->out.forest_trust_info = info_ptr;
2485
2486         return NT_STATUS_OK;
2487 }
2488
2489
2490 /*
2491   netr_ServerGetTrustInfo
2492 */
2493 static NTSTATUS dcesrv_netr_ServerGetTrustInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2494                        struct netr_ServerGetTrustInfo *r)
2495 {
2496         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2497 }
2498
2499 /*
2500   netr_Unused47
2501 */
2502 static NTSTATUS dcesrv_netr_Unused47(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2503                                      struct netr_Unused47 *r)
2504 {
2505         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2506 }
2507
2508
2509 struct netr_dnsupdate_RODC_state {
2510         struct dcesrv_call_state *dce_call;
2511         struct netr_DsrUpdateReadOnlyServerDnsRecords *r;
2512         struct dnsupdate_RODC *r2;
2513 };
2514
2515 /*
2516   called when the forwarded RODC dns update request is finished
2517  */
2518 static void netr_dnsupdate_RODC_callback(struct tevent_req *subreq)
2519 {
2520         struct netr_dnsupdate_RODC_state *st =
2521                 tevent_req_callback_data(subreq,
2522                                          struct netr_dnsupdate_RODC_state);
2523         NTSTATUS status;
2524
2525         status = dcerpc_dnsupdate_RODC_r_recv(subreq, st->dce_call);
2526         TALLOC_FREE(subreq);
2527         if (!NT_STATUS_IS_OK(status)) {
2528                 DEBUG(0,(__location__ ": IRPC callback failed %s\n", nt_errstr(status)));
2529                 st->dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
2530         }
2531
2532         st->r->out.dns_names = talloc_steal(st->dce_call, st->r2->out.dns_names);
2533
2534         status = dcesrv_reply(st->dce_call);
2535         if (!NT_STATUS_IS_OK(status)) {
2536                 DEBUG(0,(__location__ ": dcesrv_reply() failed - %s\n", nt_errstr(status)));
2537         }
2538 }
2539
2540 /*
2541   netr_DsrUpdateReadOnlyServerDnsRecords
2542 */
2543 static NTSTATUS dcesrv_netr_DsrUpdateReadOnlyServerDnsRecords(struct dcesrv_call_state *dce_call,
2544                                                               TALLOC_CTX *mem_ctx,
2545                                                               struct netr_DsrUpdateReadOnlyServerDnsRecords *r)
2546 {
2547         struct netlogon_creds_CredentialState *creds;
2548         NTSTATUS nt_status;
2549         struct dcerpc_binding_handle *binding_handle;
2550         struct netr_dnsupdate_RODC_state *st;
2551         struct tevent_req *subreq;
2552
2553         nt_status = dcesrv_netr_creds_server_step_check(dce_call,
2554                                                         mem_ctx,
2555                                                         r->in.computer_name,
2556                                                         r->in.credential,
2557                                                         r->out.return_authenticator,
2558                                                         &creds);
2559         NT_STATUS_NOT_OK_RETURN(nt_status);
2560
2561         if (creds->secure_channel_type != SEC_CHAN_RODC) {
2562                 return NT_STATUS_ACCESS_DENIED;
2563         }
2564
2565         st = talloc_zero(mem_ctx, struct netr_dnsupdate_RODC_state);
2566         NT_STATUS_HAVE_NO_MEMORY(st);
2567
2568         st->dce_call = dce_call;
2569         st->r = r;
2570         st->r2 = talloc_zero(st, struct dnsupdate_RODC);
2571         NT_STATUS_HAVE_NO_MEMORY(st->r2);
2572
2573         st->r2->in.dom_sid = creds->sid;
2574         st->r2->in.site_name = r->in.site_name;
2575         st->r2->in.dns_ttl = r->in.dns_ttl;
2576         st->r2->in.dns_names = r->in.dns_names;
2577         st->r2->out.dns_names = r->out.dns_names;
2578
2579         binding_handle = irpc_binding_handle_by_name(st, dce_call->msg_ctx,
2580                                                      "dnsupdate", &ndr_table_irpc);
2581         if (binding_handle == NULL) {
2582                 DEBUG(0,("Failed to get binding_handle for dnsupdate task\n"));
2583                 dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
2584                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2585         }
2586
2587         /* forward the call */
2588         subreq = dcerpc_dnsupdate_RODC_r_send(st, dce_call->event_ctx,
2589                                               binding_handle, st->r2);
2590         NT_STATUS_HAVE_NO_MEMORY(subreq);
2591
2592         dce_call->state_flags |= DCESRV_CALL_STATE_FLAG_ASYNC;
2593
2594         /* setup the callback */
2595         tevent_req_set_callback(subreq, netr_dnsupdate_RODC_callback, st);
2596
2597         return NT_STATUS_OK;
2598 }
2599
2600
2601 /* include the generated boilerplate */
2602 #include "librpc/gen_ndr/ndr_netlogon_s.c"