s4:rpc_server/netlogon: don't treet trusted domains as primary in LogonGetDomainInfo()
[garming/samba-autobuild/.git] / source4 / rpc_server / netlogon / dcerpc_netlogon.c
1 /*
2    Unix SMB/CIFS implementation.
3
4    endpoint server for the netlogon pipe
5
6    Copyright (C) Andrew Bartlett <abartlet@samba.org> 2004-2008
7    Copyright (C) Stefan Metzmacher <metze@samba.org>  2005
8    Copyright (C) Matthias Dieter Wallnöfer            2009-2010
9
10    This program is free software; you can redistribute it and/or modify
11    it under the terms of the GNU General Public License as published by
12    the Free Software Foundation; either version 3 of the License, or
13    (at your option) any later version.
14
15    This program is distributed in the hope that it will be useful,
16    but WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18    GNU General Public License for more details.
19
20    You should have received a copy of the GNU General Public License
21    along with this program.  If not, see <http://www.gnu.org/licenses/>.
22 */
23
24 #include "includes.h"
25 #include "rpc_server/dcerpc_server.h"
26 #include "auth/auth.h"
27 #include "auth/auth_sam_reply.h"
28 #include "dsdb/samdb/samdb.h"
29 #include "../lib/util/util_ldb.h"
30 #include "../libcli/auth/schannel.h"
31 #include "libcli/security/security.h"
32 #include "param/param.h"
33 #include "lib/messaging/irpc.h"
34 #include "librpc/gen_ndr/ndr_irpc_c.h"
35 #include "../libcli/ldap/ldap_ndr.h"
36 #include "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_lsa.h"
40 #include "librpc/gen_ndr/ndr_samr.h"
41 #include "librpc/gen_ndr/ndr_irpc.h"
42 #include "librpc/gen_ndr/ndr_winbind.h"
43 #include "librpc/gen_ndr/ndr_winbind_c.h"
44 #include "lib/socket/netif.h"
45 #include "rpc_server/common/sid_helper.h"
46 #include "lib/util/util_str_escape.h"
47
48 #define DCESRV_INTERFACE_NETLOGON_BIND(call, iface) \
49        dcesrv_interface_netlogon_bind(call, iface)
50
51 /*
52  * This #define allows the netlogon interface to accept invalid
53  * association groups, because association groups are to coordinate
54  * handles, and handles are not used in NETLOGON. This in turn avoids
55  * the need to coordinate these across multiple possible NETLOGON
56  * processes
57  */
58 #define DCESRV_INTERFACE_NETLOGON_FLAGS DCESRV_INTERFACE_FLAGS_HANDLES_NOT_USED
59
60 static NTSTATUS dcesrv_interface_netlogon_bind(struct dcesrv_call_state *dce_call,
61                                                const struct dcesrv_interface *iface)
62 {
63         return dcesrv_interface_bind_reject_connect(dce_call, iface);
64 }
65
66 struct netlogon_server_pipe_state {
67         struct netr_Credential client_challenge;
68         struct netr_Credential server_challenge;
69 };
70
71 static NTSTATUS dcesrv_netr_ServerReqChallenge(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
72                                         struct netr_ServerReqChallenge *r)
73 {
74         struct netlogon_server_pipe_state *pipe_state =
75                 talloc_get_type(dce_call->context->private_data, struct netlogon_server_pipe_state);
76         NTSTATUS ntstatus;
77
78         ZERO_STRUCTP(r->out.return_credentials);
79
80         if (pipe_state) {
81                 talloc_free(pipe_state);
82                 dce_call->context->private_data = NULL;
83         }
84
85         pipe_state = talloc(dce_call->context, struct netlogon_server_pipe_state);
86         NT_STATUS_HAVE_NO_MEMORY(pipe_state);
87
88         pipe_state->client_challenge = *r->in.credentials;
89
90         generate_random_buffer(pipe_state->server_challenge.data,
91                                sizeof(pipe_state->server_challenge.data));
92
93         *r->out.return_credentials = pipe_state->server_challenge;
94
95         dce_call->context->private_data = pipe_state;
96
97         ntstatus = schannel_save_challenge(dce_call->conn->dce_ctx->lp_ctx,
98                                            &pipe_state->client_challenge,
99                                            &pipe_state->server_challenge,
100                                            r->in.computer_name);
101         if (!NT_STATUS_IS_OK(ntstatus)) {
102                 return ntstatus;
103         }
104
105         return NT_STATUS_OK;
106 }
107
108 /*
109  * Do the actual processing of a netr_ServerAuthenticate3 message.
110  * called from dcesrv_netr_ServerAuthenticate3, which handles the logging.
111  */
112 static NTSTATUS dcesrv_netr_ServerAuthenticate3_helper(
113         struct dcesrv_call_state *dce_call,
114         TALLOC_CTX *mem_ctx,
115         struct netr_ServerAuthenticate3 *r,
116         const char **trust_account_for_search,
117         const char **trust_account_in_db,
118         struct dom_sid **sid)
119 {
120         struct netlogon_server_pipe_state *pipe_state =
121                 talloc_get_type(dce_call->context->private_data, struct netlogon_server_pipe_state);
122         bool challenge_valid = false;
123         struct netlogon_server_pipe_state challenge;
124         struct netlogon_creds_CredentialState *creds;
125         struct ldb_context *sam_ctx;
126         struct samr_Password *curNtHash = NULL;
127         struct samr_Password *prevNtHash = NULL;
128         uint32_t user_account_control;
129         int num_records;
130         struct ldb_message **msgs;
131         NTSTATUS nt_status;
132         const char *attrs[] = {"unicodePwd", "userAccountControl",
133                                "objectSid", "samAccountName", NULL};
134         uint32_t server_flags = 0;
135         uint32_t negotiate_flags = 0;
136         bool allow_nt4_crypto = lpcfg_allow_nt4_crypto(dce_call->conn->dce_ctx->lp_ctx);
137         bool reject_des_client = !allow_nt4_crypto;
138         bool reject_md5_client = lpcfg_reject_md5_clients(dce_call->conn->dce_ctx->lp_ctx);
139         int schannel = lpcfg_server_schannel(dce_call->conn->dce_ctx->lp_ctx);
140         bool reject_none_rpc = (schannel == true);
141
142         ZERO_STRUCTP(r->out.return_credentials);
143         *r->out.rid = 0;
144
145         if (pipe_state != NULL) {
146                 dce_call->context->private_data = NULL;
147
148                 /*
149                  * If we had a challenge remembered on the connection
150                  * consider this for usage. This can't be cleanup
151                  * by other clients.
152                  *
153                  * This is the default code path for typical clients
154                  * which call netr_ServerReqChallenge() and
155                  * netr_ServerAuthenticate3() on the same dcerpc connection.
156                  */
157                 challenge = *pipe_state;
158
159                 challenge_valid = true;
160
161         } else {
162                 NTSTATUS ntstatus;
163
164                 /*
165                  * Fallback and try to get the challenge from
166                  * the global cache.
167                  *
168                  * If too many clients are using this code path,
169                  * they may destroy their cache entries as the
170                  * TDB has a fixed size limited via a lossy hash
171                  *
172                  * The TDB used is the schannel store, which is
173                  * initialised at startup.
174                  *
175                  * NOTE: The challenge is deleted from the DB as soon as it is
176                  * fetched, to prevent reuse.
177                  *
178                  */
179
180                 ntstatus = schannel_get_challenge(dce_call->conn->dce_ctx->lp_ctx,
181                                                   &challenge.client_challenge,
182                                                   &challenge.server_challenge,
183                                                   r->in.computer_name);
184
185                 if (!NT_STATUS_IS_OK(ntstatus)) {
186                         ZERO_STRUCT(challenge);
187                 } else {
188                         challenge_valid = true;
189                 }
190         }
191
192         server_flags = NETLOGON_NEG_ACCOUNT_LOCKOUT |
193                        NETLOGON_NEG_PERSISTENT_SAMREPL |
194                        NETLOGON_NEG_ARCFOUR |
195                        NETLOGON_NEG_PROMOTION_COUNT |
196                        NETLOGON_NEG_CHANGELOG_BDC |
197                        NETLOGON_NEG_FULL_SYNC_REPL |
198                        NETLOGON_NEG_MULTIPLE_SIDS |
199                        NETLOGON_NEG_REDO |
200                        NETLOGON_NEG_PASSWORD_CHANGE_REFUSAL |
201                        NETLOGON_NEG_SEND_PASSWORD_INFO_PDC |
202                        NETLOGON_NEG_GENERIC_PASSTHROUGH |
203                        NETLOGON_NEG_CONCURRENT_RPC |
204                        NETLOGON_NEG_AVOID_ACCOUNT_DB_REPL |
205                        NETLOGON_NEG_AVOID_SECURITYAUTH_DB_REPL |
206                        NETLOGON_NEG_STRONG_KEYS |
207                        NETLOGON_NEG_TRANSITIVE_TRUSTS |
208                        NETLOGON_NEG_DNS_DOMAIN_TRUSTS |
209                        NETLOGON_NEG_PASSWORD_SET2 |
210                        NETLOGON_NEG_GETDOMAININFO |
211                        NETLOGON_NEG_CROSS_FOREST_TRUSTS |
212                        NETLOGON_NEG_NEUTRALIZE_NT4_EMULATION |
213                        NETLOGON_NEG_RODC_PASSTHROUGH |
214                        NETLOGON_NEG_SUPPORTS_AES |
215                        NETLOGON_NEG_AUTHENTICATED_RPC_LSASS |
216                        NETLOGON_NEG_AUTHENTICATED_RPC;
217
218         negotiate_flags = *r->in.negotiate_flags & server_flags;
219
220         if (negotiate_flags & NETLOGON_NEG_AUTHENTICATED_RPC) {
221                 reject_none_rpc = false;
222         }
223
224         if (negotiate_flags & NETLOGON_NEG_STRONG_KEYS) {
225                 reject_des_client = false;
226         }
227
228         if (negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
229                 reject_des_client = false;
230                 reject_md5_client = false;
231         }
232
233         if (reject_des_client || reject_md5_client) {
234                 /*
235                  * Here we match Windows 2012 and return no flags.
236                  */
237                 *r->out.negotiate_flags = 0;
238                 return NT_STATUS_DOWNGRADE_DETECTED;
239         }
240
241         /*
242          * This talloc_free is important to prevent re-use of the
243          * challenge.  We have to delay it this far due to NETApp
244          * servers per:
245          * https://bugzilla.samba.org/show_bug.cgi?id=11291
246          */
247         TALLOC_FREE(pipe_state);
248
249         /*
250          * At this point we must also cleanup the TDB cache
251          * entry, if we fail the client needs to call
252          * netr_ServerReqChallenge again.
253          *
254          * Note: this handles a non existing record just fine,
255          * the r->in.computer_name might not be the one used
256          * in netr_ServerReqChallenge(), but we are trying to
257          * just tidy up the normal case to prevent re-use.
258          */
259         schannel_delete_challenge(dce_call->conn->dce_ctx->lp_ctx,
260                                   r->in.computer_name);
261
262         /*
263          * According to Microsoft (see bugid #6099)
264          * Windows 7 looks at the negotiate_flags
265          * returned in this structure *even if the
266          * call fails with access denied!
267          */
268         *r->out.negotiate_flags = negotiate_flags;
269
270         if (reject_none_rpc) {
271                 /* schannel must be used, but client did not offer it. */
272                 DEBUG(0,("%s: schannel required but client failed "
273                         "to offer it. Client was %s\n",
274                          __func__,
275                          log_escape(mem_ctx, r->in.account_name)));
276                 return NT_STATUS_ACCESS_DENIED;
277         }
278
279         switch (r->in.secure_channel_type) {
280         case SEC_CHAN_WKSTA:
281         case SEC_CHAN_DNS_DOMAIN:
282         case SEC_CHAN_DOMAIN:
283         case SEC_CHAN_BDC:
284         case SEC_CHAN_RODC:
285                 break;
286         case SEC_CHAN_NULL:
287                 return NT_STATUS_INVALID_PARAMETER;
288         default:
289                 DEBUG(1, ("Client asked for an invalid secure channel type: %d\n",
290                           r->in.secure_channel_type));
291                 return NT_STATUS_INVALID_PARAMETER;
292         }
293
294         sam_ctx = samdb_connect(mem_ctx,
295                                 dce_call->event_ctx,
296                                 dce_call->conn->dce_ctx->lp_ctx,
297                                 system_session(dce_call->conn->dce_ctx->lp_ctx),
298                                 dce_call->conn->remote_address,
299                                 0);
300         if (sam_ctx == NULL) {
301                 return NT_STATUS_INVALID_SYSTEM_SERVICE;
302         }
303
304         if (r->in.secure_channel_type == SEC_CHAN_DOMAIN ||
305             r->in.secure_channel_type == SEC_CHAN_DNS_DOMAIN)
306         {
307                 struct ldb_message *tdo_msg = NULL;
308                 const char * const tdo_attrs[] = {
309                         "trustAuthIncoming",
310                         "trustAttributes",
311                         "flatName",
312                         NULL
313                 };
314                 char *encoded_name = NULL;
315                 size_t len;
316                 const char *flatname = NULL;
317                 char trailer = '$';
318                 bool require_trailer = true;
319                 const char *netbios = NULL;
320                 const char *dns = NULL;
321
322                 if (r->in.secure_channel_type == SEC_CHAN_DNS_DOMAIN) {
323                         trailer = '.';
324                         require_trailer = false;
325                 }
326
327                 encoded_name = ldb_binary_encode_string(mem_ctx,
328                                                         r->in.account_name);
329                 if (encoded_name == NULL) {
330                         return NT_STATUS_NO_MEMORY;
331                 }
332
333                 len = strlen(encoded_name);
334                 if (len < 2) {
335                         return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
336                 }
337
338                 if (require_trailer && encoded_name[len - 1] != trailer) {
339                         return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
340                 }
341                 encoded_name[len - 1] = '\0';
342
343                 if (r->in.secure_channel_type == SEC_CHAN_DNS_DOMAIN) {
344                         dns = encoded_name;
345                 } else {
346                         netbios = encoded_name;
347                 }
348
349                 nt_status = dsdb_trust_search_tdo(sam_ctx,
350                                                   netbios, dns,
351                                                   tdo_attrs, mem_ctx, &tdo_msg);
352                 if (NT_STATUS_EQUAL(nt_status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
353                         DEBUG(2, ("Client asked for a trusted domain secure channel, "
354                                   "but there's no tdo for [%s] => [%s] \n",
355                                   log_escape(mem_ctx, r->in.account_name),
356                                   encoded_name));
357                         return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
358                 }
359                 if (!NT_STATUS_IS_OK(nt_status)) {
360                         return nt_status;
361                 }
362
363                 nt_status = dsdb_trust_get_incoming_passwords(tdo_msg, mem_ctx,
364                                                               &curNtHash,
365                                                               &prevNtHash);
366                 if (NT_STATUS_EQUAL(nt_status, NT_STATUS_ACCOUNT_DISABLED)) {
367                         return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
368                 }
369                 if (!NT_STATUS_IS_OK(nt_status)) {
370                         return nt_status;
371                 }
372
373                 flatname = ldb_msg_find_attr_as_string(tdo_msg, "flatName", NULL);
374                 if (flatname == NULL) {
375                         return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
376                 }
377
378                 *trust_account_for_search = talloc_asprintf(mem_ctx, "%s$", flatname);
379                 if (*trust_account_for_search == NULL) {
380                         return NT_STATUS_NO_MEMORY;
381                 }
382         } else {
383                 *trust_account_for_search = r->in.account_name;
384         }
385
386         /* pull the user attributes */
387         num_records = gendb_search(sam_ctx, mem_ctx, NULL, &msgs, attrs,
388                                    "(&(sAMAccountName=%s)(objectclass=user))",
389                                    ldb_binary_encode_string(mem_ctx,
390                                                             *trust_account_for_search));
391
392         if (num_records == 0) {
393                 DEBUG(3,("Couldn't find user [%s] in samdb.\n",
394                          log_escape(mem_ctx, r->in.account_name)));
395                 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
396         }
397
398         if (num_records > 1) {
399                 DEBUG(0,("Found %d records matching user [%s]\n",
400                          num_records,
401                          log_escape(mem_ctx, r->in.account_name)));
402                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
403         }
404
405         *trust_account_in_db = ldb_msg_find_attr_as_string(msgs[0],
406                                                            "samAccountName",
407                                                            NULL);
408         if (*trust_account_in_db == NULL) {
409                 DEBUG(0,("No samAccountName returned in record matching user [%s]\n",
410                          r->in.account_name));
411                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
412         }
413         
414         user_account_control = ldb_msg_find_attr_as_uint(msgs[0], "userAccountControl", 0);
415
416         if (user_account_control & UF_ACCOUNTDISABLE) {
417                 DEBUG(1, ("Account [%s] is disabled\n",
418                           log_escape(mem_ctx, r->in.account_name)));
419                 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
420         }
421
422         if (r->in.secure_channel_type == SEC_CHAN_WKSTA) {
423                 if (!(user_account_control & UF_WORKSTATION_TRUST_ACCOUNT)) {
424                         DEBUG(1, ("Client asked for a workstation secure channel, but is not a workstation (member server) acb flags: 0x%x\n", user_account_control));
425                         return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
426                 }
427         } else if (r->in.secure_channel_type == SEC_CHAN_DOMAIN ||
428                    r->in.secure_channel_type == SEC_CHAN_DNS_DOMAIN) {
429                 if (!(user_account_control & UF_INTERDOMAIN_TRUST_ACCOUNT)) {
430                         DEBUG(1, ("Client asked for a trusted domain secure channel, but is not a trusted domain: acb flags: 0x%x\n", user_account_control));
431
432                         return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
433                 }
434         } else if (r->in.secure_channel_type == SEC_CHAN_BDC) {
435                 if (!(user_account_control & UF_SERVER_TRUST_ACCOUNT)) {
436                         DEBUG(1, ("Client asked for a server secure channel, but is not a server (domain controller): acb flags: 0x%x\n", user_account_control));
437                         return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
438                 }
439         } else if (r->in.secure_channel_type == SEC_CHAN_RODC) {
440                 if (!(user_account_control & UF_PARTIAL_SECRETS_ACCOUNT)) {
441                         DEBUG(1, ("Client asked for a RODC secure channel, but is not a RODC: acb flags: 0x%x\n", user_account_control));
442                         return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
443                 }
444         } else {
445                 /* we should never reach this */
446                 return NT_STATUS_INTERNAL_ERROR;
447         }
448
449         if (!(user_account_control & UF_INTERDOMAIN_TRUST_ACCOUNT)) {
450                 nt_status = samdb_result_passwords_no_lockout(mem_ctx,
451                                         dce_call->conn->dce_ctx->lp_ctx,
452                                         msgs[0], NULL, &curNtHash);
453                 if (!NT_STATUS_IS_OK(nt_status)) {
454                         return NT_STATUS_ACCESS_DENIED;
455                 }
456         }
457
458         if (curNtHash == NULL) {
459                 return NT_STATUS_ACCESS_DENIED;
460         }
461
462         if (!challenge_valid) {
463                 DEBUG(1, ("No challenge requested by client [%s/%s], "
464                           "cannot authenticate\n",
465                           log_escape(mem_ctx, r->in.computer_name),
466                           log_escape(mem_ctx, r->in.account_name)));
467                 return NT_STATUS_ACCESS_DENIED;
468         }
469
470         creds = netlogon_creds_server_init(mem_ctx,
471                                            r->in.account_name,
472                                            r->in.computer_name,
473                                            r->in.secure_channel_type,
474                                            &challenge.client_challenge,
475                                            &challenge.server_challenge,
476                                            curNtHash,
477                                            r->in.credentials,
478                                            r->out.return_credentials,
479                                            negotiate_flags);
480         if (creds == NULL && prevNtHash != NULL) {
481                 /*
482                  * We fallback to the previous password for domain trusts.
483                  *
484                  * Note that lpcfg_old_password_allowed_period() doesn't
485                  * apply here.
486                  */
487                 creds = netlogon_creds_server_init(mem_ctx,
488                                                    r->in.account_name,
489                                                    r->in.computer_name,
490                                                    r->in.secure_channel_type,
491                                                    &challenge.client_challenge,
492                                                    &challenge.server_challenge,
493                                                    prevNtHash,
494                                                    r->in.credentials,
495                                                    r->out.return_credentials,
496                                                    negotiate_flags);
497         }
498
499         if (creds == NULL) {
500                 return NT_STATUS_ACCESS_DENIED;
501         }
502         creds->sid = samdb_result_dom_sid(creds, msgs[0], "objectSid");
503         *sid = talloc_memdup(mem_ctx, creds->sid, sizeof(struct dom_sid));
504
505         nt_status = schannel_save_creds_state(mem_ctx,
506                                               dce_call->conn->dce_ctx->lp_ctx,
507                                               creds);
508         if (!NT_STATUS_IS_OK(nt_status)) {
509                 ZERO_STRUCTP(r->out.return_credentials);
510                 return nt_status;
511         }
512
513         *r->out.rid = samdb_result_rid_from_sid(mem_ctx, msgs[0],
514                                                 "objectSid", 0);
515
516         return NT_STATUS_OK;
517 }
518
519 /*
520  * Log a netr_ServerAuthenticate3 request, and then invoke
521  * dcesrv_netr_ServerAuthenticate3_helper to perform the actual processing
522  */
523 static NTSTATUS dcesrv_netr_ServerAuthenticate3(
524         struct dcesrv_call_state *dce_call,
525         TALLOC_CTX *mem_ctx,
526         struct netr_ServerAuthenticate3 *r)
527 {
528         NTSTATUS status;
529         struct dom_sid *sid = NULL;
530         const char *trust_account_for_search = NULL;
531         const char *trust_account_in_db = NULL;
532         struct auth_usersupplied_info ui = {
533                 .local_host = dce_call->conn->local_address,
534                 .remote_host = dce_call->conn->remote_address,
535                 .client = {
536                         .account_name = r->in.account_name,
537                         .domain_name = lpcfg_workgroup(dce_call->conn->dce_ctx->lp_ctx),
538                 },
539                 .service_description = "NETLOGON",
540                 .auth_description = "ServerAuthenticate",
541                 .netlogon_trust_account = {
542                         .computer_name = r->in.computer_name,
543                         .negotiate_flags = *r->in.negotiate_flags,
544                         .secure_channel_type = r->in.secure_channel_type,
545                 },
546         };
547
548         status = dcesrv_netr_ServerAuthenticate3_helper(dce_call,
549                                                         mem_ctx,
550                                                         r,
551                                                         &trust_account_for_search,
552                                                         &trust_account_in_db,
553                                                         &sid);
554         ui.netlogon_trust_account.sid = sid;
555         ui.netlogon_trust_account.account_name = trust_account_in_db;
556         ui.mapped.account_name = trust_account_for_search;
557         log_authentication_event(
558                 dce_call->conn->msg_ctx,
559                 dce_call->conn->dce_ctx->lp_ctx,
560                 NULL,
561                 &ui,
562                 status,
563                 lpcfg_workgroup(dce_call->conn->dce_ctx->lp_ctx),
564                 trust_account_in_db,
565                 NULL,
566                 sid);
567
568         return status;
569 }
570 static NTSTATUS dcesrv_netr_ServerAuthenticate(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
571                                         struct netr_ServerAuthenticate *r)
572 {
573         struct netr_ServerAuthenticate3 a;
574         uint32_t rid;
575         /* TODO:
576          * negotiate_flags is used as an [in] parameter
577          * so it need to be initialised.
578          *
579          * (I think ... = 0; seems wrong here --metze)
580          */
581         uint32_t negotiate_flags_in = 0;
582         uint32_t negotiate_flags_out = 0;
583
584         a.in.server_name                = r->in.server_name;
585         a.in.account_name               = r->in.account_name;
586         a.in.secure_channel_type        = r->in.secure_channel_type;
587         a.in.computer_name              = r->in.computer_name;
588         a.in.credentials                = r->in.credentials;
589         a.in.negotiate_flags            = &negotiate_flags_in;
590
591         a.out.return_credentials        = r->out.return_credentials;
592         a.out.rid                       = &rid;
593         a.out.negotiate_flags           = &negotiate_flags_out;
594
595         return dcesrv_netr_ServerAuthenticate3(dce_call, mem_ctx, &a);
596 }
597
598 static NTSTATUS dcesrv_netr_ServerAuthenticate2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
599                                          struct netr_ServerAuthenticate2 *r)
600 {
601         struct netr_ServerAuthenticate3 r3;
602         uint32_t rid = 0;
603
604         r3.in.server_name = r->in.server_name;
605         r3.in.account_name = r->in.account_name;
606         r3.in.secure_channel_type = r->in.secure_channel_type;
607         r3.in.computer_name = r->in.computer_name;
608         r3.in.credentials = r->in.credentials;
609         r3.out.return_credentials = r->out.return_credentials;
610         r3.in.negotiate_flags = r->in.negotiate_flags;
611         r3.out.negotiate_flags = r->out.negotiate_flags;
612         r3.out.rid = &rid;
613
614         return dcesrv_netr_ServerAuthenticate3(dce_call, mem_ctx, &r3);
615 }
616
617 /*
618  * NOTE: The following functions are nearly identical to the ones available in
619  * source3/rpc_server/srv_nelog_nt.c
620  * The reason we keep 2 copies is that they use different structures to
621  * represent the auth_info and the decrpc pipes.
622  */
623
624 /*
625  * If schannel is required for this call test that it actually is available.
626  */
627 static NTSTATUS schannel_check_required(const struct dcesrv_auth *auth_info,
628                                         const char *computer_name,
629                                         bool integrity, bool privacy)
630 {
631
632         if (auth_info && auth_info->auth_type == DCERPC_AUTH_TYPE_SCHANNEL) {
633                 if (!privacy && !integrity) {
634                         return NT_STATUS_OK;
635                 }
636
637                 if ((!privacy && integrity) &&
638                     auth_info->auth_level == DCERPC_AUTH_LEVEL_INTEGRITY) {
639                         return NT_STATUS_OK;
640                 }
641
642                 if ((privacy || integrity) &&
643                     auth_info->auth_level == DCERPC_AUTH_LEVEL_PRIVACY) {
644                         return NT_STATUS_OK;
645                 }
646         }
647
648         /* test didn't pass */
649         DEBUG(0, ("schannel_check_required: [%s] is not using schannel\n",
650                   computer_name));
651
652         return NT_STATUS_ACCESS_DENIED;
653 }
654
655 static NTSTATUS dcesrv_netr_creds_server_step_check(struct dcesrv_call_state *dce_call,
656                                                     TALLOC_CTX *mem_ctx,
657                                                     const char *computer_name,
658                                                     struct netr_Authenticator *received_authenticator,
659                                                     struct netr_Authenticator *return_authenticator,
660                                                     struct netlogon_creds_CredentialState **creds_out)
661 {
662         NTSTATUS nt_status;
663         int schannel = lpcfg_server_schannel(dce_call->conn->dce_ctx->lp_ctx);
664         bool schannel_global_required = (schannel == true);
665
666         if (schannel_global_required) {
667                 nt_status = schannel_check_required(&dce_call->conn->auth_state,
668                                                     computer_name,
669                                                     true, false);
670                 if (!NT_STATUS_IS_OK(nt_status)) {
671                         return nt_status;
672                 }
673         }
674
675         nt_status = schannel_check_creds_state(mem_ctx,
676                                                dce_call->conn->dce_ctx->lp_ctx,
677                                                computer_name,
678                                                received_authenticator,
679                                                return_authenticator,
680                                                creds_out);
681         return nt_status;
682 }
683
684 /*
685   Change the machine account password for the currently connected
686   client.  Supplies only the NT#.
687 */
688
689 static NTSTATUS dcesrv_netr_ServerPasswordSet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
690                                        struct netr_ServerPasswordSet *r)
691 {
692         struct netlogon_creds_CredentialState *creds;
693         struct ldb_context *sam_ctx;
694         const char * const attrs[] = { "unicodePwd", NULL };
695         struct ldb_message **res;
696         struct samr_Password *oldNtHash;
697         NTSTATUS nt_status;
698         int ret;
699
700         nt_status = dcesrv_netr_creds_server_step_check(dce_call,
701                                                         mem_ctx,
702                                                         r->in.computer_name,
703                                                         r->in.credential, r->out.return_authenticator,
704                                                         &creds);
705         NT_STATUS_NOT_OK_RETURN(nt_status);
706
707         sam_ctx = samdb_connect(mem_ctx,
708                                 dce_call->event_ctx,
709                                 dce_call->conn->dce_ctx->lp_ctx,
710                                 system_session(dce_call->conn->dce_ctx->lp_ctx),
711                                 dce_call->conn->remote_address,
712                                 0);
713         if (sam_ctx == NULL) {
714                 return NT_STATUS_INVALID_SYSTEM_SERVICE;
715         }
716
717         netlogon_creds_des_decrypt(creds, r->in.new_password);
718
719         /* fetch the old password hashes (the NT hash has to exist) */
720
721         ret = gendb_search(sam_ctx, mem_ctx, NULL, &res, attrs,
722                            "(&(objectClass=user)(objectSid=%s))",
723                            ldap_encode_ndr_dom_sid(mem_ctx, creds->sid));
724         if (ret != 1) {
725                 return NT_STATUS_WRONG_PASSWORD;
726         }
727
728         nt_status = samdb_result_passwords_no_lockout(mem_ctx,
729                                                       dce_call->conn->dce_ctx->lp_ctx,
730                                                       res[0], NULL, &oldNtHash);
731         if (!NT_STATUS_IS_OK(nt_status) || !oldNtHash) {
732                 return NT_STATUS_WRONG_PASSWORD;
733         }
734
735         /* Using the sid for the account as the key, set the password */
736         nt_status = samdb_set_password_sid(sam_ctx, mem_ctx,
737                                            creds->sid,
738                                            NULL, /* Don't have version */
739                                            NULL, /* Don't have plaintext */
740                                            NULL, r->in.new_password,
741                                            NULL, oldNtHash, /* Password change */
742                                            NULL, NULL);
743         return nt_status;
744 }
745
746 /*
747   Change the machine account password for the currently connected
748   client.  Supplies new plaintext.
749 */
750 static NTSTATUS dcesrv_netr_ServerPasswordSet2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
751                                        struct netr_ServerPasswordSet2 *r)
752 {
753         struct netlogon_creds_CredentialState *creds;
754         struct ldb_context *sam_ctx;
755         const char * const attrs[] = { "dBCSPwd", "unicodePwd", NULL };
756         struct ldb_message **res;
757         struct samr_Password *oldLmHash, *oldNtHash;
758         struct NL_PASSWORD_VERSION version = {};
759         const uint32_t *new_version = NULL;
760         NTSTATUS nt_status;
761         DATA_BLOB new_password;
762         int ret;
763         struct samr_CryptPassword password_buf;
764
765         nt_status = dcesrv_netr_creds_server_step_check(dce_call,
766                                                         mem_ctx,
767                                                         r->in.computer_name,
768                                                         r->in.credential, r->out.return_authenticator,
769                                                         &creds);
770         NT_STATUS_NOT_OK_RETURN(nt_status);
771
772         sam_ctx = samdb_connect(mem_ctx,
773                                 dce_call->event_ctx,
774                                 dce_call->conn->dce_ctx->lp_ctx,
775                                 system_session(dce_call->conn->dce_ctx->lp_ctx),
776                                 dce_call->conn->remote_address,
777                                 0);
778         if (sam_ctx == NULL) {
779                 return NT_STATUS_INVALID_SYSTEM_SERVICE;
780         }
781
782         memcpy(password_buf.data, r->in.new_password->data, 512);
783         SIVAL(password_buf.data, 512, r->in.new_password->length);
784
785         if (creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
786                 netlogon_creds_aes_decrypt(creds, password_buf.data, 516);
787         } else {
788                 netlogon_creds_arcfour_crypt(creds, password_buf.data, 516);
789         }
790
791         switch (creds->secure_channel_type) {
792         case SEC_CHAN_DOMAIN:
793         case SEC_CHAN_DNS_DOMAIN: {
794                 uint32_t len = IVAL(password_buf.data, 512);
795                 if (len <= 500) {
796                         uint32_t ofs = 500 - len;
797                         uint8_t *p;
798
799                         p = password_buf.data + ofs;
800
801                         version.ReservedField = IVAL(p, 0);
802                         version.PasswordVersionNumber = IVAL(p, 4);
803                         version.PasswordVersionPresent = IVAL(p, 8);
804
805                         if (version.PasswordVersionPresent == NETLOGON_PASSWORD_VERSION_NUMBER_PRESENT) {
806                                 new_version = &version.PasswordVersionNumber;
807                         }
808                 }}
809                 break;
810         default:
811                 break;
812         }
813
814         if (!extract_pw_from_buffer(mem_ctx, password_buf.data, &new_password)) {
815                 DEBUG(3,("samr: failed to decode password buffer\n"));
816                 return NT_STATUS_WRONG_PASSWORD;
817         }
818
819         /* fetch the old password hashes (at least one of both has to exist) */
820
821         ret = gendb_search(sam_ctx, mem_ctx, NULL, &res, attrs,
822                            "(&(objectClass=user)(objectSid=%s))",
823                            ldap_encode_ndr_dom_sid(mem_ctx, creds->sid));
824         if (ret != 1) {
825                 return NT_STATUS_WRONG_PASSWORD;
826         }
827
828         nt_status = samdb_result_passwords_no_lockout(mem_ctx,
829                                                       dce_call->conn->dce_ctx->lp_ctx,
830                                                       res[0], &oldLmHash, &oldNtHash);
831         if (!NT_STATUS_IS_OK(nt_status) || (!oldLmHash && !oldNtHash)) {
832                 return NT_STATUS_WRONG_PASSWORD;
833         }
834
835         /* Using the sid for the account as the key, set the password */
836         nt_status = samdb_set_password_sid(sam_ctx, mem_ctx,
837                                            creds->sid,
838                                            new_version,
839                                            &new_password, /* we have plaintext */
840                                            NULL, NULL,
841                                            oldLmHash, oldNtHash, /* Password change */
842                                            NULL, NULL);
843         return nt_status;
844 }
845
846
847 /*
848   netr_LogonUasLogon
849 */
850 static WERROR dcesrv_netr_LogonUasLogon(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
851                                  struct netr_LogonUasLogon *r)
852 {
853         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
854 }
855
856
857 /*
858   netr_LogonUasLogoff
859 */
860 static WERROR dcesrv_netr_LogonUasLogoff(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
861                        struct netr_LogonUasLogoff *r)
862 {
863         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
864 }
865
866
867 static NTSTATUS dcesrv_netr_LogonSamLogon_check(struct dcesrv_call_state *dce_call,
868                                                 const struct netr_LogonSamLogonEx *r)
869 {
870         switch (r->in.logon_level) {
871         case NetlogonInteractiveInformation:
872         case NetlogonServiceInformation:
873         case NetlogonInteractiveTransitiveInformation:
874         case NetlogonServiceTransitiveInformation:
875                 if (r->in.logon->password == NULL) {
876                         return NT_STATUS_INVALID_PARAMETER;
877                 }
878
879                 switch (r->in.validation_level) {
880                 case NetlogonValidationSamInfo:  /* 2 */
881                 case NetlogonValidationSamInfo2: /* 3 */
882                 case NetlogonValidationSamInfo4: /* 6 */
883                         break;
884                 default:
885                         return NT_STATUS_INVALID_INFO_CLASS;
886                 }
887
888                 break;
889         case NetlogonNetworkInformation:
890         case NetlogonNetworkTransitiveInformation:
891                 if (r->in.logon->network == NULL) {
892                         return NT_STATUS_INVALID_PARAMETER;
893                 }
894
895                 switch (r->in.validation_level) {
896                 case NetlogonValidationSamInfo:  /* 2 */
897                 case NetlogonValidationSamInfo2: /* 3 */
898                 case NetlogonValidationSamInfo4: /* 6 */
899                         break;
900                 default:
901                         return NT_STATUS_INVALID_INFO_CLASS;
902                 }
903
904                 break;
905
906         case NetlogonGenericInformation:
907                 if (r->in.logon->generic == NULL) {
908                         return NT_STATUS_INVALID_PARAMETER;
909                 }
910
911                 switch (r->in.validation_level) {
912                 /* TODO: case NetlogonValidationGenericInfo: 4 */
913                 case NetlogonValidationGenericInfo2: /* 5 */
914                         break;
915                 default:
916                         return NT_STATUS_INVALID_INFO_CLASS;
917                 }
918
919                 break;
920         default:
921                 return NT_STATUS_INVALID_PARAMETER;
922         }
923
924         switch (r->in.validation_level) {
925         case NetlogonValidationSamInfo4: /* 6 */
926                 if (dce_call->conn->auth_state.auth_level < DCERPC_AUTH_LEVEL_PRIVACY) {
927                         return NT_STATUS_INVALID_PARAMETER;
928                 }
929                 break;
930
931         default:
932                 break;
933         }
934
935         return NT_STATUS_OK;
936 }
937
938 struct dcesrv_netr_LogonSamLogon_base_state {
939         struct dcesrv_call_state *dce_call;
940
941         TALLOC_CTX *mem_ctx;
942
943         struct netlogon_creds_CredentialState *creds;
944
945         struct netr_LogonSamLogonEx r;
946
947         uint32_t _ignored_flags;
948
949         struct {
950                 struct netr_LogonSamLogon *lsl;
951                 struct netr_LogonSamLogonWithFlags *lslwf;
952                 struct netr_LogonSamLogonEx *lslex;
953         } _r;
954
955         struct kdc_check_generic_kerberos kr;
956 };
957
958 static void dcesrv_netr_LogonSamLogon_base_auth_done(struct tevent_req *subreq);
959 static void dcesrv_netr_LogonSamLogon_base_krb5_done(struct tevent_req *subreq);
960 static void dcesrv_netr_LogonSamLogon_base_reply(
961         struct dcesrv_netr_LogonSamLogon_base_state *state);
962
963 /*
964   netr_LogonSamLogon_base
965
966   This version of the function allows other wrappers to say 'do not check the credentials'
967
968   We can't do the traditional 'wrapping' format completely, as this
969   function must only run under schannel
970 */
971 static NTSTATUS dcesrv_netr_LogonSamLogon_base_call(struct dcesrv_netr_LogonSamLogon_base_state *state)
972 {
973         struct dcesrv_call_state *dce_call = state->dce_call;
974         TALLOC_CTX *mem_ctx = state->mem_ctx;
975         struct netr_LogonSamLogonEx *r = &state->r;
976         struct netlogon_creds_CredentialState *creds = state->creds;
977         struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
978         const char *workgroup = lpcfg_workgroup(lp_ctx);
979         struct auth4_context *auth_context = NULL;
980         struct auth_usersupplied_info *user_info = NULL;
981         NTSTATUS nt_status;
982         struct tevent_req *subreq = NULL;
983
984         *r->out.authoritative = 1;
985
986         if (*r->in.flags & NETLOGON_SAMLOGON_FLAG_PASS_TO_FOREST_ROOT) {
987                 /*
988                  * Currently we're always the forest root ourself.
989                  */
990                 return NT_STATUS_NO_SUCH_USER;
991         }
992
993         if (*r->in.flags & NETLOGON_SAMLOGON_FLAG_PASS_CROSS_FOREST_HOP) {
994                 /*
995                  * Currently we don't support trusts correctly yet.
996                  */
997                 return NT_STATUS_NO_SUCH_USER;
998         }
999
1000         user_info = talloc_zero(mem_ctx, struct auth_usersupplied_info);
1001         NT_STATUS_HAVE_NO_MEMORY(user_info);
1002
1003         user_info->service_description = "SamLogon";
1004
1005         netlogon_creds_decrypt_samlogon_logon(creds,
1006                                               r->in.logon_level,
1007                                               r->in.logon);
1008
1009         switch (r->in.logon_level) {
1010         case NetlogonInteractiveInformation:
1011         case NetlogonServiceInformation:
1012         case NetlogonInteractiveTransitiveInformation:
1013         case NetlogonServiceTransitiveInformation:
1014         case NetlogonNetworkInformation:
1015         case NetlogonNetworkTransitiveInformation:
1016
1017                 nt_status = auth_context_create_for_netlogon(mem_ctx,
1018                                         dce_call->event_ctx, dce_call->msg_ctx,
1019                                         dce_call->conn->dce_ctx->lp_ctx,
1020                                         &auth_context);
1021                 NT_STATUS_NOT_OK_RETURN(nt_status);
1022
1023                 user_info->remote_host = dce_call->conn->remote_address;
1024                 user_info->local_host = dce_call->conn->local_address;
1025
1026                 user_info->netlogon_trust_account.secure_channel_type
1027                         = creds->secure_channel_type;
1028                 user_info->netlogon_trust_account.negotiate_flags
1029                         = creds->negotiate_flags;
1030
1031                 /*
1032                  * These two can be unrelated when the account is
1033                  * actually that of a trusted domain, so we want to
1034                  * know which DC in that trusted domain contacted
1035                  * us
1036                  */
1037                 user_info->netlogon_trust_account.computer_name
1038                         = creds->computer_name;
1039                 user_info->netlogon_trust_account.account_name
1040                         = creds->account_name;
1041                 user_info->netlogon_trust_account.sid
1042                         = creds->sid;
1043
1044         default:
1045                 /* We do not need to set up the user_info in this case */
1046                 break;
1047         }
1048
1049         switch (r->in.logon_level) {
1050         case NetlogonInteractiveInformation:
1051         case NetlogonServiceInformation:
1052         case NetlogonInteractiveTransitiveInformation:
1053         case NetlogonServiceTransitiveInformation:
1054                 user_info->auth_description = "interactive";
1055
1056                 user_info->logon_parameters
1057                         = r->in.logon->password->identity_info.parameter_control;
1058                 user_info->client.account_name
1059                         = r->in.logon->password->identity_info.account_name.string;
1060                 user_info->client.domain_name
1061                         = r->in.logon->password->identity_info.domain_name.string;
1062                 user_info->workstation_name
1063                         = r->in.logon->password->identity_info.workstation.string;
1064                 user_info->flags |= USER_INFO_INTERACTIVE_LOGON;
1065                 user_info->password_state = AUTH_PASSWORD_HASH;
1066
1067                 user_info->password.hash.lanman = talloc(user_info, struct samr_Password);
1068                 NT_STATUS_HAVE_NO_MEMORY(user_info->password.hash.lanman);
1069                 *user_info->password.hash.lanman = r->in.logon->password->lmpassword;
1070
1071                 user_info->password.hash.nt = talloc(user_info, struct samr_Password);
1072                 NT_STATUS_HAVE_NO_MEMORY(user_info->password.hash.nt);
1073                 *user_info->password.hash.nt = r->in.logon->password->ntpassword;
1074
1075                 break;
1076         case NetlogonNetworkInformation:
1077         case NetlogonNetworkTransitiveInformation:
1078                 user_info->auth_description = "network";
1079
1080                 nt_status = auth_context_set_challenge(
1081                         auth_context,
1082                         r->in.logon->network->challenge,
1083                         "netr_LogonSamLogonWithFlags");
1084                 NT_STATUS_NOT_OK_RETURN(nt_status);
1085
1086                 user_info->logon_parameters
1087                         = r->in.logon->network->identity_info.parameter_control;
1088                 user_info->client.account_name
1089                         = r->in.logon->network->identity_info.account_name.string;
1090                 user_info->client.domain_name
1091                         = r->in.logon->network->identity_info.domain_name.string;
1092                 user_info->workstation_name
1093                         = r->in.logon->network->identity_info.workstation.string;
1094
1095                 user_info->password_state = AUTH_PASSWORD_RESPONSE;
1096                 user_info->password.response.lanman = data_blob_talloc(mem_ctx, r->in.logon->network->lm.data, r->in.logon->network->lm.length);
1097                 user_info->password.response.nt = data_blob_talloc(mem_ctx, r->in.logon->network->nt.data, r->in.logon->network->nt.length);
1098
1099                 nt_status = NTLMv2_RESPONSE_verify_netlogon_creds(
1100                                         user_info->client.account_name,
1101                                         user_info->client.domain_name,
1102                                         user_info->password.response.nt,
1103                                         creds, workgroup);
1104                 NT_STATUS_NOT_OK_RETURN(nt_status);
1105
1106                 break;
1107
1108
1109         case NetlogonGenericInformation:
1110         {
1111                 if (creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
1112                         /* OK */
1113                 } else if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
1114                         /* OK */
1115                 } else {
1116                         /* Using DES to verify kerberos tickets makes no sense */
1117                         return NT_STATUS_INVALID_PARAMETER;
1118                 }
1119
1120                 if (strcmp(r->in.logon->generic->package_name.string, "Kerberos") == 0) {
1121                         struct dcerpc_binding_handle *irpc_handle;
1122                         struct netr_GenericInfo2 *generic = talloc_zero(mem_ctx, struct netr_GenericInfo2);
1123                         NT_STATUS_HAVE_NO_MEMORY(generic);
1124
1125                         r->out.validation->generic = generic;
1126
1127                         irpc_handle = irpc_binding_handle_by_name(mem_ctx,
1128                                                                   dce_call->msg_ctx,
1129                                                                   "kdc_server",
1130                                                                   &ndr_table_irpc);
1131                         if (irpc_handle == NULL) {
1132                                 return NT_STATUS_NO_LOGON_SERVERS;
1133                         }
1134
1135                         state->kr.in.generic_request =
1136                                 data_blob_const(r->in.logon->generic->data,
1137                                                 r->in.logon->generic->length);
1138
1139                         /*
1140                          * 60 seconds should be enough
1141                          */
1142                         dcerpc_binding_handle_set_timeout(irpc_handle, 60);
1143                         subreq = dcerpc_kdc_check_generic_kerberos_r_send(state,
1144                                                 state->dce_call->event_ctx,
1145                                                 irpc_handle, &state->kr);
1146                         if (subreq == NULL) {
1147                                 return NT_STATUS_NO_MEMORY;
1148                         }
1149                         state->dce_call->state_flags |= DCESRV_CALL_STATE_FLAG_ASYNC;
1150                         tevent_req_set_callback(subreq,
1151                                         dcesrv_netr_LogonSamLogon_base_krb5_done,
1152                                         state);
1153                         return NT_STATUS_OK;
1154                 }
1155
1156                 /* Until we get an implemetnation of these other packages */
1157                 return NT_STATUS_INVALID_PARAMETER;
1158         }
1159         default:
1160                 return NT_STATUS_INVALID_PARAMETER;
1161         }
1162
1163         subreq = auth_check_password_send(state, state->dce_call->event_ctx,
1164                                           auth_context, user_info);
1165         state->dce_call->state_flags |= DCESRV_CALL_STATE_FLAG_ASYNC;
1166         tevent_req_set_callback(subreq,
1167                                 dcesrv_netr_LogonSamLogon_base_auth_done,
1168                                 state);
1169         return NT_STATUS_OK;
1170 }
1171
1172 static void dcesrv_netr_LogonSamLogon_base_auth_done(struct tevent_req *subreq)
1173 {
1174         struct dcesrv_netr_LogonSamLogon_base_state *state =
1175                 tevent_req_callback_data(subreq,
1176                 struct dcesrv_netr_LogonSamLogon_base_state);
1177         TALLOC_CTX *mem_ctx = state->mem_ctx;
1178         struct netr_LogonSamLogonEx *r = &state->r;
1179         struct auth_user_info_dc *user_info_dc = NULL;
1180         struct netr_SamInfo2 *sam2 = NULL;
1181         struct netr_SamInfo3 *sam3 = NULL;
1182         struct netr_SamInfo6 *sam6 = NULL;
1183         NTSTATUS nt_status;
1184
1185         nt_status = auth_check_password_recv(subreq, mem_ctx,
1186                                              &user_info_dc,
1187                                              r->out.authoritative);
1188         TALLOC_FREE(subreq);
1189         if (!NT_STATUS_IS_OK(nt_status)) {
1190                 r->out.result = nt_status;
1191                 dcesrv_netr_LogonSamLogon_base_reply(state);
1192                 return;
1193         }
1194
1195         switch (r->in.validation_level) {
1196         case 2:
1197                 nt_status = auth_convert_user_info_dc_saminfo2(mem_ctx,
1198                                                                user_info_dc,
1199                                                                &sam2);
1200                 if (!NT_STATUS_IS_OK(nt_status)) {
1201                         r->out.result = nt_status;
1202                         dcesrv_netr_LogonSamLogon_base_reply(state);
1203                         return;
1204                 }
1205
1206                 r->out.validation->sam2 = sam2;
1207                 break;
1208
1209         case 3:
1210                 nt_status = auth_convert_user_info_dc_saminfo3(mem_ctx,
1211                                                                user_info_dc,
1212                                                                &sam3);
1213                 if (!NT_STATUS_IS_OK(nt_status)) {
1214                         r->out.result = nt_status;
1215                         dcesrv_netr_LogonSamLogon_base_reply(state);
1216                         return;
1217                 }
1218
1219                 r->out.validation->sam3 = sam3;
1220                 break;
1221
1222         case 6:
1223                 nt_status = auth_convert_user_info_dc_saminfo6(mem_ctx,
1224                                                                user_info_dc,
1225                                                                &sam6);
1226                 if (!NT_STATUS_IS_OK(nt_status)) {
1227                         r->out.result = nt_status;
1228                         dcesrv_netr_LogonSamLogon_base_reply(state);
1229                         return;
1230                 }
1231
1232                 r->out.validation->sam6 = sam6;
1233                 break;
1234
1235         default:
1236                 if (!NT_STATUS_IS_OK(nt_status)) {
1237                         r->out.result = NT_STATUS_INVALID_INFO_CLASS;
1238                         dcesrv_netr_LogonSamLogon_base_reply(state);
1239                         return;
1240                 }
1241         }
1242
1243         /* TODO: Describe and deal with these flags */
1244         *r->out.flags = 0;
1245
1246         r->out.result = NT_STATUS_OK;
1247
1248         dcesrv_netr_LogonSamLogon_base_reply(state);
1249 }
1250
1251 static void dcesrv_netr_LogonSamLogon_base_krb5_done(struct tevent_req *subreq)
1252 {
1253         struct dcesrv_netr_LogonSamLogon_base_state *state =
1254                 tevent_req_callback_data(subreq,
1255                 struct dcesrv_netr_LogonSamLogon_base_state);
1256         TALLOC_CTX *mem_ctx = state->mem_ctx;
1257         struct netr_LogonSamLogonEx *r = &state->r;
1258         struct netr_GenericInfo2 *generic = NULL;
1259         NTSTATUS status;
1260
1261         status = dcerpc_kdc_check_generic_kerberos_r_recv(subreq, mem_ctx);
1262         TALLOC_FREE(subreq);
1263         if (!NT_STATUS_IS_OK(status)) {
1264                 r->out.result = status;
1265                 dcesrv_netr_LogonSamLogon_base_reply(state);
1266                 return;
1267         }
1268
1269         generic = r->out.validation->generic;
1270         generic->length = state->kr.out.generic_reply.length;
1271         generic->data = state->kr.out.generic_reply.data;
1272
1273         /* TODO: Describe and deal with these flags */
1274         *r->out.flags = 0;
1275
1276         r->out.result = NT_STATUS_OK;
1277
1278         dcesrv_netr_LogonSamLogon_base_reply(state);
1279 }
1280
1281 static void dcesrv_netr_LogonSamLogon_base_reply(
1282         struct dcesrv_netr_LogonSamLogon_base_state *state)
1283 {
1284         struct netr_LogonSamLogonEx *r = &state->r;
1285         NTSTATUS status;
1286
1287         if (NT_STATUS_IS_OK(r->out.result)) {
1288                 netlogon_creds_encrypt_samlogon_validation(state->creds,
1289                                                            r->in.validation_level,
1290                                                            r->out.validation);
1291         }
1292
1293         if (state->_r.lslex != NULL) {
1294                 struct netr_LogonSamLogonEx *_r = state->_r.lslex;
1295                 _r->out.result = r->out.result;
1296         } else if (state->_r.lslwf != NULL) {
1297                 struct netr_LogonSamLogonWithFlags *_r = state->_r.lslwf;
1298                 _r->out.result = r->out.result;
1299         } else if (state->_r.lsl != NULL) {
1300                 struct netr_LogonSamLogon *_r = state->_r.lsl;
1301                 _r->out.result = r->out.result;
1302         }
1303
1304         status = dcesrv_reply(state->dce_call);
1305         if (!NT_STATUS_IS_OK(status)) {
1306                 DBG_ERR("dcesrv_reply() failed - %s\n",
1307                         nt_errstr(status));
1308         }
1309 }
1310
1311 static NTSTATUS dcesrv_netr_LogonSamLogonEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1312                                      struct netr_LogonSamLogonEx *r)
1313 {
1314         struct dcesrv_netr_LogonSamLogon_base_state *state;
1315         NTSTATUS nt_status;
1316
1317         *r->out.authoritative = 1;
1318
1319         state = talloc_zero(mem_ctx, struct dcesrv_netr_LogonSamLogon_base_state);
1320         if (state == NULL) {
1321                 return NT_STATUS_NO_MEMORY;
1322         }
1323
1324         state->dce_call = dce_call;
1325         state->mem_ctx = mem_ctx;
1326
1327         state->r.in.server_name      = r->in.server_name;
1328         state->r.in.computer_name    = r->in.computer_name;
1329         state->r.in.logon_level      = r->in.logon_level;
1330         state->r.in.logon            = r->in.logon;
1331         state->r.in.validation_level = r->in.validation_level;
1332         state->r.in.flags            = r->in.flags;
1333         state->r.out.validation      = r->out.validation;
1334         state->r.out.authoritative   = r->out.authoritative;
1335         state->r.out.flags           = r->out.flags;
1336
1337         state->_r.lslex = r;
1338
1339         nt_status = dcesrv_netr_LogonSamLogon_check(dce_call, &state->r);
1340         if (!NT_STATUS_IS_OK(nt_status)) {
1341                 return nt_status;
1342         }
1343
1344         nt_status = schannel_get_creds_state(mem_ctx,
1345                                              dce_call->conn->dce_ctx->lp_ctx,
1346                                              r->in.computer_name, &state->creds);
1347         if (!NT_STATUS_IS_OK(nt_status)) {
1348                 return nt_status;
1349         }
1350
1351         if (dce_call->conn->auth_state.auth_type != DCERPC_AUTH_TYPE_SCHANNEL) {
1352                 return NT_STATUS_ACCESS_DENIED;
1353         }
1354
1355         nt_status = dcesrv_netr_LogonSamLogon_base_call(state);
1356
1357         if (dce_call->state_flags & DCESRV_CALL_STATE_FLAG_ASYNC) {
1358                 return nt_status;
1359         }
1360
1361         return nt_status;
1362 }
1363
1364 /*
1365   netr_LogonSamLogonWithFlags
1366
1367 */
1368 static NTSTATUS dcesrv_netr_LogonSamLogonWithFlags(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1369                                             struct netr_LogonSamLogonWithFlags *r)
1370 {
1371         struct dcesrv_netr_LogonSamLogon_base_state *state;
1372         NTSTATUS nt_status;
1373
1374         *r->out.authoritative = 1;
1375
1376         state = talloc_zero(mem_ctx, struct dcesrv_netr_LogonSamLogon_base_state);
1377         if (state == NULL) {
1378                 return NT_STATUS_NO_MEMORY;
1379         }
1380
1381         state->dce_call = dce_call;
1382         state->mem_ctx = mem_ctx;
1383
1384         state->r.in.server_name      = r->in.server_name;
1385         state->r.in.computer_name    = r->in.computer_name;
1386         state->r.in.logon_level      = r->in.logon_level;
1387         state->r.in.logon            = r->in.logon;
1388         state->r.in.validation_level = r->in.validation_level;
1389         state->r.in.flags            = r->in.flags;
1390         state->r.out.validation      = r->out.validation;
1391         state->r.out.authoritative   = r->out.authoritative;
1392         state->r.out.flags           = r->out.flags;
1393
1394         state->_r.lslwf = r;
1395
1396         nt_status = dcesrv_netr_LogonSamLogon_check(dce_call, &state->r);
1397         if (!NT_STATUS_IS_OK(nt_status)) {
1398                 return nt_status;
1399         }
1400
1401         r->out.return_authenticator = talloc_zero(mem_ctx,
1402                                                   struct netr_Authenticator);
1403         if (r->out.return_authenticator == NULL) {
1404                 return NT_STATUS_NO_MEMORY;
1405         }
1406
1407         nt_status = dcesrv_netr_creds_server_step_check(dce_call,
1408                                                         mem_ctx,
1409                                                         r->in.computer_name,
1410                                                         r->in.credential,
1411                                                         r->out.return_authenticator,
1412                                                         &state->creds);
1413         if (!NT_STATUS_IS_OK(nt_status)) {
1414                 return nt_status;
1415         }
1416
1417         nt_status = dcesrv_netr_LogonSamLogon_base_call(state);
1418
1419         if (dce_call->state_flags & DCESRV_CALL_STATE_FLAG_ASYNC) {
1420                 return nt_status;
1421         }
1422
1423         return nt_status;
1424 }
1425
1426 /*
1427   netr_LogonSamLogon
1428 */
1429 static NTSTATUS dcesrv_netr_LogonSamLogon(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1430                                    struct netr_LogonSamLogon *r)
1431 {
1432         struct dcesrv_netr_LogonSamLogon_base_state *state;
1433         NTSTATUS nt_status;
1434
1435         *r->out.authoritative = 1;
1436
1437         state = talloc_zero(mem_ctx, struct dcesrv_netr_LogonSamLogon_base_state);
1438         if (state == NULL) {
1439                 return NT_STATUS_NO_MEMORY;
1440         }
1441
1442         state->dce_call = dce_call;
1443         state->mem_ctx = mem_ctx;
1444
1445         state->r.in.server_name      = r->in.server_name;
1446         state->r.in.computer_name    = r->in.computer_name;
1447         state->r.in.logon_level      = r->in.logon_level;
1448         state->r.in.logon            = r->in.logon;
1449         state->r.in.validation_level = r->in.validation_level;
1450         state->r.in.flags            = &state->_ignored_flags;
1451         state->r.out.validation      = r->out.validation;
1452         state->r.out.authoritative   = r->out.authoritative;
1453         state->r.out.flags           = &state->_ignored_flags;
1454
1455         state->_r.lsl = r;
1456
1457         nt_status = dcesrv_netr_LogonSamLogon_check(dce_call, &state->r);
1458         if (!NT_STATUS_IS_OK(nt_status)) {
1459                 return nt_status;
1460         }
1461
1462         r->out.return_authenticator = talloc_zero(mem_ctx,
1463                                                   struct netr_Authenticator);
1464         if (r->out.return_authenticator == NULL) {
1465                 return NT_STATUS_NO_MEMORY;
1466         }
1467
1468         nt_status = dcesrv_netr_creds_server_step_check(dce_call,
1469                                                         mem_ctx,
1470                                                         r->in.computer_name,
1471                                                         r->in.credential,
1472                                                         r->out.return_authenticator,
1473                                                         &state->creds);
1474         if (!NT_STATUS_IS_OK(nt_status)) {
1475                 return nt_status;
1476         }
1477
1478         nt_status = dcesrv_netr_LogonSamLogon_base_call(state);
1479
1480         if (dce_call->state_flags & DCESRV_CALL_STATE_FLAG_ASYNC) {
1481                 return nt_status;
1482         }
1483
1484         return nt_status;
1485 }
1486
1487
1488 /*
1489   netr_LogonSamLogoff
1490 */
1491 static NTSTATUS dcesrv_netr_LogonSamLogoff(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1492                        struct netr_LogonSamLogoff *r)
1493 {
1494         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1495 }
1496
1497
1498
1499 /*
1500   netr_DatabaseDeltas
1501 */
1502 static NTSTATUS dcesrv_netr_DatabaseDeltas(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1503                        struct netr_DatabaseDeltas *r)
1504 {
1505         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1506 }
1507
1508
1509 /*
1510   netr_DatabaseSync2
1511 */
1512 static NTSTATUS dcesrv_netr_DatabaseSync2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1513                        struct netr_DatabaseSync2 *r)
1514 {
1515         /* win2k3 native mode returns  "NOT IMPLEMENTED" for this call */
1516         return NT_STATUS_NOT_IMPLEMENTED;
1517 }
1518
1519
1520 /*
1521   netr_DatabaseSync
1522 */
1523 static NTSTATUS dcesrv_netr_DatabaseSync(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1524                        struct netr_DatabaseSync *r)
1525 {
1526         struct netr_DatabaseSync2 r2;
1527         NTSTATUS status;
1528
1529         ZERO_STRUCT(r2);
1530
1531         r2.in.logon_server = r->in.logon_server;
1532         r2.in.computername = r->in.computername;
1533         r2.in.credential = r->in.credential;
1534         r2.in.database_id = r->in.database_id;
1535         r2.in.restart_state = SYNCSTATE_NORMAL_STATE;
1536         r2.in.sync_context = r->in.sync_context;
1537         r2.out.sync_context = r->out.sync_context;
1538         r2.out.delta_enum_array = r->out.delta_enum_array;
1539         r2.in.preferredmaximumlength = r->in.preferredmaximumlength;
1540
1541         status = dcesrv_netr_DatabaseSync2(dce_call, mem_ctx, &r2);
1542
1543         return status;
1544 }
1545
1546
1547 /*
1548   netr_AccountDeltas
1549 */
1550 static NTSTATUS dcesrv_netr_AccountDeltas(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1551                        struct netr_AccountDeltas *r)
1552 {
1553         /* w2k3 returns "NOT IMPLEMENTED" for this call */
1554         return NT_STATUS_NOT_IMPLEMENTED;
1555 }
1556
1557
1558 /*
1559   netr_AccountSync
1560 */
1561 static NTSTATUS dcesrv_netr_AccountSync(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1562                        struct netr_AccountSync *r)
1563 {
1564         /* w2k3 returns "NOT IMPLEMENTED" for this call */
1565         return NT_STATUS_NOT_IMPLEMENTED;
1566 }
1567
1568
1569 /*
1570   netr_GetDcName
1571 */
1572 static WERROR dcesrv_netr_GetDcName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1573                        struct netr_GetDcName *r)
1574 {
1575         const char * const attrs[] = { NULL };
1576         struct ldb_context *sam_ctx;
1577         struct ldb_message **res;
1578         struct ldb_dn *domain_dn;
1579         int ret;
1580         const char *dcname;
1581
1582         /*
1583          * [MS-NRPC] 3.5.5.3.4 NetrGetDCName says
1584          * that the domainname needs to be a valid netbios domain
1585          * name, if it is not NULL.
1586          */
1587         if (r->in.domainname) {
1588                 const char *dot = strchr(r->in.domainname, '.');
1589                 size_t len = strlen(r->in.domainname);
1590
1591                 if (dot || len > 15) {
1592                         return WERR_NERR_DCNOTFOUND;
1593                 }
1594
1595                 /*
1596                  * TODO: Should we also varify that only valid
1597                  *       netbios name characters are used?
1598                  */
1599         }
1600
1601         sam_ctx = samdb_connect(mem_ctx,
1602                                 dce_call->event_ctx,
1603                                 dce_call->conn->dce_ctx->lp_ctx,
1604                                 dce_call->conn->auth_state.session_info,
1605                                 dce_call->conn->remote_address,
1606                                 0);
1607         if (sam_ctx == NULL) {
1608                 return WERR_DS_UNAVAILABLE;
1609         }
1610
1611         domain_dn = samdb_domain_to_dn(sam_ctx, mem_ctx,
1612                                        r->in.domainname);
1613         if (domain_dn == NULL) {
1614                 return WERR_NO_SUCH_DOMAIN;
1615         }
1616
1617         ret = gendb_search_dn(sam_ctx, mem_ctx,
1618                               domain_dn, &res, attrs);
1619         if (ret != 1) {
1620                 return WERR_NO_SUCH_DOMAIN;
1621         }
1622
1623         /* TODO: - return real IP address
1624          *       - check all r->in.* parameters (server_unc is ignored by w2k3!)
1625          */
1626         dcname = talloc_asprintf(mem_ctx, "\\\\%s",
1627                                  lpcfg_netbios_name(dce_call->conn->dce_ctx->lp_ctx));
1628         W_ERROR_HAVE_NO_MEMORY(dcname);
1629
1630         *r->out.dcname = dcname;
1631         return WERR_OK;
1632 }
1633
1634 struct dcesrv_netr_LogonControl_base_state {
1635         struct dcesrv_call_state *dce_call;
1636
1637         TALLOC_CTX *mem_ctx;
1638
1639         struct netr_LogonControl2Ex r;
1640
1641         struct {
1642                 struct netr_LogonControl *l;
1643                 struct netr_LogonControl2 *l2;
1644                 struct netr_LogonControl2Ex *l2ex;
1645         } _r;
1646 };
1647
1648 static void dcesrv_netr_LogonControl_base_done(struct tevent_req *subreq);
1649
1650 static WERROR dcesrv_netr_LogonControl_base_call(struct dcesrv_netr_LogonControl_base_state *state)
1651 {
1652         struct dcesrv_connection *conn = state->dce_call->conn;
1653         struct loadparm_context *lp_ctx = state->dce_call->conn->dce_ctx->lp_ctx;
1654         struct auth_session_info *session_info = conn->auth_state.session_info;
1655         enum security_user_level security_level;
1656         struct dcerpc_binding_handle *irpc_handle;
1657         struct tevent_req *subreq;
1658         bool ok;
1659
1660         /* TODO: check for WERR_INVALID_COMPUTERNAME ? */
1661
1662         if (state->_r.l != NULL) {
1663                 /*
1664                  * netr_LogonControl
1665                  */
1666                 if (state->r.in.level == 0x00000002) {
1667                         return WERR_NOT_SUPPORTED;
1668                 } else if (state->r.in.level != 0x00000001) {
1669                         return WERR_INVALID_LEVEL;
1670                 }
1671
1672                 switch (state->r.in.function_code) {
1673                 case NETLOGON_CONTROL_QUERY:
1674                 case NETLOGON_CONTROL_REPLICATE:
1675                 case NETLOGON_CONTROL_SYNCHRONIZE:
1676                 case NETLOGON_CONTROL_PDC_REPLICATE:
1677                 case NETLOGON_CONTROL_BREAKPOINT:
1678                 case NETLOGON_CONTROL_BACKUP_CHANGE_LOG:
1679                 case NETLOGON_CONTROL_TRUNCATE_LOG:
1680                         break;
1681                 default:
1682                         return WERR_NOT_SUPPORTED;
1683                 }
1684         }
1685
1686         if (state->r.in.level < 0x00000001) {
1687                 return WERR_INVALID_LEVEL;
1688         }
1689
1690         if (state->r.in.level > 0x00000004) {
1691                 return WERR_INVALID_LEVEL;
1692         }
1693
1694         if (state->r.in.function_code == NETLOGON_CONTROL_QUERY) {
1695                 struct netr_NETLOGON_INFO_1 *info1 = NULL;
1696                 struct netr_NETLOGON_INFO_3 *info3 = NULL;
1697
1698                 switch (state->r.in.level) {
1699                 case 0x00000001:
1700                         info1 = talloc_zero(state->mem_ctx,
1701                                             struct netr_NETLOGON_INFO_1);
1702                         if (info1 == NULL) {
1703                                 return WERR_NOT_ENOUGH_MEMORY;
1704                         }
1705                         state->r.out.query->info1 = info1;
1706                         return WERR_OK;
1707
1708                 case 0x00000003:
1709                         info3 = talloc_zero(state->mem_ctx,
1710                                             struct netr_NETLOGON_INFO_3);
1711                         if (info3 == NULL) {
1712                                 return WERR_NOT_ENOUGH_MEMORY;
1713                         }
1714                         state->r.out.query->info3 = info3;
1715                         return WERR_OK;
1716
1717                 default:
1718                         return WERR_INVALID_PARAMETER;
1719                 }
1720         }
1721
1722         /*
1723          * Some validations are done before the access check
1724          * and some after the access check
1725          */
1726         security_level = security_session_user_level(session_info, NULL);
1727         if (security_level < SECURITY_ADMINISTRATOR) {
1728                 return WERR_ACCESS_DENIED;
1729         }
1730
1731         if (state->_r.l2 != NULL) {
1732                 /*
1733                  * netr_LogonControl2
1734                  */
1735                 if (state->r.in.level == 0x00000004) {
1736                         return WERR_INVALID_LEVEL;
1737                 }
1738         }
1739
1740         switch (state->r.in.level) {
1741         case 0x00000001:
1742                 break;
1743
1744         case 0x00000002:
1745                 switch (state->r.in.function_code) {
1746                 case NETLOGON_CONTROL_REDISCOVER:
1747                 case NETLOGON_CONTROL_TC_QUERY:
1748                 case NETLOGON_CONTROL_TC_VERIFY:
1749                         break;
1750                 default:
1751                         return WERR_INVALID_PARAMETER;
1752                 }
1753
1754                 break;
1755
1756         case 0x00000003:
1757                 break;
1758
1759         case 0x00000004:
1760                 if (state->r.in.function_code != NETLOGON_CONTROL_FIND_USER) {
1761                         return WERR_INVALID_PARAMETER;
1762                 }
1763
1764                 break;
1765
1766         default:
1767                 return WERR_INVALID_LEVEL;
1768         }
1769
1770         switch (state->r.in.function_code) {
1771         case NETLOGON_CONTROL_REDISCOVER:
1772         case NETLOGON_CONTROL_TC_QUERY:
1773         case NETLOGON_CONTROL_TC_VERIFY:
1774                 if (state->r.in.level != 2) {
1775                         return WERR_INVALID_PARAMETER;
1776                 }
1777
1778                 if (state->r.in.data == NULL) {
1779                         return WERR_INVALID_PARAMETER;
1780                 }
1781
1782                 if (state->r.in.data->domain == NULL) {
1783                         return WERR_INVALID_PARAMETER;
1784                 }
1785
1786                 break;
1787
1788         case NETLOGON_CONTROL_CHANGE_PASSWORD:
1789                 if (state->r.in.level != 1) {
1790                         return WERR_INVALID_PARAMETER;
1791                 }
1792
1793                 if (state->r.in.data == NULL) {
1794                         return WERR_INVALID_PARAMETER;
1795                 }
1796
1797                 if (state->r.in.data->domain == NULL) {
1798                         return WERR_INVALID_PARAMETER;
1799                 }
1800
1801                 ok = lpcfg_is_my_domain_or_realm(lp_ctx,
1802                                                  state->r.in.data->domain);
1803                 if (!ok) {
1804                         struct ldb_context *sam_ctx;
1805
1806                         sam_ctx = samdb_connect(
1807                                 state,
1808                                 state->dce_call->event_ctx,
1809                                 lp_ctx,
1810                                 system_session(lp_ctx),
1811                                 state->dce_call->conn->remote_address,
1812                                 0);
1813                         if (sam_ctx == NULL) {
1814                                 return WERR_DS_UNAVAILABLE;
1815                         }
1816
1817                         /*
1818                          * Secrets for trusted domains can only be triggered on
1819                          * the PDC.
1820                          */
1821                         ok = samdb_is_pdc(sam_ctx);
1822                         TALLOC_FREE(sam_ctx);
1823                         if (!ok) {
1824                                 return WERR_INVALID_DOMAIN_ROLE;
1825                         }
1826                 }
1827
1828                 break;
1829         default:
1830                 return WERR_NOT_SUPPORTED;
1831         }
1832
1833         irpc_handle = irpc_binding_handle_by_name(state,
1834                                                   state->dce_call->msg_ctx,
1835                                                   "winbind_server",
1836                                                   &ndr_table_winbind);
1837         if (irpc_handle == NULL) {
1838                 DEBUG(0,("Failed to get binding_handle for winbind_server task\n"));
1839                 state->dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
1840                 return WERR_SERVICE_NOT_FOUND;
1841         }
1842
1843         /*
1844          * 60 seconds timeout should be enough
1845          */
1846         dcerpc_binding_handle_set_timeout(irpc_handle, 60);
1847
1848         subreq = dcerpc_winbind_LogonControl_send(state,
1849                                                   state->dce_call->event_ctx,
1850                                                   irpc_handle,
1851                                                   state->r.in.function_code,
1852                                                   state->r.in.level,
1853                                                   state->r.in.data,
1854                                                   state->r.out.query);
1855         if (subreq == NULL) {
1856                 return WERR_NOT_ENOUGH_MEMORY;
1857         }
1858         state->dce_call->state_flags |= DCESRV_CALL_STATE_FLAG_ASYNC;
1859         tevent_req_set_callback(subreq,
1860                                 dcesrv_netr_LogonControl_base_done,
1861                                 state);
1862
1863         return WERR_OK;
1864 }
1865
1866 static void dcesrv_netr_LogonControl_base_done(struct tevent_req *subreq)
1867 {
1868         struct dcesrv_netr_LogonControl_base_state *state =
1869                 tevent_req_callback_data(subreq,
1870                 struct dcesrv_netr_LogonControl_base_state);
1871         NTSTATUS status;
1872
1873         status = dcerpc_winbind_LogonControl_recv(subreq, state->mem_ctx,
1874                                                   &state->r.out.result);
1875         TALLOC_FREE(subreq);
1876         if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) {
1877                 state->r.out.result = WERR_TIMEOUT;
1878         } else if (!NT_STATUS_IS_OK(status)) {
1879                 state->dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
1880                 DEBUG(0,(__location__ ": IRPC callback failed %s\n",
1881                          nt_errstr(status)));
1882         }
1883
1884         if (state->_r.l2ex != NULL) {
1885                 struct netr_LogonControl2Ex *r = state->_r.l2ex;
1886                 r->out.result = state->r.out.result;
1887         } else if (state->_r.l2 != NULL) {
1888                 struct netr_LogonControl2 *r = state->_r.l2;
1889                 r->out.result = state->r.out.result;
1890         } else if (state->_r.l != NULL) {
1891                 struct netr_LogonControl *r = state->_r.l;
1892                 r->out.result = state->r.out.result;
1893         }
1894
1895         status = dcesrv_reply(state->dce_call);
1896         if (!NT_STATUS_IS_OK(status)) {
1897                 DEBUG(0,(__location__ ": dcesrv_reply() failed - %s\n", nt_errstr(status)));
1898         }
1899 }
1900
1901 /*
1902   netr_LogonControl
1903 */
1904 static WERROR dcesrv_netr_LogonControl(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1905                        struct netr_LogonControl *r)
1906 {
1907         struct dcesrv_netr_LogonControl_base_state *state;
1908         WERROR werr;
1909
1910         state = talloc_zero(mem_ctx, struct dcesrv_netr_LogonControl_base_state);
1911         if (state == NULL) {
1912                 return WERR_NOT_ENOUGH_MEMORY;
1913         }
1914
1915         state->dce_call = dce_call;
1916         state->mem_ctx = mem_ctx;
1917
1918         state->r.in.logon_server = r->in.logon_server;
1919         state->r.in.function_code = r->in.function_code;
1920         state->r.in.level = r->in.level;
1921         state->r.in.data = NULL;
1922         state->r.out.query = r->out.query;
1923
1924         state->_r.l = r;
1925
1926         werr = dcesrv_netr_LogonControl_base_call(state);
1927
1928         if (dce_call->state_flags & DCESRV_CALL_STATE_FLAG_ASYNC) {
1929                 return werr;
1930         }
1931
1932         return werr;
1933 }
1934
1935 /*
1936   netr_LogonControl2
1937 */
1938 static WERROR dcesrv_netr_LogonControl2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1939                        struct netr_LogonControl2 *r)
1940 {
1941         struct dcesrv_netr_LogonControl_base_state *state;
1942         WERROR werr;
1943
1944         state = talloc_zero(mem_ctx, struct dcesrv_netr_LogonControl_base_state);
1945         if (state == NULL) {
1946                 return WERR_NOT_ENOUGH_MEMORY;
1947         }
1948
1949         state->dce_call = dce_call;
1950         state->mem_ctx = mem_ctx;
1951
1952         state->r.in.logon_server = r->in.logon_server;
1953         state->r.in.function_code = r->in.function_code;
1954         state->r.in.level = r->in.level;
1955         state->r.in.data = r->in.data;
1956         state->r.out.query = r->out.query;
1957
1958         state->_r.l2 = r;
1959
1960         werr = dcesrv_netr_LogonControl_base_call(state);
1961
1962         if (dce_call->state_flags & DCESRV_CALL_STATE_FLAG_ASYNC) {
1963                 return werr;
1964         }
1965
1966         return werr;
1967 }
1968
1969 /*
1970   netr_LogonControl2Ex
1971 */
1972 static WERROR dcesrv_netr_LogonControl2Ex(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1973                        struct netr_LogonControl2Ex *r)
1974 {
1975         struct dcesrv_netr_LogonControl_base_state *state;
1976         WERROR werr;
1977
1978         state = talloc_zero(mem_ctx, struct dcesrv_netr_LogonControl_base_state);
1979         if (state == NULL) {
1980                 return WERR_NOT_ENOUGH_MEMORY;
1981         }
1982
1983         state->dce_call = dce_call;
1984         state->mem_ctx = mem_ctx;
1985
1986         state->r = *r;
1987         state->_r.l2ex = r;
1988
1989         werr = dcesrv_netr_LogonControl_base_call(state);
1990
1991         if (dce_call->state_flags & DCESRV_CALL_STATE_FLAG_ASYNC) {
1992                 return werr;
1993         }
1994
1995         return werr;
1996 }
1997
1998 static WERROR fill_trusted_domains_array(TALLOC_CTX *mem_ctx,
1999                                          struct ldb_context *sam_ctx,
2000                                          struct netr_DomainTrustList *trusts,
2001                                          uint32_t trust_flags);
2002
2003 /*
2004   netr_GetAnyDCName
2005 */
2006 static WERROR dcesrv_netr_GetAnyDCName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2007                        struct netr_GetAnyDCName *r)
2008 {
2009         struct netr_DomainTrustList *trusts;
2010         struct ldb_context *sam_ctx;
2011         struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2012         uint32_t i;
2013         WERROR werr;
2014
2015         *r->out.dcname = NULL;
2016
2017         if ((r->in.domainname == NULL) || (r->in.domainname[0] == '\0')) {
2018                 /* if the domainname parameter wasn't set assume our domain */
2019                 r->in.domainname = lpcfg_workgroup(lp_ctx);
2020         }
2021
2022         sam_ctx = samdb_connect(mem_ctx,
2023                                 dce_call->event_ctx,
2024                                 lp_ctx,
2025                                 dce_call->conn->auth_state.session_info,
2026                                 dce_call->conn->remote_address,
2027                                 0);
2028         if (sam_ctx == NULL) {
2029                 return WERR_DS_UNAVAILABLE;
2030         }
2031
2032         if (strcasecmp(r->in.domainname, lpcfg_workgroup(lp_ctx)) == 0) {
2033                 /* well we asked for a DC of our own domain */
2034                 if (samdb_is_pdc(sam_ctx)) {
2035                         /* we are the PDC of the specified domain */
2036                         return WERR_NO_SUCH_DOMAIN;
2037                 }
2038
2039                 *r->out.dcname = talloc_asprintf(mem_ctx, "\\%s",
2040                                                 lpcfg_netbios_name(lp_ctx));
2041                 W_ERROR_HAVE_NO_MEMORY(*r->out.dcname);
2042
2043                 return WERR_OK;
2044         }
2045
2046         /* Okay, now we have to consider the trusted domains */
2047
2048         trusts = talloc_zero(mem_ctx, struct netr_DomainTrustList);
2049         W_ERROR_HAVE_NO_MEMORY(trusts);
2050
2051         trusts->count = 0;
2052
2053         werr = fill_trusted_domains_array(mem_ctx, sam_ctx, trusts,
2054                                           NETR_TRUST_FLAG_INBOUND
2055                                           | NETR_TRUST_FLAG_OUTBOUND);
2056         W_ERROR_NOT_OK_RETURN(werr);
2057
2058         for (i = 0; i < trusts->count; i++) {
2059                 if (strcasecmp(r->in.domainname, trusts->array[i].netbios_name) == 0) {
2060                         /* FIXME: Here we need to find a DC for the specified
2061                          * trusted domain. */
2062
2063                         /* return WERR_OK; */
2064                         return WERR_NO_SUCH_DOMAIN;
2065                 }
2066         }
2067
2068         return WERR_NO_SUCH_DOMAIN;
2069 }
2070
2071
2072 /*
2073   netr_DatabaseRedo
2074 */
2075 static NTSTATUS dcesrv_netr_DatabaseRedo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2076                        struct netr_DatabaseRedo *r)
2077 {
2078         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2079 }
2080
2081
2082 /*
2083   netr_NetrEnumerateTrustedDomains
2084 */
2085 static NTSTATUS dcesrv_netr_NetrEnumerateTrustedDomains(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2086                        struct netr_NetrEnumerateTrustedDomains *r)
2087 {
2088         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2089 }
2090
2091
2092 /*
2093   netr_LogonGetCapabilities
2094 */
2095 static NTSTATUS dcesrv_netr_LogonGetCapabilities(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2096                        struct netr_LogonGetCapabilities *r)
2097 {
2098         struct netlogon_creds_CredentialState *creds;
2099         NTSTATUS status;
2100
2101         status = dcesrv_netr_creds_server_step_check(dce_call,
2102                                                      mem_ctx,
2103                                                      r->in.computer_name,
2104                                                      r->in.credential,
2105                                                      r->out.return_authenticator,
2106                                                      &creds);
2107         if (!NT_STATUS_IS_OK(status)) {
2108                 DEBUG(0,(__location__ " Bad credentials - error\n"));
2109         }
2110         NT_STATUS_NOT_OK_RETURN(status);
2111
2112         if (r->in.query_level != 1) {
2113                 return NT_STATUS_NOT_SUPPORTED;
2114         }
2115
2116         r->out.capabilities->server_capabilities = creds->negotiate_flags;
2117
2118         return NT_STATUS_OK;
2119 }
2120
2121
2122 /*
2123   netr_NETRLOGONSETSERVICEBITS
2124 */
2125 static WERROR dcesrv_netr_NETRLOGONSETSERVICEBITS(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2126                        struct netr_NETRLOGONSETSERVICEBITS *r)
2127 {
2128         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2129 }
2130
2131
2132 /*
2133   netr_LogonGetTrustRid
2134 */
2135 static WERROR dcesrv_netr_LogonGetTrustRid(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2136                        struct netr_LogonGetTrustRid *r)
2137 {
2138         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2139 }
2140
2141
2142 /*
2143   netr_NETRLOGONCOMPUTESERVERDIGEST
2144 */
2145 static WERROR dcesrv_netr_NETRLOGONCOMPUTESERVERDIGEST(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2146                        struct netr_NETRLOGONCOMPUTESERVERDIGEST *r)
2147 {
2148         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2149 }
2150
2151
2152 /*
2153   netr_NETRLOGONCOMPUTECLIENTDIGEST
2154 */
2155 static WERROR dcesrv_netr_NETRLOGONCOMPUTECLIENTDIGEST(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2156                        struct netr_NETRLOGONCOMPUTECLIENTDIGEST *r)
2157 {
2158         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2159 }
2160
2161
2162
2163 /*
2164   netr_DsRGetSiteName
2165 */
2166 static WERROR dcesrv_netr_DsRGetSiteName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2167                                   struct netr_DsRGetSiteName *r)
2168 {
2169         struct ldb_context *sam_ctx;
2170         struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2171
2172         sam_ctx = samdb_connect(mem_ctx,
2173                                 dce_call->event_ctx,
2174                                 lp_ctx,
2175                                 dce_call->conn->auth_state.session_info,
2176                                 dce_call->conn->remote_address,
2177                                 0);
2178         if (sam_ctx == NULL) {
2179                 return WERR_DS_UNAVAILABLE;
2180         }
2181
2182         /*
2183          * We assume to be a DC when we get called over NETLOGON. Hence we
2184          * get our site name always by using "samdb_server_site_name()"
2185          * and not "samdb_client_site_name()".
2186          */
2187         *r->out.site = samdb_server_site_name(sam_ctx, mem_ctx);
2188         W_ERROR_HAVE_NO_MEMORY(*r->out.site);
2189
2190         return WERR_OK;
2191 }
2192
2193
2194 /*
2195   fill in a netr_OneDomainInfo from our own domain/forest
2196 */
2197 static NTSTATUS fill_our_one_domain_info(TALLOC_CTX *mem_ctx,
2198                                 const struct lsa_TrustDomainInfoInfoEx *our_tdo,
2199                                 struct GUID domain_guid,
2200                                 struct netr_OneDomainInfo *info,
2201                                 bool is_trust_list)
2202 {
2203         ZERO_STRUCTP(info);
2204
2205         if (is_trust_list) {
2206                 struct netr_trust_extension *tei = NULL;
2207
2208                 /* w2k8 only fills this on trusted domains */
2209                 tei = talloc_zero(mem_ctx, struct netr_trust_extension);
2210                 if (tei == NULL) {
2211                         return NT_STATUS_NO_MEMORY;
2212                 }
2213                 tei->flags |= NETR_TRUST_FLAG_PRIMARY;
2214
2215                 /*
2216                  * We're always within a native forest
2217                  */
2218                 tei->flags |= NETR_TRUST_FLAG_IN_FOREST;
2219                 tei->flags |= NETR_TRUST_FLAG_NATIVE;
2220
2221                 /* For now we assume we're always the tree root */
2222                 tei->flags |= NETR_TRUST_FLAG_TREEROOT;
2223                 tei->parent_index = 0;
2224
2225                 tei->trust_type = our_tdo->trust_type;
2226                 /*
2227                  * This needs to be 0 instead of our_tdo->trust_attributes
2228                  * It means LSA_TRUST_ATTRIBUTE_WITHIN_FOREST won't
2229                  * be set, while NETR_TRUST_FLAG_IN_FOREST is set above.
2230                  */
2231                 tei->trust_attributes = 0;
2232
2233                 info->trust_extension.info = tei;
2234                 info->trust_extension.length = 16;
2235         }
2236
2237         if (is_trust_list) {
2238                 info->dns_domainname.string = our_tdo->domain_name.string;
2239
2240                 /* MS-NRPC 3.5.4.3.9 - must be set to NULL for trust list */
2241                 info->dns_forestname.string = NULL;
2242         } else {
2243                 info->dns_domainname.string = talloc_asprintf(mem_ctx, "%s.",
2244                                                 our_tdo->domain_name.string);
2245                 if (info->dns_domainname.string == NULL) {
2246                         return NT_STATUS_NO_MEMORY;
2247                 }
2248
2249                 info->dns_forestname.string = info->dns_domainname.string;
2250         }
2251
2252         info->domainname.string = our_tdo->netbios_name.string;
2253         info->domain_sid = our_tdo->sid;
2254         info->domain_guid = domain_guid;
2255
2256         return NT_STATUS_OK;
2257 }
2258
2259 /*
2260   fill in a netr_OneDomainInfo from a trust tdo
2261 */
2262 static NTSTATUS fill_trust_one_domain_info(TALLOC_CTX *mem_ctx,
2263                                 struct GUID domain_guid,
2264                                 const struct lsa_TrustDomainInfoInfoEx *tdo,
2265                                 struct netr_OneDomainInfo *info)
2266 {
2267         struct netr_trust_extension *tei = NULL;
2268
2269         ZERO_STRUCTP(info);
2270
2271         /* w2k8 only fills this on trusted domains */
2272         tei = talloc_zero(mem_ctx, struct netr_trust_extension);
2273         if (tei == NULL) {
2274                 return NT_STATUS_NO_MEMORY;
2275         }
2276
2277         if (tdo->trust_direction & LSA_TRUST_DIRECTION_INBOUND) {
2278                 tei->flags |= NETR_TRUST_FLAG_INBOUND;
2279         }
2280         if (tdo->trust_direction & LSA_TRUST_DIRECTION_OUTBOUND) {
2281                 tei->flags |= NETR_TRUST_FLAG_OUTBOUND;
2282         }
2283         if (tdo->trust_attributes & LSA_TRUST_ATTRIBUTE_WITHIN_FOREST) {
2284                 tei->flags |= NETR_TRUST_FLAG_IN_FOREST;
2285         }
2286
2287         /*
2288          * TODO: once we support multiple domains within our forest,
2289          * we need to fill this correct (or let the caller do it
2290          * for all domains marked with NETR_TRUST_FLAG_IN_FOREST).
2291          */
2292         tei->parent_index = 0;
2293
2294         tei->trust_type = tdo->trust_type;
2295         tei->trust_attributes = tdo->trust_attributes;
2296
2297         info->trust_extension.info = tei;
2298         info->trust_extension.length = 16;
2299
2300         info->domainname.string = tdo->netbios_name.string;
2301         if (tdo->trust_type != LSA_TRUST_TYPE_DOWNLEVEL) {
2302                 info->dns_domainname.string = tdo->domain_name.string;
2303         } else {
2304                 info->dns_domainname.string = NULL;
2305         }
2306         info->domain_sid = tdo->sid;
2307         info->domain_guid = domain_guid;
2308
2309         /* MS-NRPC 3.5.4.3.9 - must be set to NULL for trust list */
2310         info->dns_forestname.string = NULL;
2311
2312         return NT_STATUS_OK;
2313 }
2314
2315 /*
2316   netr_LogonGetDomainInfo
2317   this is called as part of the ADS domain logon procedure.
2318
2319   It has an important role in convaying details about the client, such
2320   as Operating System, Version, Service Pack etc.
2321 */
2322 static NTSTATUS dcesrv_netr_LogonGetDomainInfo(struct dcesrv_call_state *dce_call,
2323         TALLOC_CTX *mem_ctx, struct netr_LogonGetDomainInfo *r)
2324 {
2325         struct netlogon_creds_CredentialState *creds;
2326         const char * const trusts_attrs[] = {
2327                 "securityIdentifier",
2328                 "flatName",
2329                 "trustPartner",
2330                 "trustAttributes",
2331                 "trustDirection",
2332                 "trustType",
2333                 NULL
2334         };
2335         const char * const attrs2[] = { "sAMAccountName", "dNSHostName",
2336                 "msDS-SupportedEncryptionTypes", NULL };
2337         const char *sam_account_name, *old_dns_hostname, *prefix1, *prefix2;
2338         struct ldb_context *sam_ctx;
2339         const struct GUID *our_domain_guid = NULL;
2340         struct lsa_TrustDomainInfoInfoEx *our_tdo = NULL;
2341         struct ldb_message **res1, *new_msg;
2342         struct ldb_result *trusts_res = NULL;
2343         struct ldb_dn *workstation_dn;
2344         struct netr_DomainInformation *domain_info;
2345         struct netr_LsaPolicyInformation *lsa_policy_info;
2346         uint32_t default_supported_enc_types = 0xFFFFFFFF;
2347         bool update_dns_hostname = true;
2348         int ret, i;
2349         NTSTATUS status;
2350
2351         status = dcesrv_netr_creds_server_step_check(dce_call,
2352                                                      mem_ctx,
2353                                                      r->in.computer_name,
2354                                                      r->in.credential,
2355                                                      r->out.return_authenticator,
2356                                                      &creds);
2357         if (!NT_STATUS_IS_OK(status)) {
2358                 char* local  = NULL;
2359                 char* remote = NULL;
2360                 TALLOC_CTX *frame = talloc_stackframe();
2361                 remote = tsocket_address_string(dce_call->conn->remote_address,
2362                                                 frame);
2363                 local  = tsocket_address_string(dce_call->conn->local_address,
2364                                                 frame);
2365                 DBG_ERR(("Bad credentials - "
2366                          "computer[%s] remote[%s] local[%s]\n"),
2367                         log_escape(frame, r->in.computer_name),
2368                         remote,
2369                         local);
2370                 talloc_free(frame);
2371         }
2372         NT_STATUS_NOT_OK_RETURN(status);
2373
2374         sam_ctx = samdb_connect(mem_ctx,
2375                                 dce_call->event_ctx,
2376                                 dce_call->conn->dce_ctx->lp_ctx,
2377                                 system_session(dce_call->conn->dce_ctx->lp_ctx),
2378                                 dce_call->conn->remote_address,
2379                                 0);
2380         if (sam_ctx == NULL) {
2381                 return NT_STATUS_INVALID_SYSTEM_SERVICE;
2382         }
2383
2384         switch (r->in.level) {
2385         case 1: /* Domain information */
2386
2387                 if (r->in.query->workstation_info == NULL) {
2388                         return NT_STATUS_INVALID_PARAMETER;
2389                 }
2390
2391                 /* Prepares the workstation DN */
2392                 workstation_dn = ldb_dn_new_fmt(mem_ctx, sam_ctx, "<SID=%s>",
2393                                                 dom_sid_string(mem_ctx, creds->sid));
2394                 NT_STATUS_HAVE_NO_MEMORY(workstation_dn);
2395
2396                 /* Lookup for attributes in workstation object */
2397                 ret = gendb_search_dn(sam_ctx, mem_ctx, workstation_dn, &res1,
2398                                       attrs2);
2399                 if (ret != 1) {
2400                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
2401                 }
2402
2403                 /* Gets the sam account name which is checked against the DNS
2404                  * hostname parameter. */
2405                 sam_account_name = ldb_msg_find_attr_as_string(res1[0],
2406                                                                "sAMAccountName",
2407                                                                NULL);
2408                 if (sam_account_name == NULL) {
2409                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
2410                 }
2411
2412                 /*
2413                  * Checks that the sam account name without a possible "$"
2414                  * matches as prefix with the DNS hostname in the workstation
2415                  * info structure.
2416                  */
2417                 prefix1 = talloc_strndup(mem_ctx, sam_account_name,
2418                                          strcspn(sam_account_name, "$"));
2419                 NT_STATUS_HAVE_NO_MEMORY(prefix1);
2420                 if (r->in.query->workstation_info->dns_hostname != NULL) {
2421                         prefix2 = talloc_strndup(mem_ctx,
2422                                                  r->in.query->workstation_info->dns_hostname,
2423                                                  strcspn(r->in.query->workstation_info->dns_hostname, "."));
2424                         NT_STATUS_HAVE_NO_MEMORY(prefix2);
2425
2426                         if (strcasecmp(prefix1, prefix2) != 0) {
2427                                 update_dns_hostname = false;
2428                         }
2429                 } else {
2430                         update_dns_hostname = false;
2431                 }
2432
2433                 /* Gets the old DNS hostname */
2434                 old_dns_hostname = ldb_msg_find_attr_as_string(res1[0],
2435                                                                "dNSHostName",
2436                                                                NULL);
2437
2438                 /*
2439                  * Updates the DNS hostname when the client wishes that the
2440                  * server should handle this for him
2441                  * ("NETR_WS_FLAG_HANDLES_SPN_UPDATE" not set). And this is
2442                  * obviously only checked when we do already have a
2443                  * "dNSHostName".
2444                  * See MS-NRPC section 3.5.4.3.9
2445                  */
2446                 if ((old_dns_hostname != NULL) &&
2447                     (r->in.query->workstation_info->workstation_flags
2448                     & NETR_WS_FLAG_HANDLES_SPN_UPDATE) != 0) {
2449                         update_dns_hostname = false;
2450                 }
2451
2452                 /* Gets host information and put them into our directory */
2453
2454                 new_msg = ldb_msg_new(mem_ctx);
2455                 NT_STATUS_HAVE_NO_MEMORY(new_msg);
2456
2457                 new_msg->dn = workstation_dn;
2458
2459                 /* Sets the OS name */
2460
2461                 if (r->in.query->workstation_info->os_name.string == NULL) {
2462                         return NT_STATUS_INVALID_PARAMETER;
2463                 }
2464
2465                 ret = ldb_msg_add_string(new_msg, "operatingSystem",
2466                                          r->in.query->workstation_info->os_name.string);
2467                 if (ret != LDB_SUCCESS) {
2468                         return NT_STATUS_NO_MEMORY;
2469                 }
2470
2471                 /*
2472                  * Sets information from "os_version". On an empty structure
2473                  * the values are cleared.
2474                  */
2475                 if (r->in.query->workstation_info->os_version.os != NULL) {
2476                         struct netr_OsVersionInfoEx *os_version;
2477                         const char *os_version_str;
2478
2479                         os_version = &r->in.query->workstation_info->os_version.os->os;
2480
2481                         if (os_version->CSDVersion == NULL) {
2482                                 return NT_STATUS_INVALID_PARAMETER;
2483                         }
2484
2485                         os_version_str = talloc_asprintf(new_msg, "%u.%u (%u)",
2486                                                          os_version->MajorVersion,
2487                                                          os_version->MinorVersion,
2488                                                          os_version->BuildNumber);
2489                         NT_STATUS_HAVE_NO_MEMORY(os_version_str);
2490
2491                         ret = ldb_msg_add_string(new_msg,
2492                                                  "operatingSystemServicePack",
2493                                                  os_version->CSDVersion);
2494                         if (ret != LDB_SUCCESS) {
2495                                 return NT_STATUS_NO_MEMORY;
2496                         }
2497
2498                         ret = ldb_msg_add_string(new_msg,
2499                                                  "operatingSystemVersion",
2500                                                  os_version_str);
2501                         if (ret != LDB_SUCCESS) {
2502                                 return NT_STATUS_NO_MEMORY;
2503                         }
2504                 } else {
2505                         ret = samdb_msg_add_delete(sam_ctx, mem_ctx, new_msg,
2506                                                    "operatingSystemServicePack");
2507                         if (ret != LDB_SUCCESS) {
2508                                 return NT_STATUS_NO_MEMORY;
2509                         }
2510
2511                         ret = samdb_msg_add_delete(sam_ctx, mem_ctx, new_msg,
2512                                                    "operatingSystemVersion");
2513                         if (ret != LDB_SUCCESS) {
2514                                 return NT_STATUS_NO_MEMORY;
2515                         }
2516                 }
2517
2518                 /*
2519                  * If the boolean "update_dns_hostname" remained true, then we
2520                  * are fine to start the update.
2521                  */
2522                 if (update_dns_hostname) {
2523                         ret = ldb_msg_add_string(new_msg,
2524                                                  "dNSHostname",
2525                                                  r->in.query->workstation_info->dns_hostname);
2526                         if (ret != LDB_SUCCESS) {
2527                                 return NT_STATUS_NO_MEMORY;
2528                         }
2529
2530                         /* This manual "servicePrincipalName" generation is
2531                          * still needed! Since the update in the samldb LDB
2532                          * module does only work if the entries already exist
2533                          * which isn't always the case. */
2534                         ret = ldb_msg_add_string(new_msg,
2535                                                  "servicePrincipalName",
2536                                                  talloc_asprintf(new_msg, "HOST/%s",
2537                                                  r->in.computer_name));
2538                         if (ret != LDB_SUCCESS) {
2539                                 return NT_STATUS_NO_MEMORY;
2540                         }
2541
2542                         ret = ldb_msg_add_string(new_msg,
2543                                                  "servicePrincipalName",
2544                                                  talloc_asprintf(new_msg, "HOST/%s",
2545                                                  r->in.query->workstation_info->dns_hostname));
2546                         if (ret != LDB_SUCCESS) {
2547                                 return NT_STATUS_NO_MEMORY;
2548                         }
2549                 }
2550
2551                 if (dsdb_replace(sam_ctx, new_msg, 0) != LDB_SUCCESS) {
2552                         DEBUG(3,("Impossible to update samdb: %s\n",
2553                                 ldb_errstring(sam_ctx)));
2554                 }
2555
2556                 talloc_free(new_msg);
2557
2558                 /* Writes back the domain information */
2559
2560                 our_domain_guid = samdb_domain_guid(sam_ctx);
2561                 if (our_domain_guid == NULL) {
2562                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
2563                 }
2564
2565                 status = dsdb_trust_local_tdo_info(mem_ctx, sam_ctx, &our_tdo);
2566                 if (!NT_STATUS_IS_OK(status)) {
2567                         return status;
2568                 }
2569
2570                 status = dsdb_trust_search_tdos(sam_ctx,
2571                                                 NULL, /* exclude */
2572                                                 trusts_attrs,
2573                                                 mem_ctx,
2574                                                 &trusts_res);
2575                 if (!NT_STATUS_IS_OK(status)) {
2576                         return status;
2577                 }
2578
2579                 domain_info = talloc(mem_ctx, struct netr_DomainInformation);
2580                 NT_STATUS_HAVE_NO_MEMORY(domain_info);
2581
2582                 ZERO_STRUCTP(domain_info);
2583
2584                 /* Informations about the local and trusted domains */
2585
2586                 status = fill_our_one_domain_info(mem_ctx,
2587                                                   our_tdo,
2588                                                   *our_domain_guid,
2589                                                   &domain_info->primary_domain,
2590                                                   false);
2591                 if (!NT_STATUS_IS_OK(status)) {
2592                         return status;
2593                 }
2594
2595                 domain_info->trusted_domain_count = trusts_res->count + 1;
2596                 domain_info->trusted_domains = talloc_zero_array(mem_ctx,
2597                         struct netr_OneDomainInfo,
2598                         domain_info->trusted_domain_count);
2599                 NT_STATUS_HAVE_NO_MEMORY(domain_info->trusted_domains);
2600
2601                 for (i=0; i < trusts_res->count; i++) {
2602                         struct netr_OneDomainInfo *o =
2603                                 &domain_info->trusted_domains[i];
2604                         /* we can't know the guid of trusts outside our forest */
2605                         struct GUID trust_domain_guid = GUID_zero();
2606                         struct lsa_TrustDomainInfoInfoEx *tdo = NULL;
2607
2608                         status = dsdb_trust_parse_tdo_info(mem_ctx,
2609                                                            trusts_res->msgs[i],
2610                                                            &tdo);
2611                         if (!NT_STATUS_IS_OK(status)) {
2612                                 return status;
2613                         }
2614
2615                         status = fill_trust_one_domain_info(mem_ctx,
2616                                                             trust_domain_guid,
2617                                                             tdo,
2618                                                             o);
2619                         if (!NT_STATUS_IS_OK(status)) {
2620                                 return status;
2621                         }
2622                 }
2623
2624                 status = fill_our_one_domain_info(mem_ctx,
2625                                                   our_tdo,
2626                                                   *our_domain_guid,
2627                                                   &domain_info->trusted_domains[i],
2628                                                   true);
2629                 if (!NT_STATUS_IS_OK(status)) {
2630                         return status;
2631                 }
2632
2633                 /* Sets the supported encryption types */
2634                 domain_info->supported_enc_types = ldb_msg_find_attr_as_uint(res1[0],
2635                         "msDS-SupportedEncryptionTypes",
2636                         default_supported_enc_types);
2637
2638                 /* Other host domain information */
2639
2640                 lsa_policy_info = talloc(mem_ctx,
2641                         struct netr_LsaPolicyInformation);
2642                 NT_STATUS_HAVE_NO_MEMORY(lsa_policy_info);
2643                 ZERO_STRUCTP(lsa_policy_info);
2644
2645                 domain_info->lsa_policy = *lsa_policy_info;
2646
2647                 /* The DNS hostname is only returned back when there is a chance
2648                  * for a change. */
2649                 if ((r->in.query->workstation_info->workstation_flags
2650                     & NETR_WS_FLAG_HANDLES_SPN_UPDATE) != 0) {
2651                         domain_info->dns_hostname.string = old_dns_hostname;
2652                 } else {
2653                         domain_info->dns_hostname.string = NULL;
2654                 }
2655
2656                 domain_info->workstation_flags =
2657                         r->in.query->workstation_info->workstation_flags & (
2658                         NETR_WS_FLAG_HANDLES_SPN_UPDATE | NETR_WS_FLAG_HANDLES_INBOUND_TRUSTS);
2659
2660                 r->out.info->domain_info = domain_info;
2661         break;
2662         case 2: /* LSA policy information - not used at the moment */
2663                 lsa_policy_info = talloc(mem_ctx,
2664                         struct netr_LsaPolicyInformation);
2665                 NT_STATUS_HAVE_NO_MEMORY(lsa_policy_info);
2666                 ZERO_STRUCTP(lsa_policy_info);
2667
2668                 r->out.info->lsa_policy_info = lsa_policy_info;
2669         break;
2670         default:
2671                 return NT_STATUS_INVALID_LEVEL;
2672         break;
2673         }
2674
2675         return NT_STATUS_OK;
2676 }
2677
2678
2679 /*
2680   netr_ServerPasswordGet
2681 */
2682 static NTSTATUS dcesrv_netr_ServerPasswordGet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2683                        struct netr_ServerPasswordGet *r)
2684 {
2685         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2686 }
2687
2688 static bool sam_rodc_access_check(struct ldb_context *sam_ctx,
2689                                   TALLOC_CTX *mem_ctx,
2690                                   struct dom_sid *user_sid,
2691                                   struct ldb_dn *obj_dn)
2692 {
2693         const char *rodc_attrs[] = { "msDS-KrbTgtLink", "msDS-NeverRevealGroup", "msDS-RevealOnDemandGroup", "objectGUID", NULL };
2694         const char *obj_attrs[] = { "tokenGroups", "objectSid", "UserAccountControl", "msDS-KrbTgtLinkBL", NULL };
2695         struct ldb_dn *rodc_dn;
2696         int ret;
2697         struct ldb_result *rodc_res = NULL, *obj_res = NULL;
2698         const struct dom_sid *additional_sids[] = { NULL, NULL };
2699         WERROR werr;
2700         struct dom_sid *object_sid;
2701         const struct dom_sid **never_reveal_sids, **reveal_sids, **token_sids;
2702
2703         rodc_dn = ldb_dn_new_fmt(mem_ctx, sam_ctx, "<SID=%s>",
2704                                  dom_sid_string(mem_ctx, user_sid));
2705         if (!ldb_dn_validate(rodc_dn)) goto denied;
2706
2707         /* do the two searches we need */
2708         ret = dsdb_search_dn(sam_ctx, mem_ctx, &rodc_res, rodc_dn, rodc_attrs,
2709                              DSDB_SEARCH_SHOW_EXTENDED_DN);
2710         if (ret != LDB_SUCCESS || rodc_res->count != 1) goto denied;
2711
2712         ret = dsdb_search_dn(sam_ctx, mem_ctx, &obj_res, obj_dn, obj_attrs, 0);
2713         if (ret != LDB_SUCCESS || obj_res->count != 1) goto denied;
2714
2715         object_sid = samdb_result_dom_sid(mem_ctx, obj_res->msgs[0], "objectSid");
2716
2717         additional_sids[0] = object_sid;
2718
2719         werr = samdb_result_sid_array_dn(sam_ctx, rodc_res->msgs[0],
2720                                          mem_ctx, "msDS-NeverRevealGroup", &never_reveal_sids);
2721         if (!W_ERROR_IS_OK(werr)) {
2722                 goto denied;
2723         }
2724
2725         werr = samdb_result_sid_array_dn(sam_ctx, rodc_res->msgs[0],
2726                                          mem_ctx, "msDS-RevealOnDemandGroup", &reveal_sids);
2727         if (!W_ERROR_IS_OK(werr)) {
2728                 goto denied;
2729         }
2730
2731         /*
2732          * The SID list needs to include itself as well as the tokenGroups.
2733          *
2734          * TODO determine if sIDHistory is required for this check
2735          */
2736         werr = samdb_result_sid_array_ndr(sam_ctx, obj_res->msgs[0],
2737                                           mem_ctx, "tokenGroups", &token_sids,
2738                                           additional_sids, 1);
2739         if (!W_ERROR_IS_OK(werr) || token_sids==NULL) {
2740                 goto denied;
2741         }
2742
2743         if (never_reveal_sids &&
2744             sid_list_match(token_sids, never_reveal_sids)) {
2745                 goto denied;
2746         }
2747
2748         if (reveal_sids &&
2749             sid_list_match(token_sids, reveal_sids)) {
2750                 goto allowed;
2751         }
2752
2753 denied:
2754         return false;
2755 allowed:
2756         return true;
2757
2758 }
2759
2760 /*
2761   netr_NetrLogonSendToSam
2762 */
2763 static NTSTATUS dcesrv_netr_NetrLogonSendToSam(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2764                                                struct netr_NetrLogonSendToSam *r)
2765 {
2766         struct netlogon_creds_CredentialState *creds;
2767         struct ldb_context *sam_ctx;
2768         NTSTATUS nt_status;
2769         DATA_BLOB decrypted_blob;
2770         enum ndr_err_code ndr_err;
2771         struct netr_SendToSamBase base_msg = { 0 };
2772
2773         nt_status = dcesrv_netr_creds_server_step_check(dce_call,
2774                                                         mem_ctx,
2775                                                         r->in.computer_name,
2776                                                         r->in.credential,
2777                                                         r->out.return_authenticator,
2778                                                         &creds);
2779
2780         NT_STATUS_NOT_OK_RETURN(nt_status);
2781
2782         switch (creds->secure_channel_type) {
2783         case SEC_CHAN_BDC:
2784         case SEC_CHAN_RODC:
2785                 break;
2786         case SEC_CHAN_WKSTA:
2787         case SEC_CHAN_DNS_DOMAIN:
2788         case SEC_CHAN_DOMAIN:
2789         case SEC_CHAN_NULL:
2790                 return NT_STATUS_INVALID_PARAMETER;
2791         default:
2792                 DEBUG(1, ("Client asked for an invalid secure channel type: %d\n",
2793                           creds->secure_channel_type));
2794                 return NT_STATUS_INVALID_PARAMETER;
2795         }
2796
2797         sam_ctx = samdb_connect(mem_ctx,
2798                                 dce_call->event_ctx,
2799                                 dce_call->conn->dce_ctx->lp_ctx,
2800                                 system_session(dce_call->conn->dce_ctx->lp_ctx),
2801                                 dce_call->conn->remote_address,
2802                                 0);
2803         if (sam_ctx == NULL) {
2804                 return NT_STATUS_INVALID_SYSTEM_SERVICE;
2805         }
2806
2807         /* Buffer is meant to be 16-bit aligned */
2808         if (creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
2809                 netlogon_creds_aes_decrypt(creds, r->in.opaque_buffer, r->in.buffer_len);
2810         } else {
2811                 netlogon_creds_arcfour_crypt(creds, r->in.opaque_buffer, r->in.buffer_len);
2812         }
2813
2814         decrypted_blob.data = r->in.opaque_buffer;
2815         decrypted_blob.length = r->in.buffer_len;
2816
2817         ndr_err = ndr_pull_struct_blob(&decrypted_blob, mem_ctx, &base_msg,
2818                                        (ndr_pull_flags_fn_t)ndr_pull_netr_SendToSamBase);
2819
2820         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2821                 /* We only partially implement SendToSam */
2822                 return NT_STATUS_NOT_IMPLEMENTED;
2823         }
2824
2825         /* Now 'send' to SAM */
2826         switch (base_msg.message_type) {
2827         case SendToSamResetBadPasswordCount:
2828         {
2829                 struct ldb_message *msg = ldb_msg_new(mem_ctx);
2830                 struct ldb_dn *dn = NULL;
2831                 int ret = 0;
2832
2833
2834                 ret = ldb_transaction_start(sam_ctx);
2835                 if (ret != LDB_SUCCESS) {
2836                         return NT_STATUS_INTERNAL_ERROR;
2837                 }
2838
2839                 ret = dsdb_find_dn_by_guid(sam_ctx,
2840                                            mem_ctx,
2841                                            &base_msg.message.reset_bad_password.guid,
2842                                            0,
2843                                            &dn);
2844                 if (ret != LDB_SUCCESS) {
2845                         ldb_transaction_cancel(sam_ctx);
2846                         return NT_STATUS_INVALID_PARAMETER;
2847                 }
2848
2849                 if (creds->secure_channel_type == SEC_CHAN_RODC &&
2850                     !sam_rodc_access_check(sam_ctx, mem_ctx, creds->sid, dn)) {
2851                         DEBUG(1, ("Client asked to reset bad password on "
2852                                   "an arbitrary user: %s\n",
2853                                   ldb_dn_get_linearized(dn)));
2854                         ldb_transaction_cancel(sam_ctx);
2855                         return NT_STATUS_INVALID_PARAMETER;
2856                 }
2857
2858                 msg->dn = dn;
2859
2860                 ret = samdb_msg_add_int(sam_ctx, mem_ctx, msg, "badPwdCount", 0);
2861                 if (ret != LDB_SUCCESS) {
2862                         ldb_transaction_cancel(sam_ctx);
2863                         return NT_STATUS_INVALID_PARAMETER;
2864                 }
2865
2866                 ret = dsdb_replace(sam_ctx, msg, 0);
2867                 if (ret != LDB_SUCCESS) {
2868                         ldb_transaction_cancel(sam_ctx);
2869                         return NT_STATUS_INVALID_PARAMETER;
2870                 }
2871
2872                 ret = ldb_transaction_commit(sam_ctx);
2873                 if (ret != LDB_SUCCESS) {
2874                         ldb_transaction_cancel(sam_ctx);
2875                         return NT_STATUS_INTERNAL_ERROR;
2876                 }
2877
2878                 break;
2879         }
2880         default:
2881                 return NT_STATUS_NOT_IMPLEMENTED;
2882         }
2883
2884         return NT_STATUS_OK;
2885 }
2886
2887 struct dcesrv_netr_DsRGetDCName_base_state {
2888         struct dcesrv_call_state *dce_call;
2889         TALLOC_CTX *mem_ctx;
2890
2891         struct netr_DsRGetDCNameEx2 r;
2892         const char *client_site;
2893
2894         struct {
2895                 struct netr_DsRGetDCName *dc;
2896                 struct netr_DsRGetDCNameEx *dcex;
2897                 struct netr_DsRGetDCNameEx2 *dcex2;
2898         } _r;
2899 };
2900
2901 static void dcesrv_netr_DsRGetDCName_base_done(struct tevent_req *subreq);
2902
2903 static WERROR dcesrv_netr_DsRGetDCName_base_call(struct dcesrv_netr_DsRGetDCName_base_state *state)
2904 {
2905         struct dcesrv_call_state *dce_call = state->dce_call;
2906         TALLOC_CTX *mem_ctx = state->mem_ctx;
2907         struct netr_DsRGetDCNameEx2 *r = &state->r;
2908         struct ldb_context *sam_ctx;
2909         struct netr_DsRGetDCNameInfo *info;
2910         struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2911         const struct tsocket_address *local_address;
2912         char *local_addr = NULL;
2913         const struct tsocket_address *remote_address;
2914         char *remote_addr = NULL;
2915         const char *server_site_name;
2916         char *guid_str;
2917         struct netlogon_samlogon_response response;
2918         NTSTATUS status;
2919         const char *dc_name = NULL;
2920         const char *domain_name = NULL;
2921         const char *pdc_ip;
2922         bool different_domain = true;
2923
2924         ZERO_STRUCTP(r->out.info);
2925
2926         sam_ctx = samdb_connect(state,
2927                                 dce_call->event_ctx,
2928                                 lp_ctx,
2929                                 dce_call->conn->auth_state.session_info,
2930                                 dce_call->conn->remote_address,
2931                                 0);
2932         if (sam_ctx == NULL) {
2933                 return WERR_DS_UNAVAILABLE;
2934         }
2935
2936         local_address = dcesrv_connection_get_local_address(dce_call->conn);
2937         if (tsocket_address_is_inet(local_address, "ip")) {
2938                 local_addr = tsocket_address_inet_addr_string(local_address, state);
2939                 W_ERROR_HAVE_NO_MEMORY(local_addr);
2940         }
2941
2942         remote_address = dcesrv_connection_get_remote_address(dce_call->conn);
2943         if (tsocket_address_is_inet(remote_address, "ip")) {
2944                 remote_addr = tsocket_address_inet_addr_string(remote_address, state);
2945                 W_ERROR_HAVE_NO_MEMORY(remote_addr);
2946         }
2947
2948         /* "server_unc" is ignored by w2k3 */
2949
2950         if (r->in.flags & ~(DSGETDC_VALID_FLAGS)) {
2951                 return WERR_INVALID_FLAGS;
2952         }
2953
2954         if (r->in.flags & DS_GC_SERVER_REQUIRED &&
2955             r->in.flags & DS_PDC_REQUIRED &&
2956             r->in.flags & DS_KDC_REQUIRED) {
2957                 return WERR_INVALID_FLAGS;
2958         }
2959         if (r->in.flags & DS_IS_FLAT_NAME &&
2960             r->in.flags & DS_IS_DNS_NAME) {
2961                 return WERR_INVALID_FLAGS;
2962         }
2963         if (r->in.flags & DS_RETURN_DNS_NAME &&
2964             r->in.flags & DS_RETURN_FLAT_NAME) {
2965                 return WERR_INVALID_FLAGS;
2966         }
2967         if (r->in.flags & DS_DIRECTORY_SERVICE_REQUIRED &&
2968             r->in.flags & DS_DIRECTORY_SERVICE_6_REQUIRED) {
2969                 return WERR_INVALID_FLAGS;
2970         }
2971
2972         if (r->in.flags & DS_GOOD_TIMESERV_PREFERRED &&
2973             r->in.flags &
2974             (DS_DIRECTORY_SERVICE_REQUIRED |
2975              DS_DIRECTORY_SERVICE_PREFERRED |
2976              DS_GC_SERVER_REQUIRED |
2977              DS_PDC_REQUIRED |
2978              DS_KDC_REQUIRED)) {
2979                 return WERR_INVALID_FLAGS;
2980         }
2981
2982         if (r->in.flags & DS_TRY_NEXTCLOSEST_SITE &&
2983             r->in.site_name) {
2984                 return WERR_INVALID_FLAGS;
2985         }
2986
2987         /*
2988          * If we send an all-zero GUID, we should ignore it as winbind actually
2989          * checks it with a DNS query. Windows also appears to ignore it.
2990          */
2991         if (r->in.domain_guid != NULL && GUID_all_zero(r->in.domain_guid)) {
2992                 r->in.domain_guid = NULL;
2993         }
2994
2995         /* Attempt winbind search only if we suspect the domain is incorrect */
2996         if (r->in.domain_name != NULL && strcmp("", r->in.domain_name) != 0) {
2997                 if (r->in.flags & DS_IS_FLAT_NAME) {
2998                         if (strcasecmp_m(r->in.domain_name,
2999                                          lpcfg_sam_name(lp_ctx)) == 0) {
3000                                 different_domain = false;
3001                         }
3002                 } else if (r->in.flags & DS_IS_DNS_NAME) {
3003                         if (strcasecmp_m(r->in.domain_name,
3004                                          lpcfg_dnsdomain(lp_ctx)) == 0) {
3005                                 different_domain = false;
3006                         }
3007                 } else {
3008                         if (strcasecmp_m(r->in.domain_name,
3009                                          lpcfg_sam_name(lp_ctx)) == 0 ||
3010                             strcasecmp_m(r->in.domain_name,
3011                                          lpcfg_dnsdomain(lp_ctx)) == 0) {
3012                                 different_domain = false;
3013                         }
3014                 }
3015         } else {
3016                 /*
3017                  * We need to be able to handle empty domain names, where we
3018                  * revert to our domain by default.
3019                  */
3020                 different_domain = false;
3021         }
3022
3023         /* Proof server site parameter "site_name" if it was specified */
3024         server_site_name = samdb_server_site_name(sam_ctx, state);
3025         W_ERROR_HAVE_NO_MEMORY(server_site_name);
3026         if (different_domain || (r->in.site_name != NULL &&
3027                                  (strcasecmp_m(r->in.site_name,
3028                                              server_site_name) != 0))) {
3029
3030                 struct dcerpc_binding_handle *irpc_handle = NULL;
3031                 struct tevent_req *subreq = NULL;
3032
3033                 /*
3034                  * Retrieve the client site to override the winbind response.
3035                  *
3036                  * DO NOT use Windows fallback for client site.
3037                  * In the case of multiple domains, this is plainly wrong.
3038                  *
3039                  * Note: It's possible that the client may belong to multiple
3040                  * subnets across domains. It's not clear what this would mean,
3041                  * but here we only return what this domain knows.
3042                  */
3043                 state->client_site = samdb_client_site_name(sam_ctx,
3044                                                             state,
3045                                                             remote_addr,
3046                                                             NULL,
3047                                                             false);
3048
3049                 irpc_handle = irpc_binding_handle_by_name(state,
3050                                                           dce_call->msg_ctx,
3051                                                           "winbind_server",
3052                                                           &ndr_table_winbind);
3053                 if (irpc_handle == NULL) {
3054                         DEBUG(0,("Failed to get binding_handle for "
3055                                  "winbind_server task\n"));
3056                         dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
3057                         return WERR_SERVICE_NOT_FOUND;
3058                 }
3059
3060                 dcerpc_binding_handle_set_timeout(irpc_handle, 60);
3061
3062                 dce_call->state_flags |= DCESRV_CALL_STATE_FLAG_ASYNC;
3063
3064                 subreq = dcerpc_wbint_DsGetDcName_send(state,
3065                                                        dce_call->event_ctx,
3066                                                        irpc_handle,
3067                                                        r->in.domain_name,
3068                                                        r->in.domain_guid,
3069                                                        r->in.site_name,
3070                                                        r->in.flags,
3071                                                        r->out.info);
3072                 if (subreq == NULL) {
3073                         return WERR_NOT_ENOUGH_MEMORY;
3074                 }
3075
3076                 tevent_req_set_callback(subreq,
3077                                         dcesrv_netr_DsRGetDCName_base_done,
3078                                         state);
3079
3080                 return WERR_OK;
3081         }
3082
3083         guid_str = r->in.domain_guid != NULL ?
3084                  GUID_string(state, r->in.domain_guid) : NULL;
3085
3086         status = fill_netlogon_samlogon_response(sam_ctx, mem_ctx,
3087                                                  r->in.domain_name,
3088                                                  r->in.domain_name,
3089                                                  NULL, guid_str,
3090                                                  r->in.client_account,
3091                                                  r->in.mask, remote_addr,
3092                                                  NETLOGON_NT_VERSION_5EX_WITH_IP,
3093                                                  lp_ctx, &response, true);
3094         if (!NT_STATUS_IS_OK(status)) {
3095                 return ntstatus_to_werror(status);
3096         }
3097
3098         /*
3099          * According to MS-NRPC 2.2.1.2.1 we should set the "DS_DNS_FOREST_ROOT"
3100          * (O) flag when the returned forest name is in DNS format. This is here
3101          * always the case (see below).
3102          */
3103         response.data.nt5_ex.server_type |= DS_DNS_FOREST_ROOT;
3104
3105         if (r->in.flags & DS_RETURN_DNS_NAME) {
3106                 dc_name = response.data.nt5_ex.pdc_dns_name;
3107                 domain_name = response.data.nt5_ex.dns_domain;
3108                 /*
3109                  * According to MS-NRPC 2.2.1.2.1 we should set the
3110                  * "DS_DNS_CONTROLLER" (M) and "DS_DNS_DOMAIN" (N) flags when
3111                  * the returned information is in DNS form.
3112                  */
3113                 response.data.nt5_ex.server_type |=
3114                         DS_DNS_CONTROLLER | DS_DNS_DOMAIN;
3115         } else if (r->in.flags & DS_RETURN_FLAT_NAME) {
3116                 dc_name = response.data.nt5_ex.pdc_name;
3117                 domain_name = response.data.nt5_ex.domain_name;
3118         } else {
3119
3120                 /*
3121                  * TODO: autodetect what we need to return
3122                  * based on the given arguments
3123                  */
3124                 dc_name = response.data.nt5_ex.pdc_name;
3125                 domain_name = response.data.nt5_ex.domain_name;
3126         }
3127
3128         if (!dc_name || !dc_name[0]) {
3129                 return WERR_NO_SUCH_DOMAIN;
3130         }
3131
3132         if (!domain_name || !domain_name[0]) {
3133                 return WERR_NO_SUCH_DOMAIN;
3134         }
3135
3136         info = talloc(mem_ctx, struct netr_DsRGetDCNameInfo);
3137         W_ERROR_HAVE_NO_MEMORY(info);
3138         info->dc_unc = talloc_asprintf(mem_ctx, "%s%s",
3139                         dc_name[0] != '\\'? "\\\\":"",
3140                         talloc_strdup(mem_ctx, dc_name));
3141         W_ERROR_HAVE_NO_MEMORY(info->dc_unc);
3142
3143         pdc_ip = local_addr;
3144         if (pdc_ip == NULL) {
3145                 pdc_ip = "127.0.0.1";
3146         }
3147         info->dc_address = talloc_asprintf(mem_ctx, "\\\\%s", pdc_ip);
3148         W_ERROR_HAVE_NO_MEMORY(info->dc_address);
3149         info->dc_address_type  = DS_ADDRESS_TYPE_INET;
3150         info->domain_guid      = response.data.nt5_ex.domain_uuid;
3151         info->domain_name      = domain_name;
3152         info->forest_name      = response.data.nt5_ex.forest;
3153         info->dc_flags         = response.data.nt5_ex.server_type;
3154         if (r->in.flags & DS_RETURN_DNS_NAME) {
3155                 /* As MS-NRPC.pdf in 2.2.1.2.1 the DS_DNS_CONTROLLER flag should be
3156                  * returned if we are returning info->dc_unc containing a FQDN.
3157                  * This attribute is called DomainControllerName in the specs,
3158                  * it seems that we decide to return FQDN or netbios depending on
3159                  * DS_RETURN_DNS_NAME.
3160                  */
3161                 info->dc_flags |= DS_DNS_CONTROLLER;
3162         }
3163         info->dc_site_name     = response.data.nt5_ex.server_site;
3164         info->client_site_name = response.data.nt5_ex.client_site;
3165
3166         *r->out.info = info;
3167
3168         return WERR_OK;
3169 }
3170
3171 static void dcesrv_netr_DsRGetDCName_base_done(struct tevent_req *subreq)
3172 {
3173         struct dcesrv_netr_DsRGetDCName_base_state *state =
3174                 tevent_req_callback_data(subreq,
3175                 struct dcesrv_netr_DsRGetDCName_base_state);
3176         struct dcesrv_call_state *dce_call = state->dce_call;
3177         NTSTATUS result, status;
3178
3179         status = dcerpc_wbint_DsGetDcName_recv(subreq,
3180                                                state->mem_ctx,
3181                                                &result);
3182         TALLOC_FREE(subreq);
3183
3184         if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) {
3185                 state->r.out.result = WERR_TIMEOUT;
3186                 goto finished;
3187         }
3188
3189         if (!NT_STATUS_IS_OK(status)) {
3190                 DBG_ERR(__location__ ": IRPC callback failed %s\n",
3191                         nt_errstr(status));
3192                 state->r.out.result = WERR_GEN_FAILURE;
3193                 goto finished;
3194         }
3195
3196         if (!NT_STATUS_IS_OK(result)) {
3197                 DBG_NOTICE("DC location via winbind failed - %s\n",
3198                            nt_errstr(result));
3199                 state->r.out.result = WERR_NO_SUCH_DOMAIN;
3200                 goto finished;
3201         }
3202
3203         if (state->r.out.info == NULL || state->r.out.info[0] == NULL) {
3204                 DBG_ERR("DC location via winbind returned no results\n");
3205                 state->r.out.result = WERR_GEN_FAILURE;
3206                 goto finished;
3207         }
3208
3209         if (state->r.out.info[0]->dc_unc == NULL) {
3210                 DBG_ERR("DC location via winbind returned no DC unc\n");
3211                 state->r.out.result = WERR_GEN_FAILURE;
3212                 goto finished;
3213         }
3214
3215         /*
3216          * Either the supplied site name is NULL (possibly via
3217          * TRY_NEXT_CLOSEST_SITE) or the resulting site name matches
3218          * the input match name.
3219          *
3220          * TODO: Currently this means that requests with NETBIOS domain
3221          * names can fail because they do not return the site name.
3222          */
3223         if (state->r.in.site_name == NULL ||
3224             strcasecmp_m("", state->r.in.site_name) == 0 ||
3225             (state->r.out.info[0]->dc_site_name != NULL &&
3226              strcasecmp_m(state->r.out.info[0]->dc_site_name,
3227                           state->r.in.site_name) == 0)) {
3228
3229                 state->r.out.info[0]->client_site_name =
3230                         talloc_move(state->mem_ctx, &state->client_site);
3231
3232                 /*
3233                  * Make sure to return our DC UNC with // prefix.
3234                  * Winbind currently doesn't send the leading slashes
3235                  * for some reason.
3236                  */
3237                 if (strlen(state->r.out.info[0]->dc_unc) > 2 &&
3238                     strncmp("\\\\", state->r.out.info[0]->dc_unc, 2) != 0) {
3239                         const char *dc_unc = NULL;
3240
3241                         dc_unc = talloc_asprintf(state->mem_ctx,
3242                                                  "\\\\%s",
3243                                                  state->r.out.info[0]->dc_unc);
3244                         state->r.out.info[0]->dc_unc = dc_unc;
3245                 }
3246
3247                 state->r.out.result = WERR_OK;
3248         } else {
3249                 state->r.out.info = NULL;
3250                 state->r.out.result = WERR_NO_SUCH_DOMAIN;
3251         }
3252
3253 finished:
3254         if (state->_r.dcex2 != NULL) {
3255                 struct netr_DsRGetDCNameEx2 *r = state->_r.dcex2;
3256                 r->out.result = state->r.out.result;
3257         } else if (state->_r.dcex != NULL) {
3258                 struct netr_DsRGetDCNameEx *r = state->_r.dcex;
3259                 r->out.result = state->r.out.result;
3260         } else if (state->_r.dc != NULL) {
3261                 struct netr_DsRGetDCName *r = state->_r.dc;
3262                 r->out.result = state->r.out.result;
3263         }
3264
3265         TALLOC_FREE(state);
3266         status = dcesrv_reply(dce_call);
3267         if (!NT_STATUS_IS_OK(status)) {
3268                 DEBUG(0,(__location__ ": dcesrv_reply() failed - %s\n",
3269                          nt_errstr(status)));
3270         }
3271 }
3272
3273 /*
3274   netr_DsRGetDCNameEx2
3275 */
3276 static WERROR dcesrv_netr_DsRGetDCNameEx2(struct dcesrv_call_state *dce_call,
3277                                           TALLOC_CTX *mem_ctx,
3278                                           struct netr_DsRGetDCNameEx2 *r)
3279 {
3280         struct dcesrv_netr_DsRGetDCName_base_state *state;
3281
3282         state = talloc_zero(mem_ctx, struct dcesrv_netr_DsRGetDCName_base_state);
3283         if (state == NULL) {
3284                 return WERR_NOT_ENOUGH_MEMORY;
3285         }
3286
3287         state->dce_call = dce_call;
3288         state->mem_ctx = mem_ctx;
3289
3290         state->r = *r;
3291         state->_r.dcex2 = r;
3292
3293         return dcesrv_netr_DsRGetDCName_base_call(state);
3294 }
3295
3296 /*
3297   netr_DsRGetDCNameEx
3298 */
3299 static WERROR dcesrv_netr_DsRGetDCNameEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3300                                   struct netr_DsRGetDCNameEx *r)
3301 {
3302         struct dcesrv_netr_DsRGetDCName_base_state *state;
3303
3304         state = talloc_zero(mem_ctx, struct dcesrv_netr_DsRGetDCName_base_state);
3305         if (state == NULL) {
3306                 return WERR_NOT_ENOUGH_MEMORY;
3307         }
3308
3309         state->dce_call = dce_call;
3310         state->mem_ctx = mem_ctx;
3311
3312         state->r.in.server_unc = r->in.server_unc;
3313         state->r.in.client_account = NULL;
3314         state->r.in.mask = 0;
3315         state->r.in.domain_guid = r->in.domain_guid;
3316         state->r.in.domain_name = r->in.domain_name;
3317         state->r.in.site_name = r->in.site_name;
3318         state->r.in.flags = r->in.flags;
3319         state->r.out.info = r->out.info;
3320
3321         state->_r.dcex = r;
3322
3323         return dcesrv_netr_DsRGetDCName_base_call(state);
3324 }
3325
3326 /*
3327  * netr_DsRGetDCName
3328  *
3329  * This function is a predecessor to DsrGetDcNameEx2 according to [MS-NRPC].
3330  * Although it has a site-guid parameter, the documentation 3.5.4.3.3 DsrGetDcName
3331  * insists that it be ignored.
3332  */
3333 static WERROR dcesrv_netr_DsRGetDCName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3334                                        struct netr_DsRGetDCName *r)
3335 {
3336         struct dcesrv_netr_DsRGetDCName_base_state *state;
3337
3338         state = talloc_zero(mem_ctx, struct dcesrv_netr_DsRGetDCName_base_state);
3339         if (state == NULL) {
3340                 return WERR_NOT_ENOUGH_MEMORY;
3341         }
3342
3343         state->dce_call = dce_call;
3344         state->mem_ctx = mem_ctx;
3345
3346         state->r.in.server_unc = r->in.server_unc;
3347         state->r.in.client_account = NULL;
3348         state->r.in.mask = 0;
3349         state->r.in.domain_name = r->in.domain_name;
3350         state->r.in.domain_guid = r->in.domain_guid;
3351
3352         state->r.in.site_name = NULL; /* this is correct, we should ignore site GUID */
3353         state->r.in.flags = r->in.flags;
3354         state->r.out.info = r->out.info;
3355
3356         state->_r.dc = r;
3357
3358         return dcesrv_netr_DsRGetDCName_base_call(state);
3359 }
3360 /*
3361   netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN
3362 */
3363 static WERROR dcesrv_netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3364                        struct netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN *r)
3365 {
3366         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3367 }
3368
3369
3370 /*
3371   netr_NetrEnumerateTrustedDomainsEx
3372 */
3373 static WERROR dcesrv_netr_NetrEnumerateTrustedDomainsEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3374                        struct netr_NetrEnumerateTrustedDomainsEx *r)
3375 {
3376         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3377 }
3378
3379
3380 /*
3381   netr_DsRAddressToSitenamesExW
3382 */
3383 static WERROR dcesrv_netr_DsRAddressToSitenamesExW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3384                                                    struct netr_DsRAddressToSitenamesExW *r)
3385 {
3386         struct ldb_context *sam_ctx;
3387         struct netr_DsRAddressToSitenamesExWCtr *ctr;
3388         struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
3389         sa_family_t sin_family;
3390         struct sockaddr_in *addr;
3391 #ifdef HAVE_IPV6
3392         struct sockaddr_in6 *addr6;
3393         char addr_str[INET6_ADDRSTRLEN];
3394 #else
3395         char addr_str[INET_ADDRSTRLEN];
3396 #endif
3397         char *subnet_name;
3398         const char *res;
3399         uint32_t i;
3400
3401         sam_ctx = samdb_connect(mem_ctx,
3402                                 dce_call->event_ctx,
3403                                 lp_ctx,
3404                                 dce_call->conn->auth_state.session_info,
3405                                 dce_call->conn->remote_address,
3406                                 0);
3407         if (sam_ctx == NULL) {
3408                 return WERR_DS_UNAVAILABLE;
3409         }
3410
3411         ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesExWCtr);
3412         W_ERROR_HAVE_NO_MEMORY(ctr);
3413
3414         *r->out.ctr = ctr;
3415
3416         ctr->count = r->in.count;
3417         ctr->sitename = talloc_array(ctr, struct lsa_String, ctr->count);
3418         W_ERROR_HAVE_NO_MEMORY(ctr->sitename);
3419         ctr->subnetname = talloc_array(ctr, struct lsa_String, ctr->count);
3420         W_ERROR_HAVE_NO_MEMORY(ctr->subnetname);
3421
3422         for (i=0; i<ctr->count; i++) {
3423                 ctr->sitename[i].string = NULL;
3424                 ctr->subnetname[i].string = NULL;
3425
3426                 if (r->in.addresses[i].size < sizeof(sa_family_t)) {
3427                         continue;
3428                 }
3429                 /* The first two byte of the buffer are reserved for the
3430                  * "sin_family" but for now only the first one is used. */
3431                 sin_family = r->in.addresses[i].buffer[0];
3432
3433                 switch (sin_family) {
3434                 case AF_INET:
3435                         if (r->in.addresses[i].size < sizeof(struct sockaddr_in)) {
3436                                 continue;
3437                         }
3438                         addr = (struct sockaddr_in *) r->in.addresses[i].buffer;
3439                         res = inet_ntop(AF_INET, &addr->sin_addr,
3440                                         addr_str, sizeof(addr_str));
3441                         break;
3442 #ifdef HAVE_IPV6
3443                 case AF_INET6:
3444                         if (r->in.addresses[i].size < sizeof(struct sockaddr_in6)) {
3445                                 continue;
3446                         }
3447                         addr6 = (struct sockaddr_in6 *) r->in.addresses[i].buffer;
3448                         res = inet_ntop(AF_INET6, &addr6->sin6_addr,
3449                                         addr_str, sizeof(addr_str));
3450                         break;
3451 #endif
3452                 default:
3453                         continue;
3454                 }
3455
3456                 if (res == NULL) {
3457                         continue;
3458                 }
3459
3460                 ctr->sitename[i].string   = samdb_client_site_name(sam_ctx,
3461                                                                    mem_ctx,
3462                                                                    addr_str,
3463                                                                    &subnet_name,
3464                                                                    true);
3465                 W_ERROR_HAVE_NO_MEMORY(ctr->sitename[i].string);
3466                 ctr->subnetname[i].string = subnet_name;
3467         }
3468
3469         return WERR_OK;
3470 }
3471
3472
3473 /*
3474   netr_DsRAddressToSitenamesW
3475 */
3476 static WERROR dcesrv_netr_DsRAddressToSitenamesW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3477                        struct netr_DsRAddressToSitenamesW *r)
3478 {
3479         struct netr_DsRAddressToSitenamesExW r2;
3480         struct netr_DsRAddressToSitenamesWCtr *ctr;
3481         uint32_t i;
3482         WERROR werr;
3483
3484         ZERO_STRUCT(r2);
3485
3486         r2.in.server_name = r->in.server_name;
3487         r2.in.count = r->in.count;
3488         r2.in.addresses = r->in.addresses;
3489
3490         r2.out.ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesExWCtr *);
3491         W_ERROR_HAVE_NO_MEMORY(r2.out.ctr);
3492
3493         ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesWCtr);
3494         W_ERROR_HAVE_NO_MEMORY(ctr);
3495
3496         *r->out.ctr = ctr;
3497
3498         ctr->count = r->in.count;
3499         ctr->sitename = talloc_array(ctr, struct lsa_String, ctr->count);
3500         W_ERROR_HAVE_NO_MEMORY(ctr->sitename);
3501
3502         werr = dcesrv_netr_DsRAddressToSitenamesExW(dce_call, mem_ctx, &r2);
3503
3504         for (i=0; i<ctr->count; i++) {
3505                 ctr->sitename[i].string   = (*r2.out.ctr)->sitename[i].string;
3506         }
3507
3508         return werr;
3509 }
3510
3511
3512 /*
3513   netr_DsrGetDcSiteCoverageW
3514 */
3515 static WERROR dcesrv_netr_DsrGetDcSiteCoverageW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3516                        struct netr_DsrGetDcSiteCoverageW *r)
3517 {
3518         struct ldb_context *sam_ctx;
3519         struct DcSitesCtr *ctr;
3520         struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
3521
3522         sam_ctx = samdb_connect(mem_ctx,
3523                                 dce_call->event_ctx,
3524                                 lp_ctx,
3525                                 dce_call->conn->auth_state.session_info,
3526                                 dce_call->conn->remote_address,
3527                                 0);
3528         if (sam_ctx == NULL) {
3529                 return WERR_DS_UNAVAILABLE;
3530         }
3531
3532         ctr = talloc(mem_ctx, struct DcSitesCtr);
3533         W_ERROR_HAVE_NO_MEMORY(ctr);
3534
3535         *r->out.ctr = ctr;
3536
3537         /* For now only return our default site */
3538         ctr->num_sites = 1;
3539         ctr->sites = talloc_array(ctr, struct lsa_String, ctr->num_sites);
3540         W_ERROR_HAVE_NO_MEMORY(ctr->sites);
3541         ctr->sites[0].string = samdb_server_site_name(sam_ctx, mem_ctx);
3542         W_ERROR_HAVE_NO_MEMORY(ctr->sites[0].string);
3543
3544         return WERR_OK;
3545 }
3546
3547
3548 static WERROR fill_trusted_domains_array(TALLOC_CTX *mem_ctx,
3549                                          struct ldb_context *sam_ctx,
3550                                          struct netr_DomainTrustList *trusts,
3551                                          uint32_t trust_flags)
3552 {
3553         struct ldb_dn *system_dn;
3554         struct ldb_message **dom_res = NULL;
3555         const char *trust_attrs[] = { "flatname", "trustPartner",
3556                                       "securityIdentifier", "trustDirection",
3557                                       "trustType", "trustAttributes", NULL };
3558         uint32_t n;
3559         int i;
3560         int ret;
3561
3562         if (!(trust_flags & (NETR_TRUST_FLAG_INBOUND |
3563                              NETR_TRUST_FLAG_OUTBOUND))) {
3564                 return WERR_INVALID_FLAGS;
3565         }
3566
3567         system_dn = samdb_search_dn(sam_ctx, mem_ctx,
3568                                     ldb_get_default_basedn(sam_ctx),
3569                                     "(&(objectClass=container)(cn=System))");
3570         if (!system_dn) {
3571                 return WERR_GEN_FAILURE;
3572         }
3573
3574         ret = gendb_search(sam_ctx, mem_ctx, system_dn,
3575                            &dom_res, trust_attrs,
3576                            "(objectclass=trustedDomain)");
3577
3578         for (i = 0; i < ret; i++) {
3579                 unsigned int trust_dir;
3580                 uint32_t flags = 0;
3581
3582                 trust_dir = ldb_msg_find_attr_as_uint(dom_res[i],
3583                                                       "trustDirection", 0);
3584
3585                 if (trust_dir & LSA_TRUST_DIRECTION_INBOUND) {
3586                         flags |= NETR_TRUST_FLAG_INBOUND;
3587                 }
3588                 if (trust_dir & LSA_TRUST_DIRECTION_OUTBOUND) {
3589                         flags |= NETR_TRUST_FLAG_OUTBOUND;
3590                 }
3591
3592                 if (!(flags & trust_flags)) {
3593                         /* this trust direction was not requested */
3594                         continue;
3595                 }
3596
3597                 n = trusts->count;
3598                 trusts->array = talloc_realloc(trusts, trusts->array,
3599                                                struct netr_DomainTrust,
3600                                                n + 1);
3601                 W_ERROR_HAVE_NO_MEMORY(trusts->array);
3602
3603                 trusts->array[n].netbios_name = talloc_steal(trusts->array, ldb_msg_find_attr_as_string(dom_res[i], "flatname", NULL));
3604                 if (!trusts->array[n].netbios_name) {
3605                         DEBUG(0, ("DB Error, TrustedDomain entry (%s) "
3606                                   "without flatname\n", 
3607                                   ldb_dn_get_linearized(dom_res[i]->dn)));
3608                 }
3609
3610                 trusts->array[n].dns_name = talloc_steal(trusts->array, ldb_msg_find_attr_as_string(dom_res[i], "trustPartner", NULL));
3611
3612                 trusts->array[n].trust_flags = flags;
3613                 if ((trust_flags & NETR_TRUST_FLAG_IN_FOREST) &&
3614                     !(flags & NETR_TRUST_FLAG_TREEROOT)) {
3615                         /* TODO: find if we have parent in the list */
3616                         trusts->array[n].parent_index = 0;
3617                 }
3618
3619                 trusts->array[n].trust_type =
3620                                 ldb_msg_find_attr_as_uint(dom_res[i],
3621                                                   "trustType", 0);
3622                 trusts->array[n].trust_attributes =
3623                                 ldb_msg_find_attr_as_uint(dom_res[i],
3624                                                   "trustAttributes", 0);
3625
3626                 if ((trusts->array[n].trust_type == LSA_TRUST_TYPE_MIT) ||
3627                     (trusts->array[n].trust_type == LSA_TRUST_TYPE_DCE)) {
3628                         struct dom_sid zero_sid;
3629                         ZERO_STRUCT(zero_sid);
3630                         trusts->array[n].sid =
3631                                 dom_sid_dup(trusts, &zero_sid);
3632                 } else {
3633                         trusts->array[n].sid =
3634                                 samdb_result_dom_sid(trusts, dom_res[i],
3635                                                      "securityIdentifier");
3636                 }
3637                 trusts->array[n].guid = GUID_zero();
3638
3639                 trusts->count = n + 1;
3640         }
3641
3642         talloc_free(dom_res);
3643         return WERR_OK;
3644 }
3645
3646 /*
3647   netr_DsrEnumerateDomainTrusts
3648 */
3649 static WERROR dcesrv_netr_DsrEnumerateDomainTrusts(struct dcesrv_call_state *dce_call,
3650                                                    TALLOC_CTX *mem_ctx,
3651                                                    struct netr_DsrEnumerateDomainTrusts *r)
3652 {
3653         struct netr_DomainTrustList *trusts;
3654         struct ldb_context *sam_ctx;
3655         int ret;
3656         struct ldb_message **dom_res;
3657         const char * const dom_attrs[] = { "objectSid", "objectGUID", NULL };
3658         struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
3659         const char *dnsdomain = lpcfg_dnsdomain(lp_ctx);
3660         const char *p;
3661         WERROR werr;
3662
3663         if (r->in.trust_flags & 0xFFFFFE00) {
3664                 return WERR_INVALID_FLAGS;
3665         }
3666
3667         /* TODO: turn to hard check once we are sure this is 100% correct */
3668         if (!r->in.server_name) {
3669                 DEBUG(3, ("Invalid domain! Expected name in domain [%s]. "
3670                           "But received NULL!\n", dnsdomain));
3671         } else {
3672                 p = strchr(r->in.server_name, '.');
3673                 if (!p) {
3674                         DEBUG(3, ("Invalid domain! Expected name in domain "
3675                                   "[%s]. But received [%s]!\n",
3676                                   dnsdomain, r->in.server_name));
3677                         p = r->in.server_name;
3678                 } else {
3679                         p++;
3680                 }
3681                 if (strcasecmp(p, dnsdomain)) {
3682                         DEBUG(3, ("Invalid domain! Expected name in domain "
3683                                   "[%s]. But received [%s]!\n",
3684                                   dnsdomain, r->in.server_name));
3685                 }
3686         }
3687
3688         trusts = talloc_zero(mem_ctx, struct netr_DomainTrustList);
3689         W_ERROR_HAVE_NO_MEMORY(trusts);
3690
3691         trusts->count = 0;
3692         r->out.trusts = trusts;
3693
3694         sam_ctx = samdb_connect(mem_ctx,
3695                                 dce_call->event_ctx,
3696                                 lp_ctx,
3697                                 dce_call->conn->auth_state.session_info,
3698                                 dce_call->conn->remote_address,
3699                                 0);
3700         if (sam_ctx == NULL) {
3701                 return WERR_GEN_FAILURE;
3702         }
3703
3704         if ((r->in.trust_flags & NETR_TRUST_FLAG_INBOUND) ||
3705             (r->in.trust_flags & NETR_TRUST_FLAG_OUTBOUND)) {
3706
3707                 werr = fill_trusted_domains_array(mem_ctx, sam_ctx,
3708                                                   trusts, r->in.trust_flags);
3709                 W_ERROR_NOT_OK_RETURN(werr);
3710         }
3711
3712         /* NOTE: we currently are always the root of the forest */
3713         if (r->in.trust_flags & NETR_TRUST_FLAG_IN_FOREST) {
3714                 uint32_t n = trusts->count;
3715
3716                 ret = gendb_search_dn(sam_ctx, mem_ctx, NULL,
3717                                       &dom_res, dom_attrs);
3718                 if (ret != 1) {
3719                         return WERR_GEN_FAILURE;
3720                 }
3721
3722                 trusts->count = n + 1;
3723                 trusts->array = talloc_realloc(trusts, trusts->array,
3724                                                struct netr_DomainTrust,
3725                                                trusts->count);
3726                 W_ERROR_HAVE_NO_MEMORY(trusts->array);
3727
3728                 trusts->array[n].netbios_name = lpcfg_workgroup(lp_ctx);
3729                 trusts->array[n].dns_name = lpcfg_dnsdomain(lp_ctx);
3730                 trusts->array[n].trust_flags =
3731                         NETR_TRUST_FLAG_NATIVE |
3732                         NETR_TRUST_FLAG_TREEROOT |
3733                         NETR_TRUST_FLAG_IN_FOREST |
3734                         NETR_TRUST_FLAG_PRIMARY;
3735                 /* we are always the root domain for now */
3736                 trusts->array[n].parent_index = 0;
3737                 trusts->array[n].trust_type = LSA_TRUST_TYPE_UPLEVEL;
3738                 trusts->array[n].trust_attributes = 0;
3739                 trusts->array[n].sid = samdb_result_dom_sid(mem_ctx,
3740                                                             dom_res[0],
3741                                                             "objectSid");
3742                 trusts->array[n].guid = samdb_result_guid(dom_res[0],
3743                                                           "objectGUID");
3744                 talloc_free(dom_res);
3745         }
3746
3747         return WERR_OK;
3748 }
3749
3750
3751 /*
3752   netr_DsrDeregisterDNSHostRecords
3753 */
3754 static WERROR dcesrv_netr_DsrDeregisterDNSHostRecords(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3755                        struct netr_DsrDeregisterDNSHostRecords *r)
3756 {
3757         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3758 }
3759
3760
3761 static NTSTATUS dcesrv_netr_ServerGetTrustInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3762                        struct netr_ServerGetTrustInfo *r);
3763
3764 /*
3765   netr_ServerTrustPasswordsGet
3766 */
3767 static NTSTATUS dcesrv_netr_ServerTrustPasswordsGet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3768                        struct netr_ServerTrustPasswordsGet *r)
3769 {
3770         struct netr_ServerGetTrustInfo r2 = {};
3771         struct netr_TrustInfo *_ti = NULL;
3772         NTSTATUS status;
3773
3774         r2.in.server_name = r->in.server_name;
3775         r2.in.account_name = r->in.account_name;
3776         r2.in.secure_channel_type = r->in.secure_channel_type;
3777         r2.in.computer_name = r->in.computer_name;
3778         r2.in.credential = r->in.credential;
3779
3780         r2.out.return_authenticator = r->out.return_authenticator;
3781         r2.out.new_owf_password = r->out.new_owf_password;
3782         r2.out.old_owf_password = r->out.old_owf_password;
3783         r2.out.trust_info = &_ti;
3784
3785         status = dcesrv_netr_ServerGetTrustInfo(dce_call, mem_ctx, &r2);
3786
3787         r->out.return_authenticator = r2.out.return_authenticator;
3788         r->out.new_owf_password = r2.out.new_owf_password;
3789         r->out.old_owf_password = r2.out.old_owf_password;
3790
3791         return status;
3792 }
3793
3794 /*
3795   netr_DsRGetForestTrustInformation
3796 */
3797 struct dcesrv_netr_DsRGetForestTrustInformation_state {
3798         struct dcesrv_call_state *dce_call;
3799         TALLOC_CTX *mem_ctx;
3800         struct netr_DsRGetForestTrustInformation *r;
3801 };
3802
3803 static void dcesrv_netr_DsRGetForestTrustInformation_done(struct tevent_req *subreq);
3804
3805 static WERROR dcesrv_netr_DsRGetForestTrustInformation(struct dcesrv_call_state *dce_call,
3806                                                        TALLOC_CTX *mem_ctx,
3807                                                        struct netr_DsRGetForestTrustInformation *r)
3808 {
3809         struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
3810         struct dcesrv_connection *conn = dce_call->conn;
3811         struct auth_session_info *session_info = conn->auth_state.session_info;
3812         enum security_user_level security_level;
3813         struct ldb_context *sam_ctx = NULL;
3814         struct dcesrv_netr_DsRGetForestTrustInformation_state *state = NULL;
3815         struct dcerpc_binding_handle *irpc_handle = NULL;
3816         struct tevent_req *subreq = NULL;
3817         struct ldb_dn *domain_dn = NULL;
3818         struct ldb_dn *forest_dn = NULL;
3819         int cmp;
3820         int forest_level;
3821
3822         security_level = security_session_user_level(session_info, NULL);
3823         if (security_level < SECURITY_USER) {
3824                 return WERR_ACCESS_DENIED;
3825         }
3826
3827         if (r->in.flags & 0xFFFFFFFE) {
3828                 return WERR_INVALID_FLAGS;
3829         }
3830
3831         sam_ctx = samdb_connect(mem_ctx,
3832                                 dce_call->event_ctx,
3833                                 lp_ctx,
3834                                 dce_call->conn->auth_state.session_info,
3835                                 dce_call->conn->remote_address,
3836                                 0);
3837         if (sam_ctx == NULL) {
3838                 return WERR_GEN_FAILURE;
3839         }
3840
3841         domain_dn = ldb_get_default_basedn(sam_ctx);
3842         if (domain_dn == NULL) {
3843                 return WERR_GEN_FAILURE;
3844         }
3845
3846         forest_dn = ldb_get_root_basedn(sam_ctx);
3847         if (forest_dn == NULL) {
3848                 return WERR_GEN_FAILURE;
3849         }
3850
3851         cmp = ldb_dn_compare(domain_dn, forest_dn);
3852         if (cmp != 0) {
3853                 return WERR_NERR_ACFNOTLOADED;
3854         }
3855
3856         forest_level = dsdb_forest_functional_level(sam_ctx);
3857         if (forest_level < DS_DOMAIN_FUNCTION_2003) {
3858                 return WERR_INVALID_FUNCTION;
3859         }
3860
3861         if (r->in.flags & DS_GFTI_UPDATE_TDO) {
3862                 if (!samdb_is_pdc(sam_ctx)) {
3863                         return WERR_NERR_NOTPRIMARY;
3864                 }
3865
3866                 if (r->in.trusted_domain_name == NULL) {
3867                         return WERR_INVALID_FLAGS;
3868                 }
3869         }
3870
3871         if (r->in.trusted_domain_name == NULL) {
3872                 NTSTATUS status;
3873
3874                 /*
3875                  * information about our own domain
3876                  */
3877                 status = dsdb_trust_xref_forest_info(mem_ctx, sam_ctx,
3878                                                 r->out.forest_trust_info);
3879                 if (!NT_STATUS_IS_OK(status)) {
3880                         return ntstatus_to_werror(status);
3881                 }
3882
3883                 return WERR_OK;
3884         }
3885
3886         /*
3887          * Forward the request to winbindd
3888          */
3889
3890         state = talloc_zero(mem_ctx,
3891                         struct dcesrv_netr_DsRGetForestTrustInformation_state);
3892         if (state == NULL) {
3893                 return WERR_NOT_ENOUGH_MEMORY;
3894         }
3895         state->dce_call = dce_call;
3896         state->mem_ctx = mem_ctx;
3897         state->r = r;
3898
3899         irpc_handle = irpc_binding_handle_by_name(state,
3900                                                   state->dce_call->msg_ctx,
3901                                                   "winbind_server",
3902                                                   &ndr_table_winbind);
3903         if (irpc_handle == NULL) {
3904                 DEBUG(0,("Failed to get binding_handle for winbind_server task\n"));
3905                 state->dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
3906                 return WERR_SERVICE_NOT_FOUND;
3907         }
3908
3909         /*
3910          * 60 seconds timeout should be enough
3911          */
3912         dcerpc_binding_handle_set_timeout(irpc_handle, 60);
3913
3914         subreq = dcerpc_winbind_GetForestTrustInformation_send(state,
3915                                                 state->dce_call->event_ctx,
3916                                                 irpc_handle,
3917                                                 r->in.trusted_domain_name,
3918                                                 r->in.flags,
3919                                                 r->out.forest_trust_info);
3920         if (subreq == NULL) {
3921                 return WERR_NOT_ENOUGH_MEMORY;
3922         }
3923         state->dce_call->state_flags |= DCESRV_CALL_STATE_FLAG_ASYNC;
3924         tevent_req_set_callback(subreq,
3925                                 dcesrv_netr_DsRGetForestTrustInformation_done,
3926                                 state);
3927
3928         return WERR_OK;
3929 }
3930
3931 static void dcesrv_netr_DsRGetForestTrustInformation_done(struct tevent_req *subreq)
3932 {
3933         struct dcesrv_netr_DsRGetForestTrustInformation_state *state =
3934                 tevent_req_callback_data(subreq,
3935                 struct dcesrv_netr_DsRGetForestTrustInformation_state);
3936         NTSTATUS status;
3937
3938         status = dcerpc_winbind_GetForestTrustInformation_recv(subreq,
3939                                                         state->mem_ctx,
3940                                                         &state->r->out.result);
3941         TALLOC_FREE(subreq);
3942         if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) {
3943                 state->r->out.result = WERR_TIMEOUT;
3944         } else if (!NT_STATUS_IS_OK(status)) {
3945                 state->dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
3946                 DEBUG(0,(__location__ ": IRPC callback failed %s\n",
3947                          nt_errstr(status)));
3948         }
3949
3950         status = dcesrv_reply(state->dce_call);
3951         if (!NT_STATUS_IS_OK(status)) {
3952                 DEBUG(0,(__location__ ": dcesrv_reply() failed - %s\n", nt_errstr(status)));
3953         }
3954 }
3955
3956 /*
3957   netr_GetForestTrustInformation
3958 */
3959 static NTSTATUS dcesrv_netr_GetForestTrustInformation(struct dcesrv_call_state *dce_call,
3960                                                       TALLOC_CTX *mem_ctx,
3961                                                       struct netr_GetForestTrustInformation *r)
3962 {
3963         struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
3964         struct netlogon_creds_CredentialState *creds = NULL;
3965         struct ldb_context *sam_ctx = NULL;
3966         struct ldb_dn *domain_dn = NULL;
3967         struct ldb_dn *forest_dn = NULL;
3968         int cmp;
3969         int forest_level;
3970         NTSTATUS status;
3971
3972         status = dcesrv_netr_creds_server_step_check(dce_call,
3973                                                      mem_ctx,
3974                                                      r->in.computer_name,
3975                                                      r->in.credential,
3976                                                      r->out.return_authenticator,
3977                                                      &creds);
3978         if (!NT_STATUS_IS_OK(status)) {
3979                 return status;
3980         }
3981
3982         if ((creds->secure_channel_type != SEC_CHAN_DNS_DOMAIN) &&
3983             (creds->secure_channel_type != SEC_CHAN_DOMAIN)) {
3984                 return NT_STATUS_NOT_IMPLEMENTED;
3985         }
3986
3987         sam_ctx = samdb_connect(mem_ctx,
3988                                 dce_call->event_ctx,
3989                                 lp_ctx,
3990                                 dce_call->conn->auth_state.session_info,
3991                                 dce_call->conn->remote_address,
3992                                 0);
3993         if (sam_ctx == NULL) {
3994                 return NT_STATUS_INTERNAL_ERROR;
3995         }
3996
3997         /* TODO: check r->in.server_name is our name */
3998
3999         domain_dn = ldb_get_default_basedn(sam_ctx);
4000         if (domain_dn == NULL) {
4001                 return NT_STATUS_INTERNAL_ERROR;
4002         }
4003
4004         forest_dn = ldb_get_root_basedn(sam_ctx);
4005         if (forest_dn == NULL) {
4006                 return NT_STATUS_INTERNAL_ERROR;
4007         }
4008
4009         cmp = ldb_dn_compare(domain_dn, forest_dn);
4010         if (cmp != 0) {
4011                 return NT_STATUS_INVALID_DOMAIN_STATE;
4012         }
4013
4014         forest_level = dsdb_forest_functional_level(sam_ctx);
4015         if (forest_level < DS_DOMAIN_FUNCTION_2003) {
4016                 return NT_STATUS_INVALID_DOMAIN_STATE;
4017         }
4018
4019         status = dsdb_trust_xref_forest_info(mem_ctx, sam_ctx,
4020                                              r->out.forest_trust_info);
4021         if (!NT_STATUS_IS_OK(status)) {
4022                 return status;
4023         }
4024
4025         return NT_STATUS_OK;
4026 }
4027
4028
4029 /*
4030   netr_ServerGetTrustInfo
4031 */
4032 static NTSTATUS dcesrv_netr_ServerGetTrustInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4033                        struct netr_ServerGetTrustInfo *r)
4034 {
4035         struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
4036         struct netlogon_creds_CredentialState *creds = NULL;
4037         struct ldb_context *sam_ctx = NULL;
4038         const char * const attrs[] = {
4039                 "unicodePwd",
4040                 "sAMAccountName",
4041                 "userAccountControl",
4042                 NULL
4043         };
4044         struct ldb_message **res = NULL;
4045         struct samr_Password *curNtHash = NULL, *prevNtHash = NULL;
4046         NTSTATUS nt_status;
4047         int ret;
4048         const char *asid = NULL;
4049         uint32_t uac = 0;
4050         const char *aname = NULL;
4051         struct ldb_message *tdo_msg = NULL;
4052         const char * const tdo_attrs[] = {
4053                 "trustAuthIncoming",
4054                 "trustAttributes",
4055                 NULL
4056         };
4057         struct netr_TrustInfo *trust_info = NULL;
4058
4059         ZERO_STRUCTP(r->out.new_owf_password);
4060         ZERO_STRUCTP(r->out.old_owf_password);
4061
4062         nt_status = dcesrv_netr_creds_server_step_check(dce_call,
4063                                                         mem_ctx,
4064                                                         r->in.computer_name,
4065                                                         r->in.credential,
4066                                                         r->out.return_authenticator,
4067                                                         &creds);
4068         if (!NT_STATUS_IS_OK(nt_status)) {
4069                 return nt_status;
4070         }
4071
4072         /* TODO: check r->in.server_name is our name */
4073
4074         if (strcasecmp_m(r->in.account_name, creds->account_name) != 0) {
4075                 return NT_STATUS_INVALID_PARAMETER;
4076         }
4077
4078         if (r->in.secure_channel_type != creds->secure_channel_type) {
4079                 return NT_STATUS_INVALID_PARAMETER;
4080         }
4081
4082         if (strcasecmp_m(r->in.computer_name, creds->computer_name) != 0) {
4083                 return NT_STATUS_INVALID_PARAMETER;
4084         }
4085
4086         sam_ctx = samdb_connect(mem_ctx,
4087                                 dce_call->event_ctx,
4088                                 lp_ctx,
4089                                 system_session(lp_ctx),
4090                                 dce_call->conn->remote_address,
4091                                 0);
4092         if (sam_ctx == NULL) {
4093                 return NT_STATUS_INVALID_SYSTEM_SERVICE;
4094         }
4095
4096         asid = ldap_encode_ndr_dom_sid(mem_ctx, creds->sid);
4097         if (asid == NULL) {
4098                 return NT_STATUS_NO_MEMORY;
4099         }
4100
4101         ret = gendb_search(sam_ctx, mem_ctx, NULL, &res, attrs,
4102                            "(&(objectClass=user)(objectSid=%s))",
4103                            asid);
4104         if (ret != 1) {
4105                 return NT_STATUS_ACCOUNT_DISABLED;
4106         }
4107
4108         switch (creds->secure_channel_type) {
4109         case SEC_CHAN_DNS_DOMAIN:
4110         case SEC_CHAN_DOMAIN:
4111                 uac = ldb_msg_find_attr_as_uint(res[0], "userAccountControl", 0);
4112
4113                 if (uac & UF_ACCOUNTDISABLE) {
4114                         return NT_STATUS_ACCOUNT_DISABLED;
4115                 }
4116
4117                 if (!(uac & UF_INTERDOMAIN_TRUST_ACCOUNT)) {
4118                         return NT_STATUS_ACCOUNT_DISABLED;
4119                 }
4120
4121                 aname = ldb_msg_find_attr_as_string(res[0], "sAMAccountName", NULL);
4122                 if (aname == NULL) {
4123                         return NT_STATUS_ACCOUNT_DISABLED;
4124                 }
4125
4126                 nt_status = dsdb_trust_search_tdo_by_type(sam_ctx,
4127                                                 SEC_CHAN_DOMAIN, aname,
4128                                                 tdo_attrs, mem_ctx, &tdo_msg);
4129                 if (NT_STATUS_EQUAL(nt_status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
4130                         return NT_STATUS_ACCOUNT_DISABLED;
4131                 }
4132                 if (!NT_STATUS_IS_OK(nt_status)) {
4133                         return nt_status;
4134                 }
4135
4136                 nt_status = dsdb_trust_get_incoming_passwords(tdo_msg, mem_ctx,
4137                                                               &curNtHash,
4138                                                               &prevNtHash);
4139                 if (!NT_STATUS_IS_OK(nt_status)) {
4140                         return nt_status;
4141                 }
4142
4143                 trust_info = talloc_zero(mem_ctx, struct netr_TrustInfo);
4144                 if (trust_info == NULL) {
4145                         return NT_STATUS_NO_MEMORY;
4146                 }
4147
4148                 trust_info->count = 1;
4149                 trust_info->data = talloc_array(trust_info, uint32_t,
4150                                                 trust_info->count);
4151                 if (trust_info->data == NULL) {
4152                         return NT_STATUS_NO_MEMORY;
4153                 }
4154
4155                 trust_info->data[0] = ldb_msg_find_attr_as_uint(tdo_msg,
4156                                                         "trustAttributes",
4157                                                         0);
4158                 break;
4159
4160         default:
4161                 nt_status = samdb_result_passwords_no_lockout(mem_ctx, lp_ctx,
4162                                                               res[0],
4163                                                               NULL, &curNtHash);
4164                 if (!NT_STATUS_IS_OK(nt_status)) {
4165                         return nt_status;
4166                 }
4167
4168                 prevNtHash = talloc(mem_ctx, struct samr_Password);
4169                 if (prevNtHash == NULL) {
4170                         return NT_STATUS_NO_MEMORY;
4171                 }
4172
4173                 E_md4hash("", prevNtHash->hash);
4174                 break;
4175         }
4176
4177         if (curNtHash != NULL) {
4178                 *r->out.new_owf_password = *curNtHash;
4179                 netlogon_creds_des_encrypt(creds, r->out.new_owf_password);
4180         }
4181         if (prevNtHash != NULL) {
4182                 *r->out.old_owf_password = *prevNtHash;
4183                 netlogon_creds_des_encrypt(creds, r->out.old_owf_password);
4184         }
4185
4186         if (trust_info != NULL) {
4187                 *r->out.trust_info = trust_info;
4188         }
4189
4190         return NT_STATUS_OK;
4191 }
4192
4193 /*
4194   netr_Unused47
4195 */
4196 static NTSTATUS dcesrv_netr_Unused47(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4197                                      struct netr_Unused47 *r)
4198 {
4199         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4200 }
4201
4202
4203 struct netr_dnsupdate_RODC_state {
4204         struct dcesrv_call_state *dce_call;
4205         struct netr_DsrUpdateReadOnlyServerDnsRecords *r;
4206         struct dnsupdate_RODC *r2;
4207 };
4208
4209 /*
4210   called when the forwarded RODC dns update request is finished
4211  */
4212 static void netr_dnsupdate_RODC_callback(struct tevent_req *subreq)
4213 {
4214         struct netr_dnsupdate_RODC_state *st =
4215                 tevent_req_callback_data(subreq,
4216                                          struct netr_dnsupdate_RODC_state);
4217         NTSTATUS status;
4218
4219         status = dcerpc_dnsupdate_RODC_r_recv(subreq, st->dce_call);
4220         TALLOC_FREE(subreq);
4221         if (!NT_STATUS_IS_OK(status)) {
4222                 DEBUG(0,(__location__ ": IRPC callback failed %s\n", nt_errstr(status)));
4223                 st->dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
4224         }
4225
4226         st->r->out.dns_names = talloc_steal(st->dce_call, st->r2->out.dns_names);
4227
4228         status = dcesrv_reply(st->dce_call);
4229         if (!NT_STATUS_IS_OK(status)) {
4230                 DEBUG(0,(__location__ ": dcesrv_reply() failed - %s\n", nt_errstr(status)));
4231         }
4232 }
4233
4234 /*
4235   netr_DsrUpdateReadOnlyServerDnsRecords
4236 */
4237 static NTSTATUS dcesrv_netr_DsrUpdateReadOnlyServerDnsRecords(struct dcesrv_call_state *dce_call,
4238                                                               TALLOC_CTX *mem_ctx,
4239                                                               struct netr_DsrUpdateReadOnlyServerDnsRecords *r)
4240 {
4241         struct netlogon_creds_CredentialState *creds;
4242         NTSTATUS nt_status;
4243         struct dcerpc_binding_handle *binding_handle;
4244         struct netr_dnsupdate_RODC_state *st;
4245         struct tevent_req *subreq;
4246
4247         nt_status = dcesrv_netr_creds_server_step_check(dce_call,
4248                                                         mem_ctx,
4249                                                         r->in.computer_name,
4250                                                         r->in.credential,
4251                                                         r->out.return_authenticator,
4252                                                         &creds);
4253         NT_STATUS_NOT_OK_RETURN(nt_status);
4254
4255         if (creds->secure_channel_type != SEC_CHAN_RODC) {
4256                 return NT_STATUS_ACCESS_DENIED;
4257         }
4258
4259         st = talloc_zero(mem_ctx, struct netr_dnsupdate_RODC_state);
4260         NT_STATUS_HAVE_NO_MEMORY(st);
4261
4262         st->dce_call = dce_call;
4263         st->r = r;
4264         st->r2 = talloc_zero(st, struct dnsupdate_RODC);
4265         NT_STATUS_HAVE_NO_MEMORY(st->r2);
4266
4267         st->r2->in.dom_sid = creds->sid;
4268         st->r2->in.site_name = r->in.site_name;
4269         st->r2->in.dns_ttl = r->in.dns_ttl;
4270         st->r2->in.dns_names = r->in.dns_names;
4271         st->r2->out.dns_names = r->out.dns_names;
4272
4273         binding_handle = irpc_binding_handle_by_name(st, dce_call->msg_ctx,
4274                                                      "dnsupdate", &ndr_table_irpc);
4275         if (binding_handle == NULL) {
4276                 DEBUG(0,("Failed to get binding_handle for dnsupdate task\n"));
4277                 dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
4278                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
4279         }
4280
4281         /* forward the call */
4282         subreq = dcerpc_dnsupdate_RODC_r_send(st, dce_call->event_ctx,
4283                                               binding_handle, st->r2);
4284         NT_STATUS_HAVE_NO_MEMORY(subreq);
4285
4286         dce_call->state_flags |= DCESRV_CALL_STATE_FLAG_ASYNC;
4287
4288         /* setup the callback */
4289         tevent_req_set_callback(subreq, netr_dnsupdate_RODC_callback, st);
4290
4291         return NT_STATUS_OK;
4292 }
4293
4294
4295 /* include the generated boilerplate */
4296 #include "librpc/gen_ndr/ndr_netlogon_s.c"