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