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