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