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