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