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