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