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