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