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