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