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