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