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