Line data Source code
1 : /* need access mask/acl implementation */
2 :
3 : /*
4 : Unix SMB/CIFS implementation.
5 :
6 : endpoint server for the lsarpc pipe
7 :
8 : Copyright (C) Andrew Tridgell 2004
9 : Copyright (C) Andrew Bartlett <abartlet@samba.org> 2004-2008
10 :
11 : This program is free software; you can redistribute it and/or modify
12 : it under the terms of the GNU General Public License as published by
13 : the Free Software Foundation; either version 3 of the License, or
14 : (at your option) any later version.
15 :
16 : This program is distributed in the hope that it will be useful,
17 : but WITHOUT ANY WARRANTY; without even the implied warranty of
18 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 : GNU General Public License for more details.
20 :
21 : You should have received a copy of the GNU General Public License
22 : along with this program. If not, see <http://www.gnu.org/licenses/>.
23 : */
24 :
25 : #include "rpc_server/lsa/lsa.h"
26 : #include "system/kerberos.h"
27 : #include "auth/kerberos/kerberos.h"
28 : #include "librpc/gen_ndr/ndr_drsblobs.h"
29 : #include "librpc/gen_ndr/ndr_lsa.h"
30 : #include "lib/util/tsort.h"
31 : #include "dsdb/common/util.h"
32 : #include "libcli/security/session.h"
33 : #include "libcli/lsarpc/util_lsarpc.h"
34 : #include "lib/messaging/irpc.h"
35 : #include "libds/common/roles.h"
36 : #include "lib/util/smb_strtox.h"
37 : #include "lib/param/loadparm.h"
38 : #include "librpc/rpc/dcerpc_helper.h"
39 :
40 : #include "lib/crypto/gnutls_helpers.h"
41 : #include <gnutls/gnutls.h>
42 : #include <gnutls/crypto.h>
43 :
44 : #undef strcasecmp
45 :
46 : #define DCESRV_INTERFACE_LSARPC_BIND(context, iface) \
47 : dcesrv_interface_lsarpc_bind(context, iface)
48 4047 : static NTSTATUS dcesrv_interface_lsarpc_bind(struct dcesrv_connection_context *context,
49 : const struct dcesrv_interface *iface)
50 : {
51 4047 : return dcesrv_interface_bind_reject_connect(context, iface);
52 : }
53 :
54 : static NTSTATUS lsarpc__op_init_server(struct dcesrv_context *dce_ctx,
55 : const struct dcesrv_endpoint_server *ep_server);
56 : static const struct dcesrv_interface dcesrv_lsarpc_interface;
57 :
58 : #define NCACN_NP_PIPE_NETLOGON "ncacn_np:[\\pipe\\netlogon]"
59 : #define NCACN_NP_PIPE_LSASS "ncacn_np:[\\pipe\\lsass]"
60 : #define DCESRV_INTERFACE_LSARPC_NCACN_NP_SECONDARY_ENDPOINT NCACN_NP_PIPE_LSASS
61 :
62 : #define DCESRV_INTERFACE_LSARPC_INIT_SERVER \
63 : dcesrv_interface_lsarpc_init_server
64 64 : static NTSTATUS dcesrv_interface_lsarpc_init_server(struct dcesrv_context *dce_ctx,
65 : const struct dcesrv_endpoint_server *ep_server)
66 : {
67 64 : if (lpcfg_lsa_over_netlogon(dce_ctx->lp_ctx)) {
68 9 : NTSTATUS ret = dcesrv_interface_register(dce_ctx,
69 : NCACN_NP_PIPE_NETLOGON,
70 : NCACN_NP_PIPE_LSASS,
71 : &dcesrv_lsarpc_interface, NULL);
72 9 : if (!NT_STATUS_IS_OK(ret)) {
73 0 : DEBUG(1,("lsarpc_op_init_server: failed to register endpoint '\\pipe\\netlogon'\n"));
74 0 : return ret;
75 : }
76 : }
77 64 : return lsarpc__op_init_server(dce_ctx, ep_server);
78 : }
79 :
80 : /*
81 : this type allows us to distinguish handle types
82 : */
83 :
84 : /*
85 : state associated with a lsa_OpenAccount() operation
86 : */
87 : struct lsa_account_state {
88 : struct lsa_policy_state *policy;
89 : uint32_t access_mask;
90 : struct dom_sid *account_sid;
91 : };
92 :
93 :
94 : /*
95 : state associated with a lsa_OpenSecret() operation
96 : */
97 : struct lsa_secret_state {
98 : struct lsa_policy_state *policy;
99 : uint32_t access_mask;
100 : struct ldb_dn *secret_dn;
101 : struct ldb_context *sam_ldb;
102 : bool global;
103 : };
104 :
105 : /*
106 : state associated with a lsa_OpenTrustedDomain() operation
107 : */
108 : struct lsa_trusted_domain_state {
109 : struct lsa_policy_state *policy;
110 : uint32_t access_mask;
111 : struct ldb_dn *trusted_domain_dn;
112 : struct ldb_dn *trusted_domain_user_dn;
113 : };
114 :
115 123 : static bool dcesrc_lsa_valid_AccountRight(const char *right)
116 : {
117 0 : enum sec_privilege priv_id;
118 0 : uint32_t right_bit;
119 :
120 123 : priv_id = sec_privilege_id(right);
121 123 : if (priv_id != SEC_PRIV_INVALID) {
122 115 : return true;
123 : }
124 :
125 8 : right_bit = sec_right_bit(right);
126 8 : if (right_bit != 0) {
127 8 : return true;
128 : }
129 :
130 0 : return false;
131 : }
132 :
133 : /*
134 : this is based on the samba3 function make_lsa_object_sd()
135 : It uses the same logic, but with samba4 helper functions
136 : */
137 0 : static NTSTATUS dcesrv_build_lsa_sd(TALLOC_CTX *mem_ctx,
138 : struct security_descriptor **sd,
139 : struct dom_sid *sid,
140 : uint32_t sid_access)
141 : {
142 0 : NTSTATUS status;
143 0 : uint32_t rid;
144 0 : struct dom_sid *domain_sid, *domain_admins_sid;
145 0 : const char *domain_admins_sid_str, *sidstr;
146 0 : TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
147 :
148 0 : status = dom_sid_split_rid(tmp_ctx, sid, &domain_sid, &rid);
149 0 : if (!NT_STATUS_IS_OK(status)) {
150 0 : TALLOC_FREE(tmp_ctx);
151 0 : return status;
152 : }
153 :
154 0 : domain_admins_sid = dom_sid_add_rid(tmp_ctx, domain_sid, DOMAIN_RID_ADMINS);
155 0 : if (domain_admins_sid == NULL) {
156 0 : TALLOC_FREE(tmp_ctx);
157 0 : return NT_STATUS_NO_MEMORY;
158 : }
159 :
160 0 : domain_admins_sid_str = dom_sid_string(tmp_ctx, domain_admins_sid);
161 0 : if (domain_admins_sid_str == NULL) {
162 0 : TALLOC_FREE(tmp_ctx);
163 0 : return NT_STATUS_NO_MEMORY;
164 : }
165 :
166 0 : sidstr = dom_sid_string(tmp_ctx, sid);
167 0 : if (sidstr == NULL) {
168 0 : TALLOC_FREE(tmp_ctx);
169 0 : return NT_STATUS_NO_MEMORY;
170 : }
171 :
172 0 : *sd = security_descriptor_dacl_create(mem_ctx,
173 : 0, sidstr, NULL,
174 :
175 : SID_WORLD,
176 : SEC_ACE_TYPE_ACCESS_ALLOWED,
177 : SEC_GENERIC_EXECUTE | SEC_GENERIC_READ, 0,
178 :
179 : SID_BUILTIN_ADMINISTRATORS,
180 : SEC_ACE_TYPE_ACCESS_ALLOWED,
181 : SEC_GENERIC_ALL, 0,
182 :
183 : SID_BUILTIN_ACCOUNT_OPERATORS,
184 : SEC_ACE_TYPE_ACCESS_ALLOWED,
185 : SEC_GENERIC_ALL, 0,
186 :
187 : domain_admins_sid_str,
188 : SEC_ACE_TYPE_ACCESS_ALLOWED,
189 : SEC_GENERIC_ALL, 0,
190 :
191 : sidstr,
192 : SEC_ACE_TYPE_ACCESS_ALLOWED,
193 : sid_access, 0,
194 :
195 : NULL);
196 0 : talloc_free(tmp_ctx);
197 :
198 0 : NT_STATUS_HAVE_NO_MEMORY(*sd);
199 :
200 0 : return NT_STATUS_OK;
201 : }
202 :
203 :
204 : static NTSTATUS dcesrv_lsa_EnumAccountRights(struct dcesrv_call_state *dce_call,
205 : TALLOC_CTX *mem_ctx,
206 : struct lsa_EnumAccountRights *r);
207 :
208 : static NTSTATUS dcesrv_lsa_AddRemoveAccountRights(struct dcesrv_call_state *dce_call,
209 : TALLOC_CTX *mem_ctx,
210 : struct lsa_policy_state *state,
211 : int ldb_flag,
212 : struct dom_sid *sid,
213 : const struct lsa_RightSet *rights);
214 :
215 : /*
216 : lsa_Close
217 : */
218 922 : static NTSTATUS dcesrv_lsa_Close(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
219 : struct lsa_Close *r)
220 : {
221 36 : enum dcerpc_transport_t transport =
222 922 : dcerpc_binding_get_transport(dce_call->conn->endpoint->ep_description);
223 36 : struct dcesrv_handle *h;
224 :
225 922 : if (transport != NCACN_NP && transport != NCALRPC) {
226 0 : DCESRV_FAULT(DCERPC_FAULT_ACCESS_DENIED);
227 : }
228 :
229 922 : *r->out.handle = *r->in.handle;
230 :
231 922 : DCESRV_PULL_HANDLE(h, r->in.handle, DCESRV_HANDLE_ANY);
232 :
233 753 : talloc_free(h);
234 :
235 753 : ZERO_STRUCTP(r->out.handle);
236 :
237 753 : return NT_STATUS_OK;
238 : }
239 :
240 :
241 : /*
242 : lsa_Delete
243 : */
244 33 : static NTSTATUS dcesrv_lsa_Delete(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
245 : struct lsa_Delete *r)
246 : {
247 33 : return NT_STATUS_NOT_SUPPORTED;
248 : }
249 :
250 :
251 : /*
252 : lsa_DeleteObject
253 : */
254 1788 : static NTSTATUS dcesrv_lsa_DeleteObject(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
255 : struct lsa_DeleteObject *r)
256 : {
257 0 : struct auth_session_info *session_info =
258 1788 : dcesrv_call_session_info(dce_call);
259 0 : struct dcesrv_handle *h;
260 0 : int ret;
261 :
262 1788 : DCESRV_PULL_HANDLE(h, r->in.handle, DCESRV_HANDLE_ANY);
263 :
264 1788 : if (h->wire_handle.handle_type == LSA_HANDLE_SECRET) {
265 1669 : struct lsa_secret_state *secret_state = h->data;
266 :
267 : /* Ensure user is permitted to delete this... */
268 1669 : switch (security_session_user_level(session_info, NULL))
269 : {
270 1669 : case SECURITY_SYSTEM:
271 : case SECURITY_ADMINISTRATOR:
272 1669 : break;
273 0 : default:
274 : /* Users and anonymous are not allowed to delete things */
275 0 : return NT_STATUS_ACCESS_DENIED;
276 : }
277 :
278 1669 : ret = ldb_delete(secret_state->sam_ldb,
279 : secret_state->secret_dn);
280 1669 : if (ret != LDB_SUCCESS) {
281 18 : return NT_STATUS_INVALID_HANDLE;
282 : }
283 :
284 1651 : ZERO_STRUCTP(r->out.handle);
285 :
286 1651 : return NT_STATUS_OK;
287 :
288 119 : } else if (h->wire_handle.handle_type == LSA_HANDLE_TRUSTED_DOMAIN) {
289 0 : struct lsa_trusted_domain_state *trusted_domain_state =
290 112 : talloc_get_type(h->data, struct lsa_trusted_domain_state);
291 112 : ret = ldb_transaction_start(trusted_domain_state->policy->sam_ldb);
292 112 : if (ret != LDB_SUCCESS) {
293 0 : return NT_STATUS_INTERNAL_DB_CORRUPTION;
294 : }
295 :
296 112 : ret = ldb_delete(trusted_domain_state->policy->sam_ldb,
297 : trusted_domain_state->trusted_domain_dn);
298 112 : if (ret != LDB_SUCCESS) {
299 0 : ldb_transaction_cancel(trusted_domain_state->policy->sam_ldb);
300 0 : return NT_STATUS_INVALID_HANDLE;
301 : }
302 :
303 112 : if (trusted_domain_state->trusted_domain_user_dn) {
304 52 : ret = ldb_delete(trusted_domain_state->policy->sam_ldb,
305 : trusted_domain_state->trusted_domain_user_dn);
306 52 : if (ret != LDB_SUCCESS) {
307 0 : ldb_transaction_cancel(trusted_domain_state->policy->sam_ldb);
308 0 : return NT_STATUS_INVALID_HANDLE;
309 : }
310 : }
311 :
312 112 : ret = ldb_transaction_commit(trusted_domain_state->policy->sam_ldb);
313 112 : if (ret != LDB_SUCCESS) {
314 0 : return NT_STATUS_INTERNAL_DB_CORRUPTION;
315 : }
316 :
317 112 : ZERO_STRUCTP(r->out.handle);
318 :
319 112 : return NT_STATUS_OK;
320 :
321 7 : } else if (h->wire_handle.handle_type == LSA_HANDLE_ACCOUNT) {
322 0 : struct lsa_RightSet *rights;
323 0 : struct lsa_account_state *astate;
324 0 : struct lsa_EnumAccountRights r2;
325 0 : NTSTATUS status;
326 :
327 7 : rights = talloc(mem_ctx, struct lsa_RightSet);
328 :
329 7 : DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
330 :
331 7 : astate = h->data;
332 :
333 7 : r2.in.handle = &astate->policy->handle->wire_handle;
334 7 : r2.in.sid = astate->account_sid;
335 7 : r2.out.rights = rights;
336 :
337 : /* dcesrv_lsa_EnumAccountRights takes a LSA_HANDLE_POLICY,
338 : but we have a LSA_HANDLE_ACCOUNT here, so this call
339 : will always fail */
340 7 : status = dcesrv_lsa_EnumAccountRights(dce_call, mem_ctx, &r2);
341 7 : if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
342 3 : return NT_STATUS_OK;
343 : }
344 :
345 4 : if (!NT_STATUS_IS_OK(status)) {
346 0 : return status;
347 : }
348 :
349 4 : status = dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, astate->policy,
350 : LDB_FLAG_MOD_DELETE, astate->account_sid,
351 4 : r2.out.rights);
352 4 : if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
353 0 : return NT_STATUS_OK;
354 : }
355 :
356 4 : if (!NT_STATUS_IS_OK(status)) {
357 0 : return status;
358 : }
359 :
360 4 : ZERO_STRUCTP(r->out.handle);
361 :
362 4 : return NT_STATUS_OK;
363 : }
364 :
365 0 : return NT_STATUS_INVALID_HANDLE;
366 : }
367 :
368 :
369 : /*
370 : lsa_EnumPrivs
371 : */
372 3 : static NTSTATUS dcesrv_lsa_EnumPrivs(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
373 : struct lsa_EnumPrivs *r)
374 : {
375 0 : struct dcesrv_handle *h;
376 0 : uint32_t i;
377 0 : enum sec_privilege priv;
378 0 : const char *privname;
379 :
380 3 : DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
381 :
382 3 : i = *r->in.resume_handle;
383 :
384 78 : while (((priv = sec_privilege_from_index(i)) != SEC_PRIV_INVALID) &&
385 75 : r->out.privs->count < r->in.max_count) {
386 0 : struct lsa_PrivEntry *e;
387 75 : privname = sec_privilege_name(priv);
388 75 : r->out.privs->privs = talloc_realloc(r->out.privs,
389 : r->out.privs->privs,
390 : struct lsa_PrivEntry,
391 : r->out.privs->count+1);
392 75 : if (r->out.privs->privs == NULL) {
393 0 : return NT_STATUS_NO_MEMORY;
394 : }
395 75 : e = &r->out.privs->privs[r->out.privs->count];
396 75 : e->luid.low = priv;
397 75 : e->luid.high = 0;
398 75 : e->name.string = privname;
399 75 : r->out.privs->count++;
400 75 : i++;
401 : }
402 :
403 3 : *r->out.resume_handle = i;
404 :
405 3 : return NT_STATUS_OK;
406 : }
407 :
408 :
409 : /*
410 : lsa_QuerySecObj
411 : */
412 48 : static NTSTATUS dcesrv_lsa_QuerySecurity(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
413 : struct lsa_QuerySecurity *r)
414 : {
415 12 : struct auth_session_info *session_info =
416 48 : dcesrv_call_session_info(dce_call);
417 12 : struct dcesrv_handle *h;
418 48 : const struct security_descriptor *sd = NULL;
419 48 : uint32_t access_granted = 0;
420 48 : struct sec_desc_buf *sdbuf = NULL;
421 12 : NTSTATUS status;
422 12 : struct dom_sid *sid;
423 :
424 48 : DCESRV_PULL_HANDLE(h, r->in.handle, DCESRV_HANDLE_ANY);
425 :
426 48 : sid = &session_info->security_token->sids[PRIMARY_USER_SID_INDEX];
427 :
428 48 : if (h->wire_handle.handle_type == LSA_HANDLE_POLICY) {
429 48 : struct lsa_policy_state *pstate = h->data;
430 :
431 48 : sd = pstate->sd;
432 48 : access_granted = pstate->access_mask;
433 :
434 0 : } else if (h->wire_handle.handle_type == LSA_HANDLE_ACCOUNT) {
435 0 : struct lsa_account_state *astate = h->data;
436 0 : struct security_descriptor *_sd = NULL;
437 :
438 0 : status = dcesrv_build_lsa_sd(mem_ctx, &_sd, sid,
439 : LSA_ACCOUNT_ALL_ACCESS);
440 0 : if (!NT_STATUS_IS_OK(status)) {
441 0 : return status;
442 : }
443 0 : sd = _sd;
444 0 : access_granted = astate->access_mask;
445 : } else {
446 0 : return NT_STATUS_INVALID_HANDLE;
447 : }
448 :
449 48 : sdbuf = talloc_zero(mem_ctx, struct sec_desc_buf);
450 48 : if (sdbuf == NULL) {
451 0 : return NT_STATUS_NO_MEMORY;
452 : }
453 :
454 48 : status = security_descriptor_for_client(sdbuf, sd, r->in.sec_info,
455 : access_granted, &sdbuf->sd);
456 48 : if (!NT_STATUS_IS_OK(status)) {
457 0 : return status;
458 : }
459 :
460 48 : *r->out.sdbuf = sdbuf;
461 :
462 48 : return NT_STATUS_OK;
463 : }
464 :
465 :
466 : /*
467 : lsa_SetSecObj
468 : */
469 0 : static NTSTATUS dcesrv_lsa_SetSecObj(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
470 : struct lsa_SetSecObj *r)
471 : {
472 0 : DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
473 : }
474 :
475 :
476 : /*
477 : lsa_ChangePassword
478 : */
479 0 : static NTSTATUS dcesrv_lsa_ChangePassword(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
480 : struct lsa_ChangePassword *r)
481 : {
482 0 : DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
483 : }
484 :
485 : /*
486 : dssetup_DsRoleGetPrimaryDomainInformation
487 :
488 : This is not an LSA call, but is the only call left on the DSSETUP
489 : pipe (after the pipe was truncated), and needs lsa_get_policy_state
490 : */
491 123 : static WERROR dcesrv_dssetup_DsRoleGetPrimaryDomainInformation(struct dcesrv_call_state *dce_call,
492 : TALLOC_CTX *mem_ctx,
493 : struct dssetup_DsRoleGetPrimaryDomainInformation *r)
494 : {
495 9 : union dssetup_DsRoleInfo *info;
496 :
497 123 : info = talloc_zero(mem_ctx, union dssetup_DsRoleInfo);
498 123 : W_ERROR_HAVE_NO_MEMORY(info);
499 :
500 123 : switch (r->in.level) {
501 63 : case DS_ROLE_BASIC_INFORMATION:
502 : {
503 63 : enum dssetup_DsRole role = DS_ROLE_STANDALONE_SERVER;
504 63 : uint32_t flags = 0;
505 63 : const char *domain = NULL;
506 63 : const char *dns_domain = NULL;
507 63 : const char *forest = NULL;
508 3 : struct GUID domain_guid;
509 3 : struct lsa_policy_state *state;
510 :
511 63 : NTSTATUS status = dcesrv_lsa_get_policy_state(dce_call, mem_ctx,
512 : 0, /* we skip access checks */
513 : &state);
514 63 : if (!NT_STATUS_IS_OK(status)) {
515 0 : return ntstatus_to_werror(status);
516 : }
517 :
518 63 : ZERO_STRUCT(domain_guid);
519 :
520 63 : switch (lpcfg_server_role(dce_call->conn->dce_ctx->lp_ctx)) {
521 0 : case ROLE_STANDALONE:
522 0 : role = DS_ROLE_STANDALONE_SERVER;
523 0 : break;
524 4 : case ROLE_DOMAIN_MEMBER:
525 4 : role = DS_ROLE_MEMBER_SERVER;
526 4 : break;
527 59 : case ROLE_ACTIVE_DIRECTORY_DC:
528 59 : if (samdb_is_pdc(state->sam_ldb)) {
529 56 : role = DS_ROLE_PRIMARY_DC;
530 : } else {
531 0 : role = DS_ROLE_BACKUP_DC;
532 : }
533 56 : break;
534 : }
535 :
536 63 : switch (lpcfg_server_role(dce_call->conn->dce_ctx->lp_ctx)) {
537 0 : case ROLE_STANDALONE:
538 0 : domain = talloc_strdup(mem_ctx, lpcfg_workgroup(dce_call->conn->dce_ctx->lp_ctx));
539 0 : W_ERROR_HAVE_NO_MEMORY(domain);
540 0 : break;
541 4 : case ROLE_DOMAIN_MEMBER:
542 4 : domain = talloc_strdup(mem_ctx, lpcfg_workgroup(dce_call->conn->dce_ctx->lp_ctx));
543 4 : W_ERROR_HAVE_NO_MEMORY(domain);
544 : /* TODO: what is with dns_domain and forest and guid? */
545 4 : break;
546 59 : case ROLE_ACTIVE_DIRECTORY_DC:
547 59 : flags = DS_ROLE_PRIMARY_DS_RUNNING;
548 :
549 59 : if (state->mixed_domain == 1) {
550 0 : flags |= DS_ROLE_PRIMARY_DS_MIXED_MODE;
551 : }
552 :
553 59 : domain = state->domain_name;
554 59 : dns_domain = state->domain_dns;
555 59 : forest = state->forest_dns;
556 :
557 59 : domain_guid = state->domain_guid;
558 59 : flags |= DS_ROLE_PRIMARY_DOMAIN_GUID_PRESENT;
559 59 : break;
560 : }
561 :
562 63 : info->basic.role = role;
563 63 : info->basic.flags = flags;
564 63 : info->basic.domain = domain;
565 63 : info->basic.dns_domain = dns_domain;
566 63 : info->basic.forest = forest;
567 63 : info->basic.domain_guid = domain_guid;
568 :
569 63 : r->out.info = info;
570 63 : return WERR_OK;
571 : }
572 30 : case DS_ROLE_UPGRADE_STATUS:
573 : {
574 30 : info->upgrade.upgrading = DS_ROLE_NOT_UPGRADING;
575 30 : info->upgrade.previous_role = DS_ROLE_PREVIOUS_UNKNOWN;
576 :
577 30 : r->out.info = info;
578 30 : return WERR_OK;
579 : }
580 30 : case DS_ROLE_OP_STATUS:
581 : {
582 30 : info->opstatus.status = DS_ROLE_OP_IDLE;
583 :
584 30 : r->out.info = info;
585 30 : return WERR_OK;
586 : }
587 0 : default:
588 0 : return WERR_INVALID_PARAMETER;
589 : }
590 : }
591 :
592 : /*
593 : fill in the AccountDomain info
594 : */
595 751 : static NTSTATUS dcesrv_lsa_info_AccountDomain(struct lsa_policy_state *state, TALLOC_CTX *mem_ctx,
596 : struct lsa_DomainInfo *info)
597 : {
598 751 : info->name.string = state->domain_name;
599 751 : info->sid = state->domain_sid;
600 :
601 751 : return NT_STATUS_OK;
602 : }
603 :
604 : /*
605 : fill in the DNS domain info
606 : */
607 880 : static NTSTATUS dcesrv_lsa_info_DNS(struct lsa_policy_state *state, TALLOC_CTX *mem_ctx,
608 : struct lsa_DnsDomainInfo *info)
609 : {
610 880 : info->name.string = state->domain_name;
611 880 : info->sid = state->domain_sid;
612 880 : info->dns_domain.string = state->domain_dns;
613 880 : info->dns_forest.string = state->forest_dns;
614 880 : info->domain_guid = state->domain_guid;
615 :
616 880 : return NT_STATUS_OK;
617 : }
618 :
619 : /*
620 : lsa_QueryInfoPolicy2
621 : */
622 1847 : static NTSTATUS dcesrv_lsa_QueryInfoPolicy2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
623 : struct lsa_QueryInfoPolicy2 *r)
624 : {
625 146 : struct lsa_policy_state *state;
626 146 : struct dcesrv_handle *h;
627 146 : union lsa_PolicyInformation *info;
628 :
629 1847 : *r->out.info = NULL;
630 :
631 1847 : DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
632 :
633 1847 : state = h->data;
634 :
635 1847 : info = talloc_zero(mem_ctx, union lsa_PolicyInformation);
636 1847 : if (!info) {
637 0 : return NT_STATUS_NO_MEMORY;
638 : }
639 1847 : *r->out.info = info;
640 :
641 1847 : switch (r->in.level) {
642 24 : case LSA_POLICY_INFO_AUDIT_LOG:
643 : /* we don't need to fill in any of this */
644 24 : ZERO_STRUCT(info->audit_log);
645 24 : return NT_STATUS_OK;
646 24 : case LSA_POLICY_INFO_AUDIT_EVENTS:
647 : /* we don't need to fill in any of this */
648 24 : ZERO_STRUCT(info->audit_events);
649 24 : return NT_STATUS_OK;
650 24 : case LSA_POLICY_INFO_PD:
651 : /* we don't need to fill in any of this */
652 24 : ZERO_STRUCT(info->pd);
653 24 : return NT_STATUS_OK;
654 :
655 563 : case LSA_POLICY_INFO_DOMAIN:
656 563 : return dcesrv_lsa_info_AccountDomain(state, mem_ctx, &info->domain);
657 164 : case LSA_POLICY_INFO_ACCOUNT_DOMAIN:
658 164 : return dcesrv_lsa_info_AccountDomain(state, mem_ctx, &info->account_domain);
659 24 : case LSA_POLICY_INFO_L_ACCOUNT_DOMAIN:
660 24 : return dcesrv_lsa_info_AccountDomain(state, mem_ctx, &info->l_account_domain);
661 :
662 24 : case LSA_POLICY_INFO_ROLE:
663 24 : info->role.role = LSA_ROLE_PRIMARY;
664 24 : return NT_STATUS_OK;
665 :
666 880 : case LSA_POLICY_INFO_DNS:
667 : case LSA_POLICY_INFO_DNS_INT:
668 880 : return dcesrv_lsa_info_DNS(state, mem_ctx, &info->dns);
669 :
670 24 : case LSA_POLICY_INFO_REPLICA:
671 24 : ZERO_STRUCT(info->replica);
672 24 : return NT_STATUS_OK;
673 :
674 24 : case LSA_POLICY_INFO_QUOTA:
675 24 : ZERO_STRUCT(info->quota);
676 24 : return NT_STATUS_OK;
677 :
678 72 : case LSA_POLICY_INFO_MOD:
679 : case LSA_POLICY_INFO_AUDIT_FULL_SET:
680 : case LSA_POLICY_INFO_AUDIT_FULL_QUERY:
681 : /* windows gives INVALID_PARAMETER */
682 72 : *r->out.info = NULL;
683 72 : return NT_STATUS_INVALID_PARAMETER;
684 : }
685 :
686 0 : *r->out.info = NULL;
687 0 : return NT_STATUS_INVALID_INFO_CLASS;
688 : }
689 :
690 : /*
691 : lsa_QueryInfoPolicy
692 : */
693 847 : static NTSTATUS dcesrv_lsa_QueryInfoPolicy(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
694 : struct lsa_QueryInfoPolicy *r)
695 : {
696 72 : struct lsa_QueryInfoPolicy2 r2;
697 72 : NTSTATUS status;
698 :
699 847 : ZERO_STRUCT(r2);
700 :
701 847 : r2.in.handle = r->in.handle;
702 847 : r2.in.level = r->in.level;
703 847 : r2.out.info = r->out.info;
704 :
705 847 : status = dcesrv_lsa_QueryInfoPolicy2(dce_call, mem_ctx, &r2);
706 :
707 847 : return status;
708 : }
709 :
710 : /*
711 : lsa_SetInfoPolicy
712 : */
713 0 : static NTSTATUS dcesrv_lsa_SetInfoPolicy(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
714 : struct lsa_SetInfoPolicy *r)
715 : {
716 : /* need to support this */
717 0 : DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
718 : }
719 :
720 :
721 : /*
722 : lsa_ClearAuditLog
723 : */
724 0 : static NTSTATUS dcesrv_lsa_ClearAuditLog(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
725 : struct lsa_ClearAuditLog *r)
726 : {
727 0 : DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
728 : }
729 :
730 :
731 : static const struct generic_mapping dcesrv_lsa_account_mapping = {
732 : LSA_ACCOUNT_READ,
733 : LSA_ACCOUNT_WRITE,
734 : LSA_ACCOUNT_EXECUTE,
735 : LSA_ACCOUNT_ALL_ACCESS
736 : };
737 :
738 : /*
739 : lsa_CreateAccount
740 :
741 : This call does not seem to have any long-term effects, hence no database operations
742 :
743 : we need to talk to the MS product group to find out what this account database means!
744 :
745 : answer is that the lsa database is totally separate from the SAM and
746 : ldap databases. We are going to need a separate ldb to store these
747 : accounts. The SIDs on this account bear no relation to the SIDs in
748 : AD
749 : */
750 3 : static NTSTATUS dcesrv_lsa_CreateAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
751 : struct lsa_CreateAccount *r)
752 : {
753 0 : struct lsa_account_state *astate;
754 :
755 0 : struct lsa_policy_state *state;
756 0 : struct dcesrv_handle *h, *ah;
757 :
758 3 : ZERO_STRUCTP(r->out.acct_handle);
759 :
760 3 : DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
761 :
762 3 : state = h->data;
763 :
764 3 : astate = talloc(dce_call->conn, struct lsa_account_state);
765 3 : if (astate == NULL) {
766 0 : return NT_STATUS_NO_MEMORY;
767 : }
768 :
769 3 : astate->account_sid = dom_sid_dup(astate, r->in.sid);
770 3 : if (astate->account_sid == NULL) {
771 0 : talloc_free(astate);
772 0 : return NT_STATUS_NO_MEMORY;
773 : }
774 :
775 3 : astate->policy = talloc_reference(astate, state);
776 3 : astate->access_mask = r->in.access_mask;
777 :
778 : /*
779 : * For now we grant all requested access.
780 : *
781 : * We will fail at the ldb layer later.
782 : */
783 3 : if (astate->access_mask & SEC_FLAG_MAXIMUM_ALLOWED) {
784 3 : astate->access_mask &= ~SEC_FLAG_MAXIMUM_ALLOWED;
785 3 : astate->access_mask |= LSA_ACCOUNT_ALL_ACCESS;
786 : }
787 3 : se_map_generic(&astate->access_mask, &dcesrv_lsa_account_mapping);
788 :
789 3 : DEBUG(10,("%s: %s access desired[0x%08X] granted[0x%08X].\n",
790 : __func__, dom_sid_string(mem_ctx, astate->account_sid),
791 : (unsigned)r->in.access_mask,
792 : (unsigned)astate->access_mask));
793 :
794 3 : ah = dcesrv_handle_create(dce_call, LSA_HANDLE_ACCOUNT);
795 3 : if (!ah) {
796 0 : talloc_free(astate);
797 0 : return NT_STATUS_NO_MEMORY;
798 : }
799 :
800 3 : ah->data = talloc_steal(ah, astate);
801 :
802 3 : *r->out.acct_handle = ah->wire_handle;
803 :
804 3 : return NT_STATUS_OK;
805 : }
806 :
807 :
808 : /*
809 : lsa_EnumAccounts
810 : */
811 18 : static NTSTATUS dcesrv_lsa_EnumAccounts(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
812 : struct lsa_EnumAccounts *r)
813 : {
814 0 : struct dcesrv_handle *h;
815 0 : struct lsa_policy_state *state;
816 0 : int ret;
817 0 : struct ldb_message **res;
818 18 : const char * const attrs[] = { "objectSid", NULL};
819 0 : uint32_t count, i;
820 :
821 18 : DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
822 :
823 18 : state = h->data;
824 :
825 : /* NOTE: This call must only return accounts that have at least
826 : one privilege set
827 : */
828 18 : ret = gendb_search(state->pdb, mem_ctx, NULL, &res, attrs,
829 : "(&(objectSid=*)(privilege=*))");
830 18 : if (ret < 0) {
831 0 : return NT_STATUS_INTERNAL_DB_CORRUPTION;
832 : }
833 :
834 18 : if (*r->in.resume_handle >= ret) {
835 3 : return NT_STATUS_NO_MORE_ENTRIES;
836 : }
837 :
838 15 : count = ret - *r->in.resume_handle;
839 15 : if (count > r->in.num_entries) {
840 0 : count = r->in.num_entries;
841 : }
842 :
843 15 : if (count == 0) {
844 0 : return NT_STATUS_NO_MORE_ENTRIES;
845 : }
846 :
847 15 : r->out.sids->sids = talloc_array(r->out.sids, struct lsa_SidPtr, count);
848 15 : if (r->out.sids->sids == NULL) {
849 0 : return NT_STATUS_NO_MEMORY;
850 : }
851 :
852 113 : for (i=0;i<count;i++) {
853 196 : r->out.sids->sids[i].sid =
854 98 : samdb_result_dom_sid(r->out.sids->sids,
855 98 : res[i + *r->in.resume_handle],
856 : "objectSid");
857 98 : NT_STATUS_HAVE_NO_MEMORY(r->out.sids->sids[i].sid);
858 : }
859 :
860 15 : r->out.sids->num_sids = count;
861 15 : *r->out.resume_handle = count + *r->in.resume_handle;
862 :
863 15 : return NT_STATUS_OK;
864 : }
865 :
866 : /* This decrypts and returns Trusted Domain Auth Information Internal data */
867 62 : static NTSTATUS get_trustdom_auth_blob(struct dcesrv_call_state *dce_call,
868 : TALLOC_CTX *mem_ctx, DATA_BLOB *auth_blob,
869 : struct trustDomainPasswords *auth_struct)
870 : {
871 62 : DATA_BLOB session_key = data_blob(NULL, 0);
872 0 : enum ndr_err_code ndr_err;
873 0 : NTSTATUS nt_status;
874 62 : gnutls_cipher_hd_t cipher_hnd = NULL;
875 0 : gnutls_datum_t _session_key;
876 0 : int rc;
877 0 : struct auth_session_info *session_info =
878 62 : dcesrv_call_session_info(dce_call);
879 62 : struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
880 0 : bool encrypted;
881 :
882 0 : encrypted =
883 62 : dcerpc_is_transport_encrypted(session_info);
884 62 : if (lpcfg_weak_crypto(lp_ctx) == SAMBA_WEAK_CRYPTO_DISALLOWED &&
885 0 : !encrypted) {
886 0 : DBG_ERR("Transport isn't encrypted and weak crypto disallowed!\n");
887 0 : return NT_STATUS_ACCESS_DENIED;
888 : }
889 :
890 :
891 62 : nt_status = dcesrv_transport_session_key(dce_call, &session_key);
892 62 : if (!NT_STATUS_IS_OK(nt_status)) {
893 0 : return nt_status;
894 : }
895 :
896 62 : _session_key = (gnutls_datum_t) {
897 62 : .data = session_key.data,
898 62 : .size = session_key.length,
899 : };
900 :
901 62 : GNUTLS_FIPS140_SET_LAX_MODE();
902 62 : rc = gnutls_cipher_init(&cipher_hnd,
903 : GNUTLS_CIPHER_ARCFOUR_128,
904 : &_session_key,
905 : NULL);
906 62 : if (rc < 0) {
907 0 : GNUTLS_FIPS140_SET_STRICT_MODE();
908 0 : nt_status = gnutls_error_to_ntstatus(rc, NT_STATUS_CRYPTO_SYSTEM_INVALID);
909 0 : goto out;
910 : }
911 :
912 62 : rc = gnutls_cipher_decrypt(cipher_hnd,
913 62 : auth_blob->data,
914 : auth_blob->length);
915 62 : gnutls_cipher_deinit(cipher_hnd);
916 62 : GNUTLS_FIPS140_SET_STRICT_MODE();
917 62 : if (rc < 0) {
918 0 : nt_status = gnutls_error_to_ntstatus(rc, NT_STATUS_CRYPTO_SYSTEM_INVALID);
919 0 : goto out;
920 : }
921 :
922 62 : ndr_err = ndr_pull_struct_blob(auth_blob, mem_ctx,
923 : auth_struct,
924 : (ndr_pull_flags_fn_t)ndr_pull_trustDomainPasswords);
925 62 : if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
926 0 : return NT_STATUS_INVALID_PARAMETER;
927 : }
928 :
929 62 : nt_status = NT_STATUS_OK;
930 62 : out:
931 62 : return nt_status;
932 : }
933 :
934 118 : static NTSTATUS get_trustauth_inout_blob(struct dcesrv_call_state *dce_call,
935 : TALLOC_CTX *mem_ctx,
936 : struct trustAuthInOutBlob *iopw,
937 : DATA_BLOB *trustauth_blob)
938 : {
939 0 : enum ndr_err_code ndr_err;
940 :
941 118 : if (iopw->current.count != iopw->count) {
942 0 : return NT_STATUS_INVALID_PARAMETER;
943 : }
944 :
945 118 : if (iopw->previous.count > iopw->current.count) {
946 0 : return NT_STATUS_INVALID_PARAMETER;
947 : }
948 :
949 118 : if (iopw->previous.count == 0) {
950 : /*
951 : * If the previous credentials are not present
952 : * we need to make a copy.
953 : */
954 46 : iopw->previous = iopw->current;
955 : }
956 :
957 118 : if (iopw->previous.count < iopw->current.count) {
958 0 : struct AuthenticationInformationArray *c = &iopw->current;
959 0 : struct AuthenticationInformationArray *p = &iopw->previous;
960 :
961 : /*
962 : * The previous array needs to have the same size
963 : * as the current one.
964 : *
965 : * We may have to fill with TRUST_AUTH_TYPE_NONE
966 : * elements.
967 : */
968 0 : p->array = talloc_realloc(mem_ctx, p->array,
969 : struct AuthenticationInformation,
970 : c->count);
971 0 : if (p->array == NULL) {
972 0 : return NT_STATUS_NO_MEMORY;
973 : }
974 :
975 0 : while (p->count < c->count) {
976 0 : struct AuthenticationInformation *a =
977 0 : &p->array[p->count++];
978 :
979 0 : *a = (struct AuthenticationInformation) {
980 0 : .LastUpdateTime = p->array[0].LastUpdateTime,
981 : .AuthType = TRUST_AUTH_TYPE_NONE,
982 : };
983 : }
984 : }
985 :
986 118 : ndr_err = ndr_push_struct_blob(trustauth_blob, mem_ctx,
987 : iopw,
988 : (ndr_push_flags_fn_t)ndr_push_trustAuthInOutBlob);
989 118 : if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
990 0 : return NT_STATUS_INVALID_PARAMETER;
991 : }
992 :
993 118 : return NT_STATUS_OK;
994 : }
995 :
996 71 : static NTSTATUS add_trust_user(TALLOC_CTX *mem_ctx,
997 : struct ldb_context *sam_ldb,
998 : struct ldb_dn *base_dn,
999 : const char *netbios_name,
1000 : struct trustAuthInOutBlob *in,
1001 : struct ldb_dn **user_dn)
1002 : {
1003 0 : struct ldb_request *req;
1004 0 : struct ldb_message *msg;
1005 0 : struct ldb_dn *dn;
1006 0 : uint32_t i;
1007 0 : int ret;
1008 :
1009 71 : dn = ldb_dn_copy(mem_ctx, base_dn);
1010 71 : if (!dn) {
1011 0 : return NT_STATUS_NO_MEMORY;
1012 : }
1013 71 : if (!ldb_dn_add_child_fmt(dn, "cn=%s$,cn=users", netbios_name)) {
1014 0 : return NT_STATUS_NO_MEMORY;
1015 : }
1016 :
1017 71 : msg = ldb_msg_new(mem_ctx);
1018 71 : if (!msg) {
1019 0 : return NT_STATUS_NO_MEMORY;
1020 : }
1021 71 : msg->dn = dn;
1022 :
1023 71 : ret = ldb_msg_add_string(msg, "objectClass", "user");
1024 71 : if (ret != LDB_SUCCESS) {
1025 0 : return NT_STATUS_NO_MEMORY;
1026 : }
1027 :
1028 71 : ret = ldb_msg_add_fmt(msg, "samAccountName", "%s$", netbios_name);
1029 71 : if (ret != LDB_SUCCESS) {
1030 0 : return NT_STATUS_NO_MEMORY;
1031 : }
1032 :
1033 71 : ret = samdb_msg_add_uint(sam_ldb, msg, msg, "userAccountControl",
1034 : UF_INTERDOMAIN_TRUST_ACCOUNT);
1035 71 : if (ret != LDB_SUCCESS) {
1036 0 : return NT_STATUS_NO_MEMORY;
1037 : }
1038 :
1039 118 : for (i = 0; i < in->count; i++) {
1040 0 : const char *attribute;
1041 0 : struct ldb_val v;
1042 47 : switch (in->current.array[i].AuthType) {
1043 0 : case TRUST_AUTH_TYPE_NT4OWF:
1044 0 : attribute = "unicodePwd";
1045 0 : v.data = (uint8_t *)&in->current.array[i].AuthInfo.nt4owf.password;
1046 0 : v.length = 16;
1047 0 : break;
1048 47 : case TRUST_AUTH_TYPE_CLEAR:
1049 47 : attribute = "clearTextPassword";
1050 47 : v.data = in->current.array[i].AuthInfo.clear.password;
1051 47 : v.length = in->current.array[i].AuthInfo.clear.size;
1052 47 : break;
1053 0 : default:
1054 0 : continue;
1055 : }
1056 :
1057 47 : ret = ldb_msg_add_value(msg, attribute, &v, NULL);
1058 47 : if (ret != LDB_SUCCESS) {
1059 0 : return NT_STATUS_NO_MEMORY;
1060 : }
1061 : }
1062 :
1063 : /* create the trusted_domain user account */
1064 71 : ret = ldb_build_add_req(&req, sam_ldb, mem_ctx, msg, NULL, NULL,
1065 : ldb_op_default_callback, NULL);
1066 71 : if (ret != LDB_SUCCESS) {
1067 0 : return NT_STATUS_NO_MEMORY;
1068 : }
1069 :
1070 71 : ret = ldb_request_add_control(req, DSDB_CONTROL_PERMIT_INTERDOMAIN_TRUST_UAC_OID,
1071 : false, NULL);
1072 71 : if (ret != LDB_SUCCESS) {
1073 0 : return NT_STATUS_NO_MEMORY;
1074 : }
1075 :
1076 71 : ret = dsdb_autotransaction_request(sam_ldb, req);
1077 71 : if (ret != LDB_SUCCESS) {
1078 0 : DEBUG(0,("Failed to create user record %s: %s\n",
1079 : ldb_dn_get_linearized(msg->dn),
1080 : ldb_errstring(sam_ldb)));
1081 :
1082 0 : switch (ret) {
1083 0 : case LDB_ERR_ENTRY_ALREADY_EXISTS:
1084 0 : return NT_STATUS_DOMAIN_EXISTS;
1085 0 : case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
1086 0 : return NT_STATUS_ACCESS_DENIED;
1087 0 : default:
1088 0 : return NT_STATUS_INTERNAL_DB_CORRUPTION;
1089 : }
1090 : }
1091 :
1092 71 : if (user_dn) {
1093 71 : *user_dn = dn;
1094 : }
1095 71 : return NT_STATUS_OK;
1096 : }
1097 :
1098 : /*
1099 : lsa_CreateTrustedDomainEx2
1100 : */
1101 134 : static NTSTATUS dcesrv_lsa_CreateTrustedDomain_base(struct dcesrv_call_state *dce_call,
1102 : TALLOC_CTX *mem_ctx,
1103 : struct lsa_CreateTrustedDomainEx2 *r,
1104 : int op,
1105 : struct lsa_TrustDomainInfoAuthInfo *unencrypted_auth_info)
1106 : {
1107 0 : struct dcesrv_handle *policy_handle;
1108 0 : struct lsa_policy_state *policy_state;
1109 0 : struct lsa_trusted_domain_state *trusted_domain_state;
1110 0 : struct dcesrv_handle *handle;
1111 0 : struct ldb_message **msgs, *msg;
1112 134 : const char *attrs[] = {
1113 : NULL
1114 : };
1115 0 : const char *netbios_name;
1116 0 : const char *dns_name;
1117 0 : DATA_BLOB trustAuthIncoming, trustAuthOutgoing, auth_blob;
1118 0 : struct trustDomainPasswords auth_struct;
1119 0 : int ret;
1120 0 : NTSTATUS nt_status;
1121 0 : struct ldb_context *sam_ldb;
1122 134 : struct server_id *server_ids = NULL;
1123 134 : uint32_t num_server_ids = 0;
1124 0 : NTSTATUS status;
1125 0 : bool ok;
1126 134 : char *dns_encoded = NULL;
1127 134 : char *netbios_encoded = NULL;
1128 134 : char *sid_encoded = NULL;
1129 0 : struct imessaging_context *imsg_ctx =
1130 134 : dcesrv_imessaging_context(dce_call->conn);
1131 :
1132 134 : DCESRV_PULL_HANDLE(policy_handle, r->in.policy_handle, LSA_HANDLE_POLICY);
1133 134 : ZERO_STRUCTP(r->out.trustdom_handle);
1134 :
1135 134 : policy_state = policy_handle->data;
1136 134 : sam_ldb = policy_state->sam_ldb;
1137 :
1138 134 : netbios_name = r->in.info->netbios_name.string;
1139 134 : if (!netbios_name) {
1140 0 : return NT_STATUS_INVALID_PARAMETER;
1141 : }
1142 :
1143 134 : dns_name = r->in.info->domain_name.string;
1144 134 : if (dns_name == NULL) {
1145 0 : return NT_STATUS_INVALID_PARAMETER;
1146 : }
1147 :
1148 134 : if (r->in.info->sid == NULL) {
1149 0 : return NT_STATUS_INVALID_SID;
1150 : }
1151 :
1152 : /*
1153 : * We expect S-1-5-21-A-B-C, but we don't
1154 : * allow S-1-5-21-0-0-0 as this is used
1155 : * for claims and compound identities.
1156 : */
1157 134 : ok = dom_sid_is_valid_account_domain(r->in.info->sid);
1158 134 : if (!ok) {
1159 0 : return NT_STATUS_INVALID_PARAMETER;
1160 : }
1161 :
1162 134 : dns_encoded = ldb_binary_encode_string(mem_ctx, dns_name);
1163 134 : if (dns_encoded == NULL) {
1164 0 : return NT_STATUS_NO_MEMORY;
1165 : }
1166 134 : netbios_encoded = ldb_binary_encode_string(mem_ctx, netbios_name);
1167 134 : if (netbios_encoded == NULL) {
1168 0 : return NT_STATUS_NO_MEMORY;
1169 : }
1170 134 : sid_encoded = ldap_encode_ndr_dom_sid(mem_ctx, r->in.info->sid);
1171 134 : if (sid_encoded == NULL) {
1172 0 : return NT_STATUS_NO_MEMORY;
1173 : }
1174 :
1175 134 : trusted_domain_state = talloc_zero(mem_ctx, struct lsa_trusted_domain_state);
1176 134 : if (!trusted_domain_state) {
1177 0 : return NT_STATUS_NO_MEMORY;
1178 : }
1179 134 : trusted_domain_state->policy = policy_state;
1180 :
1181 134 : if (strcasecmp(netbios_name, "BUILTIN") == 0
1182 134 : || (strcasecmp(dns_name, "BUILTIN") == 0)
1183 134 : || (dom_sid_in_domain(policy_state->builtin_sid, r->in.info->sid))) {
1184 0 : return NT_STATUS_INVALID_PARAMETER;
1185 : }
1186 :
1187 134 : if (strcasecmp(netbios_name, policy_state->domain_name) == 0
1188 134 : || strcasecmp(netbios_name, policy_state->domain_dns) == 0
1189 134 : || strcasecmp(dns_name, policy_state->domain_dns) == 0
1190 134 : || strcasecmp(dns_name, policy_state->domain_name) == 0
1191 134 : || (dom_sid_equal(policy_state->domain_sid, r->in.info->sid))) {
1192 0 : return NT_STATUS_CURRENT_DOMAIN_NOT_ALLOWED;
1193 : }
1194 :
1195 : /* While this is a REF pointer, some of the functions that wrap this don't provide this */
1196 134 : if (op == NDR_LSA_CREATETRUSTEDDOMAIN) {
1197 : /* No secrets are created at this time, for this function */
1198 36 : auth_struct.outgoing.count = 0;
1199 36 : auth_struct.incoming.count = 0;
1200 98 : } else if (op == NDR_LSA_CREATETRUSTEDDOMAINEX2) {
1201 62 : auth_blob = data_blob_const(r->in.auth_info_internal->auth_blob.data,
1202 62 : r->in.auth_info_internal->auth_blob.size);
1203 62 : nt_status = get_trustdom_auth_blob(dce_call, mem_ctx,
1204 : &auth_blob, &auth_struct);
1205 62 : if (!NT_STATUS_IS_OK(nt_status)) {
1206 0 : return nt_status;
1207 : }
1208 36 : } else if (op == NDR_LSA_CREATETRUSTEDDOMAINEX) {
1209 :
1210 36 : if (unencrypted_auth_info->incoming_count > 1) {
1211 0 : return NT_STATUS_INVALID_PARAMETER;
1212 : }
1213 :
1214 : /* more investigation required here, do not create secrets for
1215 : * now */
1216 36 : auth_struct.outgoing.count = 0;
1217 36 : auth_struct.incoming.count = 0;
1218 : } else {
1219 0 : return NT_STATUS_INVALID_PARAMETER;
1220 : }
1221 :
1222 134 : if (auth_struct.incoming.count) {
1223 59 : nt_status = get_trustauth_inout_blob(dce_call, mem_ctx,
1224 : &auth_struct.incoming,
1225 : &trustAuthIncoming);
1226 59 : if (!NT_STATUS_IS_OK(nt_status)) {
1227 0 : return nt_status;
1228 : }
1229 : } else {
1230 75 : trustAuthIncoming = data_blob(NULL, 0);
1231 : }
1232 :
1233 134 : if (auth_struct.outgoing.count) {
1234 59 : nt_status = get_trustauth_inout_blob(dce_call, mem_ctx,
1235 : &auth_struct.outgoing,
1236 : &trustAuthOutgoing);
1237 59 : if (!NT_STATUS_IS_OK(nt_status)) {
1238 0 : return nt_status;
1239 : }
1240 : } else {
1241 75 : trustAuthOutgoing = data_blob(NULL, 0);
1242 : }
1243 :
1244 134 : ret = ldb_transaction_start(sam_ldb);
1245 134 : if (ret != LDB_SUCCESS) {
1246 0 : return NT_STATUS_INTERNAL_DB_CORRUPTION;
1247 : }
1248 :
1249 : /* search for the trusted_domain record */
1250 134 : ret = gendb_search(sam_ldb,
1251 : mem_ctx, policy_state->system_dn, &msgs, attrs,
1252 : "(&(objectClass=trustedDomain)(|"
1253 : "(flatname=%s)(trustPartner=%s)"
1254 : "(flatname=%s)(trustPartner=%s)"
1255 : "(securityIdentifier=%s)))",
1256 : dns_encoded, dns_encoded,
1257 : netbios_encoded, netbios_encoded,
1258 : sid_encoded);
1259 134 : if (ret > 0) {
1260 0 : ldb_transaction_cancel(sam_ldb);
1261 0 : return NT_STATUS_OBJECT_NAME_COLLISION;
1262 : }
1263 134 : if (ret < 0) {
1264 0 : ldb_transaction_cancel(sam_ldb);
1265 0 : return NT_STATUS_INTERNAL_DB_CORRUPTION;
1266 : }
1267 :
1268 134 : msg = ldb_msg_new(mem_ctx);
1269 134 : if (msg == NULL) {
1270 0 : return NT_STATUS_NO_MEMORY;
1271 : }
1272 :
1273 134 : msg->dn = ldb_dn_copy(mem_ctx, policy_state->system_dn);
1274 134 : if ( ! ldb_dn_add_child_fmt(msg->dn, "cn=%s", dns_name)) {
1275 0 : ldb_transaction_cancel(sam_ldb);
1276 0 : return NT_STATUS_NO_MEMORY;
1277 : }
1278 :
1279 134 : ret = ldb_msg_add_string(msg, "objectClass", "trustedDomain");
1280 134 : if (ret != LDB_SUCCESS) {
1281 0 : ldb_transaction_cancel(sam_ldb);
1282 0 : return NT_STATUS_NO_MEMORY;;
1283 : }
1284 :
1285 134 : ret = ldb_msg_add_string(msg, "flatname", netbios_name);
1286 134 : if (ret != LDB_SUCCESS) {
1287 0 : ldb_transaction_cancel(sam_ldb);
1288 0 : return NT_STATUS_NO_MEMORY;
1289 : }
1290 :
1291 134 : ret = ldb_msg_add_string(msg, "trustPartner", dns_name);
1292 134 : if (ret != LDB_SUCCESS) {
1293 0 : ldb_transaction_cancel(sam_ldb);
1294 0 : return NT_STATUS_NO_MEMORY;;
1295 : }
1296 :
1297 134 : ret = samdb_msg_add_dom_sid(sam_ldb, mem_ctx, msg, "securityIdentifier",
1298 134 : r->in.info->sid);
1299 134 : if (ret != LDB_SUCCESS) {
1300 0 : ldb_transaction_cancel(sam_ldb);
1301 0 : return NT_STATUS_NO_MEMORY;;
1302 : }
1303 :
1304 134 : ret = samdb_msg_add_int(sam_ldb, mem_ctx, msg, "trustType", r->in.info->trust_type);
1305 134 : if (ret != LDB_SUCCESS) {
1306 0 : ldb_transaction_cancel(sam_ldb);
1307 0 : return NT_STATUS_NO_MEMORY;;
1308 : }
1309 :
1310 134 : ret = samdb_msg_add_int(sam_ldb, mem_ctx, msg, "trustAttributes", r->in.info->trust_attributes);
1311 134 : if (ret != LDB_SUCCESS) {
1312 0 : ldb_transaction_cancel(sam_ldb);
1313 0 : return NT_STATUS_NO_MEMORY;;
1314 : }
1315 :
1316 134 : ret = samdb_msg_add_int(sam_ldb, mem_ctx, msg, "trustDirection", r->in.info->trust_direction);
1317 134 : if (ret != LDB_SUCCESS) {
1318 0 : ldb_transaction_cancel(sam_ldb);
1319 0 : return NT_STATUS_NO_MEMORY;;
1320 : }
1321 :
1322 134 : if (trustAuthIncoming.data) {
1323 59 : ret = ldb_msg_add_value(msg, "trustAuthIncoming", &trustAuthIncoming, NULL);
1324 59 : if (ret != LDB_SUCCESS) {
1325 0 : ldb_transaction_cancel(sam_ldb);
1326 0 : return NT_STATUS_NO_MEMORY;
1327 : }
1328 : }
1329 134 : if (trustAuthOutgoing.data) {
1330 59 : ret = ldb_msg_add_value(msg, "trustAuthOutgoing", &trustAuthOutgoing, NULL);
1331 59 : if (ret != LDB_SUCCESS) {
1332 0 : ldb_transaction_cancel(sam_ldb);
1333 0 : return NT_STATUS_NO_MEMORY;
1334 : }
1335 : }
1336 :
1337 134 : trusted_domain_state->trusted_domain_dn = talloc_reference(trusted_domain_state, msg->dn);
1338 :
1339 : /* create the trusted_domain */
1340 134 : ret = ldb_add(sam_ldb, msg);
1341 134 : switch (ret) {
1342 134 : case LDB_SUCCESS:
1343 134 : break;
1344 0 : case LDB_ERR_ENTRY_ALREADY_EXISTS:
1345 0 : ldb_transaction_cancel(sam_ldb);
1346 0 : DEBUG(0,("Failed to create trusted domain record %s: %s\n",
1347 : ldb_dn_get_linearized(msg->dn),
1348 : ldb_errstring(sam_ldb)));
1349 0 : return NT_STATUS_DOMAIN_EXISTS;
1350 0 : case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
1351 0 : ldb_transaction_cancel(sam_ldb);
1352 0 : DEBUG(0,("Failed to create trusted domain record %s: %s\n",
1353 : ldb_dn_get_linearized(msg->dn),
1354 : ldb_errstring(sam_ldb)));
1355 0 : return NT_STATUS_ACCESS_DENIED;
1356 0 : default:
1357 0 : ldb_transaction_cancel(sam_ldb);
1358 0 : DEBUG(0,("Failed to create user record %s: %s\n",
1359 : ldb_dn_get_linearized(msg->dn),
1360 : ldb_errstring(sam_ldb)));
1361 0 : return NT_STATUS_INTERNAL_DB_CORRUPTION;
1362 : }
1363 :
1364 134 : if (r->in.info->trust_direction & LSA_TRUST_DIRECTION_INBOUND) {
1365 0 : struct ldb_dn *user_dn;
1366 : /* Inbound trusts must also create a cn=users object to match */
1367 71 : nt_status = add_trust_user(mem_ctx, sam_ldb,
1368 : policy_state->domain_dn,
1369 : netbios_name,
1370 : &auth_struct.incoming,
1371 : &user_dn);
1372 71 : if (!NT_STATUS_IS_OK(nt_status)) {
1373 0 : ldb_transaction_cancel(sam_ldb);
1374 0 : return nt_status;
1375 : }
1376 :
1377 : /* save the trust user dn */
1378 0 : trusted_domain_state->trusted_domain_user_dn
1379 71 : = talloc_steal(trusted_domain_state, user_dn);
1380 : }
1381 :
1382 134 : ret = ldb_transaction_commit(sam_ldb);
1383 134 : if (ret != LDB_SUCCESS) {
1384 0 : return NT_STATUS_INTERNAL_DB_CORRUPTION;
1385 : }
1386 :
1387 : /*
1388 : * Notify winbindd that we have a new trust
1389 : */
1390 134 : status = irpc_servers_byname(imsg_ctx,
1391 : mem_ctx,
1392 : "winbind_server",
1393 : &num_server_ids,
1394 : &server_ids);
1395 134 : if (NT_STATUS_IS_OK(status) && num_server_ids >= 1) {
1396 134 : imessaging_send(imsg_ctx,
1397 : server_ids[0],
1398 : MSG_WINBIND_RELOAD_TRUSTED_DOMAINS,
1399 : NULL);
1400 : }
1401 134 : TALLOC_FREE(server_ids);
1402 :
1403 134 : handle = dcesrv_handle_create(dce_call, LSA_HANDLE_TRUSTED_DOMAIN);
1404 134 : if (!handle) {
1405 0 : return NT_STATUS_NO_MEMORY;
1406 : }
1407 :
1408 134 : handle->data = talloc_steal(handle, trusted_domain_state);
1409 :
1410 134 : trusted_domain_state->access_mask = r->in.access_mask;
1411 134 : trusted_domain_state->policy = talloc_reference(trusted_domain_state, policy_state);
1412 :
1413 134 : *r->out.trustdom_handle = handle->wire_handle;
1414 :
1415 134 : return NT_STATUS_OK;
1416 : }
1417 :
1418 : /*
1419 : lsa_CreateTrustedDomainEx2
1420 : */
1421 62 : static NTSTATUS dcesrv_lsa_CreateTrustedDomainEx2(struct dcesrv_call_state *dce_call,
1422 : TALLOC_CTX *mem_ctx,
1423 : struct lsa_CreateTrustedDomainEx2 *r)
1424 : {
1425 62 : return dcesrv_lsa_CreateTrustedDomain_base(dce_call, mem_ctx, r, NDR_LSA_CREATETRUSTEDDOMAINEX2, NULL);
1426 : }
1427 : /*
1428 : lsa_CreateTrustedDomainEx
1429 : */
1430 36 : static NTSTATUS dcesrv_lsa_CreateTrustedDomainEx(struct dcesrv_call_state *dce_call,
1431 : TALLOC_CTX *mem_ctx,
1432 : struct lsa_CreateTrustedDomainEx *r)
1433 : {
1434 36 : struct lsa_CreateTrustedDomainEx2 r2 = {};
1435 :
1436 36 : r2.in.policy_handle = r->in.policy_handle;
1437 36 : r2.in.info = r->in.info;
1438 36 : r2.out.trustdom_handle = r->out.trustdom_handle;
1439 36 : return dcesrv_lsa_CreateTrustedDomain_base(dce_call, mem_ctx, &r2, NDR_LSA_CREATETRUSTEDDOMAINEX, r->in.auth_info);
1440 : }
1441 :
1442 : /*
1443 : lsa_CreateTrustedDomain
1444 : */
1445 36 : static NTSTATUS dcesrv_lsa_CreateTrustedDomain(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1446 : struct lsa_CreateTrustedDomain *r)
1447 : {
1448 36 : struct lsa_CreateTrustedDomainEx2 r2 = {};
1449 :
1450 36 : r2.in.policy_handle = r->in.policy_handle;
1451 36 : r2.in.info = talloc(mem_ctx, struct lsa_TrustDomainInfoInfoEx);
1452 36 : if (!r2.in.info) {
1453 0 : return NT_STATUS_NO_MEMORY;
1454 : }
1455 :
1456 36 : r2.in.info->domain_name = r->in.info->name;
1457 36 : r2.in.info->netbios_name = r->in.info->name;
1458 36 : r2.in.info->sid = r->in.info->sid;
1459 36 : r2.in.info->trust_direction = LSA_TRUST_DIRECTION_OUTBOUND;
1460 36 : r2.in.info->trust_type = LSA_TRUST_TYPE_DOWNLEVEL;
1461 36 : r2.in.info->trust_attributes = 0;
1462 :
1463 36 : r2.in.access_mask = r->in.access_mask;
1464 36 : r2.out.trustdom_handle = r->out.trustdom_handle;
1465 :
1466 36 : return dcesrv_lsa_CreateTrustedDomain_base(dce_call, mem_ctx, &r2, NDR_LSA_CREATETRUSTEDDOMAIN, NULL);
1467 : }
1468 :
1469 3424 : static NTSTATUS dcesrv_lsa_OpenTrustedDomain_common(
1470 : struct dcesrv_call_state *dce_call,
1471 : TALLOC_CTX *tmp_mem,
1472 : struct lsa_policy_state *policy_state,
1473 : const char *filter,
1474 : uint32_t access_mask,
1475 : struct dcesrv_handle **_handle)
1476 : {
1477 0 : struct lsa_trusted_domain_state *trusted_domain_state;
1478 0 : struct dcesrv_handle *handle;
1479 0 : struct ldb_message **msgs;
1480 3424 : const char *attrs[] = {
1481 : "trustDirection",
1482 : "flatname",
1483 : NULL
1484 : };
1485 0 : uint32_t direction;
1486 0 : int ret;
1487 :
1488 : /* TODO: perform access checks */
1489 :
1490 : /* search for the trusted_domain record */
1491 3424 : ret = gendb_search(policy_state->sam_ldb, tmp_mem,
1492 : policy_state->system_dn,
1493 : &msgs, attrs, "%s", filter);
1494 3424 : if (ret == 0) {
1495 53 : return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1496 : }
1497 :
1498 3371 : if (ret != 1) {
1499 0 : DEBUG(0,("Found %d records matching %s under %s\n", ret,
1500 : filter,
1501 : ldb_dn_get_linearized(policy_state->system_dn)));
1502 0 : return NT_STATUS_INTERNAL_DB_CORRUPTION;
1503 : }
1504 :
1505 3371 : trusted_domain_state = talloc_zero(tmp_mem,
1506 : struct lsa_trusted_domain_state);
1507 3371 : if (!trusted_domain_state) {
1508 0 : return NT_STATUS_NO_MEMORY;
1509 : }
1510 3371 : trusted_domain_state->policy = policy_state;
1511 :
1512 3371 : trusted_domain_state->trusted_domain_dn =
1513 3371 : talloc_steal(trusted_domain_state, msgs[0]->dn);
1514 :
1515 3371 : direction = ldb_msg_find_attr_as_int(msgs[0], "trustDirection", 0);
1516 3371 : if (direction & LSA_TRUST_DIRECTION_INBOUND) {
1517 1612 : const char *flatname = ldb_msg_find_attr_as_string(msgs[0],
1518 : "flatname", NULL);
1519 :
1520 : /* search for the trusted_domain account */
1521 1612 : ret = gendb_search(policy_state->sam_ldb, tmp_mem,
1522 : policy_state->domain_dn,
1523 : &msgs, attrs,
1524 : "(&(samaccountname=%s$)(objectclass=user)"
1525 : "(userAccountControl:%s:=%u))",
1526 : flatname,
1527 : LDB_OID_COMPARATOR_AND,
1528 : UF_INTERDOMAIN_TRUST_ACCOUNT);
1529 1612 : if (ret == 1) {
1530 1612 : trusted_domain_state->trusted_domain_user_dn =
1531 1612 : talloc_steal(trusted_domain_state, msgs[0]->dn);
1532 : }
1533 : }
1534 :
1535 3371 : handle = dcesrv_handle_create(dce_call, LSA_HANDLE_TRUSTED_DOMAIN);
1536 3371 : if (!handle) {
1537 0 : return NT_STATUS_NO_MEMORY;
1538 : }
1539 :
1540 3371 : handle->data = talloc_steal(handle, trusted_domain_state);
1541 :
1542 3371 : trusted_domain_state->access_mask = access_mask;
1543 3371 : trusted_domain_state->policy = talloc_reference(trusted_domain_state,
1544 : policy_state);
1545 :
1546 3371 : *_handle = handle;
1547 :
1548 3371 : return NT_STATUS_OK;
1549 : }
1550 :
1551 : /*
1552 : lsa_OpenTrustedDomain
1553 : */
1554 1625 : static NTSTATUS dcesrv_lsa_OpenTrustedDomain(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1555 : struct lsa_OpenTrustedDomain *r)
1556 : {
1557 0 : struct dcesrv_handle *policy_handle;
1558 0 : struct lsa_policy_state *policy_state;
1559 0 : struct dcesrv_handle *handle;
1560 0 : const char *sid_string;
1561 0 : char *filter;
1562 0 : NTSTATUS status;
1563 :
1564 1625 : DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
1565 1625 : ZERO_STRUCTP(r->out.trustdom_handle);
1566 1625 : policy_state = policy_handle->data;
1567 :
1568 1625 : sid_string = dom_sid_string(mem_ctx, r->in.sid);
1569 1625 : if (!sid_string) {
1570 0 : return NT_STATUS_NO_MEMORY;
1571 : }
1572 :
1573 1625 : filter = talloc_asprintf(mem_ctx,
1574 : "(&(securityIdentifier=%s)"
1575 : "(objectclass=trustedDomain))",
1576 : sid_string);
1577 1625 : if (filter == NULL) {
1578 0 : return NT_STATUS_NO_MEMORY;
1579 : }
1580 :
1581 1625 : status = dcesrv_lsa_OpenTrustedDomain_common(dce_call, mem_ctx,
1582 : policy_state,
1583 : filter,
1584 : r->in.access_mask,
1585 : &handle);
1586 1625 : if (!NT_STATUS_IS_OK(status)) {
1587 1 : return status;
1588 : }
1589 :
1590 1624 : *r->out.trustdom_handle = handle->wire_handle;
1591 :
1592 1624 : return NT_STATUS_OK;
1593 : }
1594 :
1595 :
1596 : /*
1597 : lsa_OpenTrustedDomainByName
1598 : */
1599 1799 : static NTSTATUS dcesrv_lsa_OpenTrustedDomainByName(struct dcesrv_call_state *dce_call,
1600 : TALLOC_CTX *mem_ctx,
1601 : struct lsa_OpenTrustedDomainByName *r)
1602 : {
1603 0 : struct dcesrv_handle *policy_handle;
1604 0 : struct lsa_policy_state *policy_state;
1605 0 : struct dcesrv_handle *handle;
1606 0 : char *td_name;
1607 0 : char *filter;
1608 0 : NTSTATUS status;
1609 :
1610 1799 : DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
1611 1799 : ZERO_STRUCTP(r->out.trustdom_handle);
1612 1799 : policy_state = policy_handle->data;
1613 :
1614 1799 : if (!r->in.name.string) {
1615 0 : return NT_STATUS_INVALID_PARAMETER;
1616 : }
1617 :
1618 : /* search for the trusted_domain record */
1619 1799 : td_name = ldb_binary_encode_string(mem_ctx, r->in.name.string);
1620 1799 : if (td_name == NULL) {
1621 0 : return NT_STATUS_NO_MEMORY;
1622 : }
1623 :
1624 1799 : filter = talloc_asprintf(mem_ctx,
1625 : "(&(|(flatname=%s)(cn=%s)(trustPartner=%s))"
1626 : "(objectclass=trustedDomain))",
1627 : td_name, td_name, td_name);
1628 1799 : if (filter == NULL) {
1629 0 : return NT_STATUS_NO_MEMORY;
1630 : }
1631 :
1632 1799 : status = dcesrv_lsa_OpenTrustedDomain_common(dce_call, mem_ctx,
1633 : policy_state,
1634 : filter,
1635 : r->in.access_mask,
1636 : &handle);
1637 1799 : if (!NT_STATUS_IS_OK(status)) {
1638 52 : return status;
1639 : }
1640 :
1641 1747 : *r->out.trustdom_handle = handle->wire_handle;
1642 :
1643 1747 : return NT_STATUS_OK;
1644 : }
1645 :
1646 :
1647 :
1648 : /*
1649 : lsa_SetTrustedDomainInfo
1650 : */
1651 0 : static NTSTATUS dcesrv_lsa_SetTrustedDomainInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1652 : struct lsa_SetTrustedDomainInfo *r)
1653 : {
1654 0 : DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1655 : }
1656 :
1657 :
1658 :
1659 : /* parameters 4 to 6 are optional if the dn is a dn of a TDO object,
1660 : * otherwise at least one must be provided */
1661 46 : static NTSTATUS get_tdo(struct ldb_context *sam, TALLOC_CTX *mem_ctx,
1662 : struct ldb_dn *basedn, const char *dns_domain,
1663 : const char *netbios, struct dom_sid2 *sid,
1664 : struct ldb_message ***msgs)
1665 : {
1666 46 : const char *attrs[] = { "flatname", "trustPartner",
1667 : "securityIdentifier", "trustDirection",
1668 : "trustType", "trustAttributes",
1669 : "trustPosixOffset",
1670 : "msDs-supportedEncryptionTypes",
1671 : "msDS-TrustForestTrustInfo",
1672 : NULL
1673 : };
1674 46 : char *dns = NULL;
1675 46 : char *nbn = NULL;
1676 0 : char *filter;
1677 0 : int ret;
1678 :
1679 :
1680 46 : if (dns_domain || netbios || sid) {
1681 24 : filter = talloc_strdup(mem_ctx,
1682 : "(&(objectclass=trustedDomain)(|");
1683 : } else {
1684 22 : filter = talloc_strdup(mem_ctx,
1685 : "(objectclass=trustedDomain)");
1686 : }
1687 :
1688 46 : if (dns_domain) {
1689 24 : dns = ldb_binary_encode_string(mem_ctx, dns_domain);
1690 24 : if (!dns) {
1691 0 : return NT_STATUS_NO_MEMORY;
1692 : }
1693 24 : talloc_asprintf_addbuf(&filter, "(trustPartner=%s)", dns);
1694 : }
1695 46 : if (netbios) {
1696 24 : nbn = ldb_binary_encode_string(mem_ctx, netbios);
1697 24 : if (!nbn) {
1698 0 : return NT_STATUS_NO_MEMORY;
1699 : }
1700 24 : talloc_asprintf_addbuf(&filter, "(flatname=%s)", nbn);
1701 : }
1702 46 : if (sid) {
1703 0 : struct dom_sid_buf buf;
1704 6 : char *sidstr = dom_sid_str_buf(sid, &buf);
1705 6 : talloc_asprintf_addbuf(
1706 : &filter, "(securityIdentifier=%s)", sidstr);
1707 : }
1708 46 : if (dns_domain || netbios || sid) {
1709 24 : talloc_asprintf_addbuf(&filter, "))");
1710 : }
1711 46 : if (filter == NULL) {
1712 0 : return NT_STATUS_NO_MEMORY;
1713 : }
1714 :
1715 46 : ret = gendb_search(sam, mem_ctx, basedn, msgs, attrs, "%s", filter);
1716 46 : if (ret == 0) {
1717 0 : return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1718 : }
1719 :
1720 46 : if (ret != 1) {
1721 0 : return NT_STATUS_OBJECT_NAME_COLLISION;
1722 : }
1723 :
1724 46 : return NT_STATUS_OK;
1725 : }
1726 :
1727 43 : static NTSTATUS update_uint32_t_value(TALLOC_CTX *mem_ctx,
1728 : struct ldb_context *sam_ldb,
1729 : struct ldb_message *orig,
1730 : struct ldb_message *dest,
1731 : const char *attribute,
1732 : uint32_t value,
1733 : uint32_t *orig_value)
1734 : {
1735 0 : const struct ldb_val *orig_val;
1736 43 : uint32_t orig_uint = 0;
1737 43 : unsigned int flags = 0;
1738 0 : int ret;
1739 43 : int error = 0;
1740 :
1741 43 : orig_val = ldb_msg_find_ldb_val(orig, attribute);
1742 43 : if (!orig_val || !orig_val->data) {
1743 : /* add new attribute */
1744 28 : flags = LDB_FLAG_MOD_ADD;
1745 :
1746 : } else {
1747 15 : orig_uint = smb_strtoul((const char *)orig_val->data,
1748 : NULL,
1749 : 0,
1750 : &error,
1751 : SMB_STR_STANDARD);
1752 15 : if (error != 0 || orig_uint != value) {
1753 : /* replace also if can't get value */
1754 0 : flags = LDB_FLAG_MOD_REPLACE;
1755 : }
1756 : }
1757 :
1758 43 : if (flags == 0) {
1759 : /* stored value is identical, nothing to change */
1760 15 : goto done;
1761 : }
1762 :
1763 28 : ret = samdb_msg_append_uint(sam_ldb, dest, dest, attribute, value, flags);
1764 28 : if (ret != LDB_SUCCESS) {
1765 0 : return NT_STATUS_NO_MEMORY;
1766 : }
1767 :
1768 28 : done:
1769 43 : if (orig_value) {
1770 12 : *orig_value = orig_uint;
1771 : }
1772 43 : return NT_STATUS_OK;
1773 : }
1774 :
1775 0 : static NTSTATUS update_trust_user(TALLOC_CTX *mem_ctx,
1776 : struct ldb_context *sam_ldb,
1777 : struct ldb_dn *base_dn,
1778 : bool delete_user,
1779 : const char *netbios_name,
1780 : struct trustAuthInOutBlob *in)
1781 : {
1782 0 : const char *attrs[] = { "userAccountControl", NULL };
1783 0 : struct ldb_message **msgs;
1784 0 : struct ldb_message *msg;
1785 0 : uint32_t uac;
1786 0 : uint32_t i;
1787 0 : int ret;
1788 :
1789 0 : ret = gendb_search(sam_ldb, mem_ctx,
1790 : base_dn, &msgs, attrs,
1791 : "samAccountName=%s$", netbios_name);
1792 0 : if (ret > 1) {
1793 0 : return NT_STATUS_INTERNAL_DB_CORRUPTION;
1794 : }
1795 :
1796 0 : if (ret == 0) {
1797 0 : if (delete_user) {
1798 0 : return NT_STATUS_OK;
1799 : }
1800 :
1801 : /* ok no existing user, add it from scratch */
1802 0 : return add_trust_user(mem_ctx, sam_ldb, base_dn,
1803 : netbios_name, in, NULL);
1804 : }
1805 :
1806 : /* check user is what we are looking for */
1807 0 : uac = ldb_msg_find_attr_as_uint(msgs[0],
1808 : "userAccountControl", 0);
1809 0 : if (!(uac & UF_INTERDOMAIN_TRUST_ACCOUNT)) {
1810 0 : return NT_STATUS_OBJECT_NAME_COLLISION;
1811 : }
1812 :
1813 0 : if (delete_user) {
1814 0 : ret = ldb_delete(sam_ldb, msgs[0]->dn);
1815 0 : switch (ret) {
1816 0 : case LDB_SUCCESS:
1817 0 : return NT_STATUS_OK;
1818 0 : case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
1819 0 : return NT_STATUS_ACCESS_DENIED;
1820 0 : default:
1821 0 : return NT_STATUS_INTERNAL_DB_CORRUPTION;
1822 : }
1823 : }
1824 :
1825 : /* entry exists, just modify secret if any */
1826 0 : if (in == NULL || in->count == 0) {
1827 0 : return NT_STATUS_OK;
1828 : }
1829 :
1830 0 : msg = ldb_msg_new(mem_ctx);
1831 0 : if (!msg) {
1832 0 : return NT_STATUS_NO_MEMORY;
1833 : }
1834 0 : msg->dn = msgs[0]->dn;
1835 :
1836 0 : for (i = 0; i < in->count; i++) {
1837 0 : const char *attribute;
1838 0 : struct ldb_val v;
1839 0 : switch (in->current.array[i].AuthType) {
1840 0 : case TRUST_AUTH_TYPE_NT4OWF:
1841 0 : attribute = "unicodePwd";
1842 0 : v.data = (uint8_t *)&in->current.array[i].AuthInfo.nt4owf.password;
1843 0 : v.length = 16;
1844 0 : break;
1845 0 : case TRUST_AUTH_TYPE_CLEAR:
1846 0 : attribute = "clearTextPassword";
1847 0 : v.data = in->current.array[i].AuthInfo.clear.password;
1848 0 : v.length = in->current.array[i].AuthInfo.clear.size;
1849 0 : break;
1850 0 : default:
1851 0 : continue;
1852 : }
1853 :
1854 0 : ret = ldb_msg_append_value(msg, attribute, &v, LDB_FLAG_MOD_REPLACE);
1855 0 : if (ret != LDB_SUCCESS) {
1856 0 : return NT_STATUS_NO_MEMORY;
1857 : }
1858 : }
1859 :
1860 : /* create the trusted_domain user account */
1861 0 : ret = ldb_modify(sam_ldb, msg);
1862 0 : if (ret != LDB_SUCCESS) {
1863 0 : DEBUG(0,("Failed to create user record %s: %s\n",
1864 : ldb_dn_get_linearized(msg->dn),
1865 : ldb_errstring(sam_ldb)));
1866 :
1867 0 : switch (ret) {
1868 0 : case LDB_ERR_ENTRY_ALREADY_EXISTS:
1869 0 : return NT_STATUS_DOMAIN_EXISTS;
1870 0 : case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
1871 0 : return NT_STATUS_ACCESS_DENIED;
1872 0 : default:
1873 0 : return NT_STATUS_INTERNAL_DB_CORRUPTION;
1874 : }
1875 : }
1876 :
1877 0 : return NT_STATUS_OK;
1878 : }
1879 :
1880 :
1881 40 : static NTSTATUS setInfoTrustedDomain_base(struct dcesrv_call_state *dce_call,
1882 : struct lsa_policy_state *p_state,
1883 : TALLOC_CTX *mem_ctx,
1884 : struct ldb_message *dom_msg,
1885 : enum lsa_TrustDomInfoEnum level,
1886 : union lsa_TrustedDomainInfo *info)
1887 : {
1888 40 : uint32_t *posix_offset = NULL;
1889 40 : struct lsa_TrustDomainInfoInfoEx *info_ex = NULL;
1890 40 : struct lsa_TrustDomainInfoAuthInfo *auth_info = NULL;
1891 40 : struct lsa_TrustDomainInfoAuthInfoInternal *auth_info_int = NULL;
1892 40 : uint32_t *enc_types = NULL;
1893 0 : DATA_BLOB trustAuthIncoming, trustAuthOutgoing, auth_blob;
1894 0 : struct trustDomainPasswords auth_struct;
1895 40 : struct trustAuthInOutBlob *current_passwords = NULL;
1896 0 : NTSTATUS nt_status;
1897 0 : struct ldb_message **msgs;
1898 0 : struct ldb_message *msg;
1899 40 : bool add_outgoing = false;
1900 40 : bool add_incoming = false;
1901 40 : bool del_outgoing = false;
1902 40 : bool del_incoming = false;
1903 40 : bool del_forest_info = false;
1904 40 : bool in_transaction = false;
1905 0 : int ret;
1906 0 : bool am_rodc;
1907 :
1908 40 : switch (level) {
1909 3 : case LSA_TRUSTED_DOMAIN_INFO_POSIX_OFFSET:
1910 3 : posix_offset = &info->posix_offset.posix_offset;
1911 3 : break;
1912 3 : case LSA_TRUSTED_DOMAIN_INFO_INFO_EX:
1913 3 : info_ex = &info->info_ex;
1914 3 : break;
1915 0 : case LSA_TRUSTED_DOMAIN_INFO_AUTH_INFO:
1916 0 : auth_info = &info->auth_info;
1917 0 : break;
1918 3 : case LSA_TRUSTED_DOMAIN_INFO_FULL_INFO:
1919 3 : posix_offset = &info->full_info.posix_offset.posix_offset;
1920 3 : info_ex = &info->full_info.info_ex;
1921 3 : auth_info = &info->full_info.auth_info;
1922 3 : break;
1923 0 : case LSA_TRUSTED_DOMAIN_INFO_AUTH_INFO_INTERNAL:
1924 0 : auth_info_int = &info->auth_info_internal;
1925 0 : break;
1926 0 : case LSA_TRUSTED_DOMAIN_INFO_FULL_INFO_INTERNAL:
1927 0 : posix_offset = &info->full_info_internal.posix_offset.posix_offset;
1928 0 : info_ex = &info->full_info_internal.info_ex;
1929 0 : auth_info_int = &info->full_info_internal.auth_info;
1930 0 : break;
1931 25 : case LSA_TRUSTED_DOMAIN_SUPPORTED_ENCRYPTION_TYPES:
1932 25 : enc_types = &info->enc_types.enc_types;
1933 25 : break;
1934 6 : default:
1935 6 : return NT_STATUS_INVALID_PARAMETER;
1936 : }
1937 :
1938 34 : if (auth_info) {
1939 3 : nt_status = auth_info_2_auth_blob(mem_ctx, auth_info,
1940 : &trustAuthIncoming,
1941 : &trustAuthOutgoing);
1942 3 : if (!NT_STATUS_IS_OK(nt_status)) {
1943 0 : return nt_status;
1944 : }
1945 3 : if (trustAuthIncoming.data) {
1946 : /* This does the decode of some of this twice, but it is easier that way */
1947 0 : nt_status = auth_info_2_trustauth_inout(mem_ctx,
1948 : auth_info->incoming_count,
1949 : auth_info->incoming_current_auth_info,
1950 : NULL,
1951 : ¤t_passwords);
1952 0 : if (!NT_STATUS_IS_OK(nt_status)) {
1953 0 : return nt_status;
1954 : }
1955 : }
1956 : }
1957 :
1958 : /* decode auth_info_int if set */
1959 34 : if (auth_info_int) {
1960 :
1961 : /* now decrypt blob */
1962 0 : auth_blob = data_blob_const(auth_info_int->auth_blob.data,
1963 0 : auth_info_int->auth_blob.size);
1964 :
1965 0 : nt_status = get_trustdom_auth_blob(dce_call, mem_ctx,
1966 : &auth_blob, &auth_struct);
1967 0 : if (!NT_STATUS_IS_OK(nt_status)) {
1968 0 : return nt_status;
1969 : }
1970 : }
1971 :
1972 34 : if (info_ex) {
1973 : /* verify data matches */
1974 6 : if (info_ex->trust_attributes &
1975 : LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE) {
1976 : /* TODO: check what behavior level we have */
1977 6 : if (strcasecmp_m(p_state->domain_dns,
1978 : p_state->forest_dns) != 0) {
1979 0 : return NT_STATUS_INVALID_DOMAIN_STATE;
1980 : }
1981 : }
1982 :
1983 6 : ret = samdb_rodc(p_state->sam_ldb, &am_rodc);
1984 6 : if (ret == LDB_SUCCESS && am_rodc) {
1985 0 : return NT_STATUS_NO_SUCH_DOMAIN;
1986 : }
1987 :
1988 : /* verify only one object matches the dns/netbios/sid
1989 : * triplet and that this is the one we already have */
1990 6 : nt_status = get_tdo(p_state->sam_ldb, mem_ctx,
1991 : p_state->system_dn,
1992 : info_ex->domain_name.string,
1993 : info_ex->netbios_name.string,
1994 : info_ex->sid, &msgs);
1995 6 : if (!NT_STATUS_IS_OK(nt_status)) {
1996 0 : return nt_status;
1997 : }
1998 6 : if (ldb_dn_compare(dom_msg->dn, msgs[0]->dn) != 0) {
1999 0 : return NT_STATUS_OBJECT_NAME_COLLISION;
2000 : }
2001 6 : talloc_free(msgs);
2002 : }
2003 :
2004 : /* TODO: should we fetch previous values from the existing entry
2005 : * and append them ? */
2006 34 : if (auth_info_int && auth_struct.incoming.count) {
2007 0 : nt_status = get_trustauth_inout_blob(dce_call, mem_ctx,
2008 : &auth_struct.incoming,
2009 : &trustAuthIncoming);
2010 0 : if (!NT_STATUS_IS_OK(nt_status)) {
2011 0 : return nt_status;
2012 : }
2013 :
2014 0 : current_passwords = &auth_struct.incoming;
2015 :
2016 : } else {
2017 34 : trustAuthIncoming = data_blob(NULL, 0);
2018 : }
2019 :
2020 34 : if (auth_info_int && auth_struct.outgoing.count) {
2021 0 : nt_status = get_trustauth_inout_blob(dce_call, mem_ctx,
2022 : &auth_struct.outgoing,
2023 : &trustAuthOutgoing);
2024 0 : if (!NT_STATUS_IS_OK(nt_status)) {
2025 0 : return nt_status;
2026 : }
2027 : } else {
2028 34 : trustAuthOutgoing = data_blob(NULL, 0);
2029 : }
2030 :
2031 34 : msg = ldb_msg_new(mem_ctx);
2032 34 : if (msg == NULL) {
2033 0 : return NT_STATUS_NO_MEMORY;
2034 : }
2035 34 : msg->dn = dom_msg->dn;
2036 :
2037 34 : if (posix_offset) {
2038 6 : nt_status = update_uint32_t_value(mem_ctx, p_state->sam_ldb,
2039 : dom_msg, msg,
2040 : "trustPosixOffset",
2041 : *posix_offset, NULL);
2042 6 : if (!NT_STATUS_IS_OK(nt_status)) {
2043 0 : return nt_status;
2044 : }
2045 : }
2046 :
2047 34 : if (info_ex) {
2048 0 : uint32_t origattrs;
2049 0 : uint32_t changed_attrs;
2050 0 : uint32_t origdir;
2051 0 : int origtype;
2052 :
2053 6 : nt_status = update_uint32_t_value(mem_ctx, p_state->sam_ldb,
2054 : dom_msg, msg,
2055 : "trustDirection",
2056 : info_ex->trust_direction,
2057 : &origdir);
2058 6 : if (!NT_STATUS_IS_OK(nt_status)) {
2059 0 : return nt_status;
2060 : }
2061 :
2062 6 : if (info_ex->trust_direction & LSA_TRUST_DIRECTION_INBOUND) {
2063 6 : if (auth_info != NULL && trustAuthIncoming.length > 0) {
2064 0 : add_incoming = true;
2065 : }
2066 : }
2067 6 : if (info_ex->trust_direction & LSA_TRUST_DIRECTION_OUTBOUND) {
2068 6 : if (auth_info != NULL && trustAuthOutgoing.length > 0) {
2069 0 : add_outgoing = true;
2070 : }
2071 : }
2072 :
2073 6 : if ((origdir & LSA_TRUST_DIRECTION_INBOUND) &&
2074 6 : !(info_ex->trust_direction & LSA_TRUST_DIRECTION_INBOUND)) {
2075 0 : del_incoming = true;
2076 : }
2077 6 : if ((origdir & LSA_TRUST_DIRECTION_OUTBOUND) &&
2078 6 : !(info_ex->trust_direction & LSA_TRUST_DIRECTION_OUTBOUND)) {
2079 0 : del_outgoing = true;
2080 : }
2081 :
2082 6 : origtype = ldb_msg_find_attr_as_int(dom_msg, "trustType", -1);
2083 6 : if (origtype == -1 || origtype != info_ex->trust_type) {
2084 0 : DEBUG(1, ("Attempted to change trust type! "
2085 : "Operation not handled\n"));
2086 0 : return NT_STATUS_INVALID_PARAMETER;
2087 : }
2088 :
2089 6 : nt_status = update_uint32_t_value(mem_ctx, p_state->sam_ldb,
2090 : dom_msg, msg,
2091 : "trustAttributes",
2092 : info_ex->trust_attributes,
2093 : &origattrs);
2094 6 : if (!NT_STATUS_IS_OK(nt_status)) {
2095 0 : return nt_status;
2096 : }
2097 : /* TODO: check forestFunctionality from ldb opaque */
2098 : /* TODO: check what is set makes sense */
2099 :
2100 6 : changed_attrs = origattrs ^ info_ex->trust_attributes;
2101 6 : if (changed_attrs & ~LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE) {
2102 : /*
2103 : * For now we only allow
2104 : * LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE to be changed.
2105 : *
2106 : * TODO: we may need to support more attribute changes
2107 : */
2108 0 : DEBUG(1, ("Attempted to change trust attributes "
2109 : "(0x%08x != 0x%08x)! "
2110 : "Operation not handled yet...\n",
2111 : (unsigned)origattrs,
2112 : (unsigned)info_ex->trust_attributes));
2113 0 : return NT_STATUS_INVALID_PARAMETER;
2114 : }
2115 :
2116 6 : if (!(info_ex->trust_attributes &
2117 : LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE))
2118 : {
2119 0 : struct ldb_message_element *orig_forest_el = NULL;
2120 :
2121 0 : orig_forest_el = ldb_msg_find_element(dom_msg,
2122 : "msDS-TrustForestTrustInfo");
2123 0 : if (orig_forest_el != NULL) {
2124 0 : del_forest_info = true;
2125 : }
2126 : }
2127 : }
2128 :
2129 34 : if (enc_types) {
2130 25 : nt_status = update_uint32_t_value(mem_ctx, p_state->sam_ldb,
2131 : dom_msg, msg,
2132 : "msDS-SupportedEncryptionTypes",
2133 : *enc_types, NULL);
2134 25 : if (!NT_STATUS_IS_OK(nt_status)) {
2135 0 : return nt_status;
2136 : }
2137 : }
2138 :
2139 34 : if (add_incoming || del_incoming) {
2140 0 : if (add_incoming) {
2141 0 : ret = ldb_msg_append_value(msg, "trustAuthIncoming",
2142 : &trustAuthIncoming, LDB_FLAG_MOD_REPLACE);
2143 0 : if (ret != LDB_SUCCESS) {
2144 0 : return NT_STATUS_NO_MEMORY;
2145 : }
2146 : } else {
2147 0 : ret = ldb_msg_add_empty(msg, "trustAuthIncoming",
2148 : LDB_FLAG_MOD_REPLACE, NULL);
2149 0 : if (ret != LDB_SUCCESS) {
2150 0 : return NT_STATUS_NO_MEMORY;
2151 : }
2152 : }
2153 : }
2154 34 : if (add_outgoing || del_outgoing) {
2155 0 : if (add_outgoing) {
2156 0 : ret = ldb_msg_append_value(msg, "trustAuthOutgoing",
2157 : &trustAuthOutgoing, LDB_FLAG_MOD_REPLACE);
2158 0 : if (ret != LDB_SUCCESS) {
2159 0 : return NT_STATUS_NO_MEMORY;
2160 : }
2161 : } else {
2162 0 : ret = ldb_msg_add_empty(msg, "trustAuthOutgoing",
2163 : LDB_FLAG_MOD_REPLACE, NULL);
2164 0 : if (ret != LDB_SUCCESS) {
2165 0 : return NT_STATUS_NO_MEMORY;
2166 : }
2167 : }
2168 : }
2169 34 : if (del_forest_info) {
2170 0 : ret = ldb_msg_add_empty(msg, "msDS-TrustForestTrustInfo",
2171 : LDB_FLAG_MOD_REPLACE, NULL);
2172 0 : if (ret != LDB_SUCCESS) {
2173 0 : return NT_STATUS_NO_MEMORY;
2174 : }
2175 : }
2176 :
2177 : /* start transaction */
2178 34 : ret = ldb_transaction_start(p_state->sam_ldb);
2179 34 : if (ret != LDB_SUCCESS) {
2180 0 : return NT_STATUS_INTERNAL_DB_CORRUPTION;
2181 : }
2182 34 : in_transaction = true;
2183 :
2184 34 : if (msg->num_elements) {
2185 28 : ret = ldb_modify(p_state->sam_ldb, msg);
2186 28 : if (ret != LDB_SUCCESS) {
2187 0 : DEBUG(1,("Failed to modify trusted domain record %s: %s\n",
2188 : ldb_dn_get_linearized(msg->dn),
2189 : ldb_errstring(p_state->sam_ldb)));
2190 0 : nt_status = dsdb_ldb_err_to_ntstatus(ret);
2191 0 : goto done;
2192 : }
2193 : }
2194 :
2195 34 : if (add_incoming || del_incoming) {
2196 0 : const char *netbios_name;
2197 :
2198 0 : netbios_name = ldb_msg_find_attr_as_string(dom_msg,
2199 : "flatname", NULL);
2200 0 : if (!netbios_name) {
2201 0 : nt_status = NT_STATUS_INVALID_DOMAIN_STATE;
2202 0 : goto done;
2203 : }
2204 :
2205 : /* We use trustAuthIncoming.data to indicate that auth_struct.incoming is valid */
2206 0 : nt_status = update_trust_user(mem_ctx,
2207 : p_state->sam_ldb,
2208 : p_state->domain_dn,
2209 : del_incoming,
2210 : netbios_name,
2211 : current_passwords);
2212 0 : if (!NT_STATUS_IS_OK(nt_status)) {
2213 0 : goto done;
2214 : }
2215 : }
2216 :
2217 : /* ok, all fine, commit transaction and return */
2218 34 : ret = ldb_transaction_commit(p_state->sam_ldb);
2219 34 : if (ret != LDB_SUCCESS) {
2220 0 : return NT_STATUS_INTERNAL_DB_CORRUPTION;
2221 : }
2222 34 : in_transaction = false;
2223 :
2224 34 : nt_status = NT_STATUS_OK;
2225 :
2226 34 : done:
2227 34 : if (in_transaction) {
2228 0 : ldb_transaction_cancel(p_state->sam_ldb);
2229 : }
2230 34 : return nt_status;
2231 : }
2232 :
2233 : /*
2234 : lsa_SetInformationTrustedDomain
2235 : */
2236 22 : static NTSTATUS dcesrv_lsa_SetInformationTrustedDomain(
2237 : struct dcesrv_call_state *dce_call,
2238 : TALLOC_CTX *mem_ctx,
2239 : struct lsa_SetInformationTrustedDomain *r)
2240 : {
2241 0 : struct dcesrv_handle *h;
2242 0 : struct lsa_trusted_domain_state *td_state;
2243 0 : struct ldb_message **msgs;
2244 0 : NTSTATUS nt_status;
2245 :
2246 22 : DCESRV_PULL_HANDLE(h, r->in.trustdom_handle,
2247 : LSA_HANDLE_TRUSTED_DOMAIN);
2248 :
2249 22 : td_state = talloc_get_type(h->data, struct lsa_trusted_domain_state);
2250 :
2251 : /* get the trusted domain object */
2252 22 : nt_status = get_tdo(td_state->policy->sam_ldb, mem_ctx,
2253 : td_state->trusted_domain_dn,
2254 : NULL, NULL, NULL, &msgs);
2255 22 : if (!NT_STATUS_IS_OK(nt_status)) {
2256 0 : if (NT_STATUS_EQUAL(nt_status,
2257 : NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
2258 0 : return nt_status;
2259 : }
2260 0 : return NT_STATUS_INTERNAL_DB_CORRUPTION;
2261 : }
2262 :
2263 22 : return setInfoTrustedDomain_base(dce_call, td_state->policy, mem_ctx,
2264 : msgs[0], r->in.level, r->in.info);
2265 : }
2266 :
2267 :
2268 : /*
2269 : lsa_DeleteTrustedDomain
2270 : */
2271 112 : static NTSTATUS dcesrv_lsa_DeleteTrustedDomain(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2272 : struct lsa_DeleteTrustedDomain *r)
2273 : {
2274 0 : NTSTATUS status;
2275 112 : struct lsa_OpenTrustedDomain opn = {{0},{0}};
2276 0 : struct lsa_DeleteObject del;
2277 0 : struct dcesrv_handle *h;
2278 :
2279 112 : opn.in.handle = r->in.handle;
2280 112 : opn.in.sid = r->in.dom_sid;
2281 112 : opn.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2282 112 : opn.out.trustdom_handle = talloc(mem_ctx, struct policy_handle);
2283 112 : if (!opn.out.trustdom_handle) {
2284 0 : return NT_STATUS_NO_MEMORY;
2285 : }
2286 112 : status = dcesrv_lsa_OpenTrustedDomain(dce_call, mem_ctx, &opn);
2287 112 : if (!NT_STATUS_IS_OK(status)) {
2288 0 : return status;
2289 : }
2290 :
2291 112 : DCESRV_PULL_HANDLE(h, opn.out.trustdom_handle, DCESRV_HANDLE_ANY);
2292 112 : talloc_steal(mem_ctx, h);
2293 :
2294 112 : del.in.handle = opn.out.trustdom_handle;
2295 112 : del.out.handle = opn.out.trustdom_handle;
2296 112 : status = dcesrv_lsa_DeleteObject(dce_call, mem_ctx, &del);
2297 112 : if (!NT_STATUS_IS_OK(status)) {
2298 0 : return status;
2299 : }
2300 112 : return NT_STATUS_OK;
2301 : }
2302 :
2303 2041 : static NTSTATUS fill_trust_domain_ex(TALLOC_CTX *mem_ctx,
2304 : struct ldb_message *msg,
2305 : struct lsa_TrustDomainInfoInfoEx *info_ex)
2306 : {
2307 0 : info_ex->domain_name.string
2308 2041 : = ldb_msg_find_attr_as_string(msg, "trustPartner", NULL);
2309 0 : info_ex->netbios_name.string
2310 2041 : = ldb_msg_find_attr_as_string(msg, "flatname", NULL);
2311 0 : info_ex->sid
2312 2041 : = samdb_result_dom_sid(mem_ctx, msg, "securityIdentifier");
2313 0 : info_ex->trust_direction
2314 2041 : = ldb_msg_find_attr_as_int(msg, "trustDirection", 0);
2315 0 : info_ex->trust_type
2316 2041 : = ldb_msg_find_attr_as_int(msg, "trustType", 0);
2317 0 : info_ex->trust_attributes
2318 2041 : = ldb_msg_find_attr_as_int(msg, "trustAttributes", 0);
2319 2041 : return NT_STATUS_OK;
2320 : }
2321 :
2322 : /*
2323 : lsa_QueryTrustedDomainInfo
2324 : */
2325 5962 : static NTSTATUS dcesrv_lsa_QueryTrustedDomainInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2326 : struct lsa_QueryTrustedDomainInfo *r)
2327 : {
2328 5962 : union lsa_TrustedDomainInfo *info = NULL;
2329 0 : struct dcesrv_handle *h;
2330 0 : struct lsa_trusted_domain_state *trusted_domain_state;
2331 0 : struct ldb_message *msg;
2332 0 : int ret;
2333 0 : struct ldb_message **res;
2334 5962 : const char *attrs[] = {
2335 : "flatname",
2336 : "trustPartner",
2337 : "securityIdentifier",
2338 : "trustDirection",
2339 : "trustType",
2340 : "trustAttributes",
2341 : "msDs-supportedEncryptionTypes",
2342 : NULL
2343 : };
2344 :
2345 5962 : DCESRV_PULL_HANDLE(h, r->in.trustdom_handle, LSA_HANDLE_TRUSTED_DOMAIN);
2346 :
2347 5962 : trusted_domain_state = talloc_get_type(h->data, struct lsa_trusted_domain_state);
2348 :
2349 : /* pull all the user attributes */
2350 5962 : ret = gendb_search_dn(trusted_domain_state->policy->sam_ldb, mem_ctx,
2351 : trusted_domain_state->trusted_domain_dn, &res, attrs);
2352 5962 : if (ret != 1) {
2353 0 : return NT_STATUS_INTERNAL_DB_CORRUPTION;
2354 : }
2355 5962 : msg = res[0];
2356 :
2357 5962 : info = talloc_zero(mem_ctx, union lsa_TrustedDomainInfo);
2358 5962 : if (!info) {
2359 0 : return NT_STATUS_NO_MEMORY;
2360 : }
2361 5962 : *r->out.info = info;
2362 :
2363 5962 : switch (r->in.level) {
2364 435 : case LSA_TRUSTED_DOMAIN_INFO_NAME:
2365 0 : info->name.netbios_name.string
2366 435 : = ldb_msg_find_attr_as_string(msg, "flatname", NULL);
2367 435 : break;
2368 435 : case LSA_TRUSTED_DOMAIN_INFO_POSIX_OFFSET:
2369 0 : info->posix_offset.posix_offset
2370 435 : = ldb_msg_find_attr_as_uint(msg, "posixOffset", 0);
2371 435 : break;
2372 : #if 0 /* Win2k3 doesn't implement this */
2373 : case LSA_TRUSTED_DOMAIN_INFO_BASIC:
2374 : r->out.info->info_basic.netbios_name.string
2375 : = ldb_msg_find_attr_as_string(msg, "flatname", NULL);
2376 : r->out.info->info_basic.sid
2377 : = samdb_result_dom_sid(mem_ctx, msg, "securityIdentifier");
2378 : break;
2379 : #endif
2380 715 : case LSA_TRUSTED_DOMAIN_INFO_INFO_EX:
2381 4633 : return fill_trust_domain_ex(mem_ctx, msg, &info->info_ex);
2382 :
2383 459 : case LSA_TRUSTED_DOMAIN_INFO_FULL_INFO:
2384 459 : ZERO_STRUCT(info->full_info);
2385 459 : return fill_trust_domain_ex(mem_ctx, msg, &info->full_info.info_ex);
2386 435 : case LSA_TRUSTED_DOMAIN_INFO_FULL_INFO_2_INTERNAL:
2387 435 : ZERO_STRUCT(info->full_info2_internal);
2388 0 : info->full_info2_internal.posix_offset.posix_offset
2389 435 : = ldb_msg_find_attr_as_uint(msg, "posixOffset", 0);
2390 435 : return fill_trust_domain_ex(mem_ctx, msg, &info->full_info2_internal.info.info_ex);
2391 :
2392 459 : case LSA_TRUSTED_DOMAIN_SUPPORTED_ENCRYPTION_TYPES:
2393 0 : info->enc_types.enc_types
2394 459 : = ldb_msg_find_attr_as_uint(msg, "msDs-supportedEncryptionTypes", KERB_ENCTYPE_RC4_HMAC_MD5);
2395 459 : break;
2396 :
2397 864 : case LSA_TRUSTED_DOMAIN_INFO_CONTROLLERS:
2398 : case LSA_TRUSTED_DOMAIN_INFO_INFO_EX2_INTERNAL:
2399 : /* oops, we don't want to return the info after all */
2400 864 : talloc_free(info);
2401 864 : *r->out.info = NULL;
2402 864 : return NT_STATUS_INVALID_PARAMETER;
2403 2160 : default:
2404 : /* oops, we don't want to return the info after all */
2405 2160 : talloc_free(info);
2406 2160 : *r->out.info = NULL;
2407 2160 : return NT_STATUS_INVALID_INFO_CLASS;
2408 : }
2409 :
2410 1329 : return NT_STATUS_OK;
2411 : }
2412 :
2413 :
2414 : /*
2415 : lsa_QueryTrustedDomainInfoBySid
2416 : */
2417 1405 : static NTSTATUS dcesrv_lsa_QueryTrustedDomainInfoBySid(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2418 : struct lsa_QueryTrustedDomainInfoBySid *r)
2419 : {
2420 0 : NTSTATUS status;
2421 1405 : struct lsa_OpenTrustedDomain opn = {{0},{0}};
2422 0 : struct lsa_QueryTrustedDomainInfo query;
2423 0 : struct dcesrv_handle *h;
2424 :
2425 1405 : opn.in.handle = r->in.handle;
2426 1405 : opn.in.sid = r->in.dom_sid;
2427 1405 : opn.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2428 1405 : opn.out.trustdom_handle = talloc(mem_ctx, struct policy_handle);
2429 1405 : if (!opn.out.trustdom_handle) {
2430 0 : return NT_STATUS_NO_MEMORY;
2431 : }
2432 1405 : status = dcesrv_lsa_OpenTrustedDomain(dce_call, mem_ctx, &opn);
2433 1405 : if (!NT_STATUS_IS_OK(status)) {
2434 1 : return status;
2435 : }
2436 :
2437 : /* Ensure this handle goes away at the end of this call */
2438 1404 : DCESRV_PULL_HANDLE(h, opn.out.trustdom_handle, DCESRV_HANDLE_ANY);
2439 1404 : talloc_steal(mem_ctx, h);
2440 :
2441 1404 : query.in.trustdom_handle = opn.out.trustdom_handle;
2442 1404 : query.in.level = r->in.level;
2443 1404 : query.out.info = r->out.info;
2444 1404 : status = dcesrv_lsa_QueryTrustedDomainInfo(dce_call, mem_ctx, &query);
2445 1404 : if (!NT_STATUS_IS_OK(status)) {
2446 756 : return status;
2447 : }
2448 :
2449 648 : return NT_STATUS_OK;
2450 : }
2451 :
2452 : /*
2453 : lsa_SetTrustedDomainInfoByName
2454 : */
2455 18 : static NTSTATUS dcesrv_lsa_SetTrustedDomainInfoByName(struct dcesrv_call_state *dce_call,
2456 : TALLOC_CTX *mem_ctx,
2457 : struct lsa_SetTrustedDomainInfoByName *r)
2458 : {
2459 0 : struct dcesrv_handle *policy_handle;
2460 0 : struct lsa_policy_state *policy_state;
2461 0 : struct ldb_message **msgs;
2462 0 : NTSTATUS nt_status;
2463 :
2464 18 : DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
2465 18 : policy_state = policy_handle->data;
2466 :
2467 : /* get the trusted domain object */
2468 18 : nt_status = get_tdo(policy_state->sam_ldb, mem_ctx,
2469 : policy_state->domain_dn,
2470 18 : r->in.trusted_domain->string,
2471 18 : r->in.trusted_domain->string,
2472 : NULL, &msgs);
2473 18 : if (!NT_STATUS_IS_OK(nt_status)) {
2474 0 : if (NT_STATUS_EQUAL(nt_status,
2475 : NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
2476 0 : return nt_status;
2477 : }
2478 0 : return NT_STATUS_INTERNAL_DB_CORRUPTION;
2479 : }
2480 :
2481 18 : return setInfoTrustedDomain_base(dce_call, policy_state, mem_ctx,
2482 : msgs[0], r->in.level, r->in.info);
2483 : }
2484 :
2485 : /*
2486 : lsa_QueryTrustedDomainInfoByName
2487 : */
2488 1691 : static NTSTATUS dcesrv_lsa_QueryTrustedDomainInfoByName(struct dcesrv_call_state *dce_call,
2489 : TALLOC_CTX *mem_ctx,
2490 : struct lsa_QueryTrustedDomainInfoByName *r)
2491 : {
2492 0 : NTSTATUS status;
2493 1691 : struct lsa_OpenTrustedDomainByName opn = {{0},{0}};
2494 0 : struct lsa_QueryTrustedDomainInfo query;
2495 0 : struct dcesrv_handle *h;
2496 :
2497 1691 : opn.in.handle = r->in.handle;
2498 1691 : opn.in.name = *r->in.trusted_domain;
2499 1691 : opn.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2500 1691 : opn.out.trustdom_handle = talloc(mem_ctx, struct policy_handle);
2501 1691 : if (!opn.out.trustdom_handle) {
2502 0 : return NT_STATUS_NO_MEMORY;
2503 : }
2504 1691 : status = dcesrv_lsa_OpenTrustedDomainByName(dce_call, mem_ctx, &opn);
2505 1691 : if (!NT_STATUS_IS_OK(status)) {
2506 52 : return status;
2507 : }
2508 :
2509 : /* Ensure this handle goes away at the end of this call */
2510 1639 : DCESRV_PULL_HANDLE(h, opn.out.trustdom_handle, DCESRV_HANDLE_ANY);
2511 1639 : talloc_steal(mem_ctx, h);
2512 :
2513 1639 : query.in.trustdom_handle = opn.out.trustdom_handle;
2514 1639 : query.in.level = r->in.level;
2515 1639 : query.out.info = r->out.info;
2516 1639 : status = dcesrv_lsa_QueryTrustedDomainInfo(dce_call, mem_ctx, &query);
2517 1639 : if (!NT_STATUS_IS_OK(status)) {
2518 756 : return status;
2519 : }
2520 :
2521 883 : return NT_STATUS_OK;
2522 : }
2523 :
2524 : /*
2525 : lsa_CloseTrustedDomainEx
2526 : */
2527 108 : static NTSTATUS dcesrv_lsa_CloseTrustedDomainEx(struct dcesrv_call_state *dce_call,
2528 : TALLOC_CTX *mem_ctx,
2529 : struct lsa_CloseTrustedDomainEx *r)
2530 : {
2531 : /* The result of a bad hair day from an IDL programmer? Not
2532 : * implemented in Win2k3. You should always just lsa_Close
2533 : * anyway. */
2534 108 : return NT_STATUS_NOT_IMPLEMENTED;
2535 : }
2536 :
2537 :
2538 : /*
2539 : comparison function for sorting lsa_DomainInformation array
2540 : */
2541 1076 : static int compare_DomainInfo(struct lsa_DomainInfo *e1, struct lsa_DomainInfo *e2)
2542 : {
2543 1076 : return strcasecmp_m(e1->name.string, e2->name.string);
2544 : }
2545 :
2546 : /*
2547 : lsa_EnumTrustDom
2548 : */
2549 66 : static NTSTATUS dcesrv_lsa_EnumTrustDom(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2550 : struct lsa_EnumTrustDom *r)
2551 : {
2552 3 : struct dcesrv_handle *policy_handle;
2553 3 : struct lsa_DomainInfo *entries;
2554 3 : struct lsa_policy_state *policy_state;
2555 3 : struct ldb_message **domains;
2556 66 : const char *attrs[] = {
2557 : "flatname",
2558 : "securityIdentifier",
2559 : NULL
2560 : };
2561 :
2562 :
2563 3 : int count, i;
2564 :
2565 66 : *r->out.resume_handle = 0;
2566 :
2567 66 : r->out.domains->domains = NULL;
2568 66 : r->out.domains->count = 0;
2569 :
2570 66 : DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
2571 :
2572 66 : policy_state = policy_handle->data;
2573 :
2574 : /* search for all users in this domain. This could possibly be cached and
2575 : resumed based on resume_key */
2576 66 : count = gendb_search(policy_state->sam_ldb, mem_ctx, policy_state->system_dn, &domains, attrs,
2577 : "objectclass=trustedDomain");
2578 66 : if (count < 0) {
2579 0 : return NT_STATUS_INTERNAL_DB_CORRUPTION;
2580 : }
2581 :
2582 : /* convert to lsa_TrustInformation format */
2583 66 : entries = talloc_array(mem_ctx, struct lsa_DomainInfo, count);
2584 66 : if (!entries) {
2585 0 : return NT_STATUS_NO_MEMORY;
2586 : }
2587 498 : for (i=0;i<count;i++) {
2588 432 : entries[i].sid = samdb_result_dom_sid(mem_ctx, domains[i], "securityIdentifier");
2589 432 : entries[i].name.string = ldb_msg_find_attr_as_string(domains[i], "flatname", NULL);
2590 : }
2591 :
2592 : /* sort the results by name */
2593 66 : TYPESAFE_QSORT(entries, count, compare_DomainInfo);
2594 :
2595 66 : if (*r->in.resume_handle >= count) {
2596 30 : *r->out.resume_handle = -1;
2597 :
2598 30 : return NT_STATUS_NO_MORE_ENTRIES;
2599 : }
2600 :
2601 : /* return the rest, limit by max_size. Note that we
2602 : use the w2k3 element size value of 60 */
2603 36 : r->out.domains->count = count - *r->in.resume_handle;
2604 36 : r->out.domains->count = MIN(r->out.domains->count,
2605 : 1+(r->in.max_size/LSA_ENUM_TRUST_DOMAIN_MULTIPLIER));
2606 :
2607 36 : r->out.domains->domains = entries + *r->in.resume_handle;
2608 :
2609 36 : if (r->out.domains->count < count - *r->in.resume_handle) {
2610 27 : *r->out.resume_handle = *r->in.resume_handle + r->out.domains->count;
2611 27 : return STATUS_MORE_ENTRIES;
2612 : }
2613 :
2614 : /* according to MS-LSAD 3.1.4.7.8 output resume handle MUST
2615 : * always be larger than the previous input resume handle, in
2616 : * particular when hitting the last query it is vital to set the
2617 : * resume handle correctly to avoid infinite client loops, as
2618 : * seen e.g. with Windows XP SP3 when resume handle is 0 and
2619 : * status is NT_STATUS_OK - gd */
2620 :
2621 9 : *r->out.resume_handle = (uint32_t)-1;
2622 :
2623 9 : return NT_STATUS_OK;
2624 : }
2625 :
2626 : /*
2627 : comparison function for sorting lsa_DomainInformation array
2628 : */
2629 1076 : static int compare_TrustDomainInfoInfoEx(struct lsa_TrustDomainInfoInfoEx *e1, struct lsa_TrustDomainInfoInfoEx *e2)
2630 : {
2631 1076 : return strcasecmp_m(e1->netbios_name.string, e2->netbios_name.string);
2632 : }
2633 :
2634 : /*
2635 : lsa_EnumTrustedDomainsEx
2636 : */
2637 42 : static NTSTATUS dcesrv_lsa_EnumTrustedDomainsEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2638 : struct lsa_EnumTrustedDomainsEx *r)
2639 : {
2640 0 : struct dcesrv_handle *policy_handle;
2641 0 : struct lsa_TrustDomainInfoInfoEx *entries;
2642 0 : struct lsa_policy_state *policy_state;
2643 0 : struct ldb_message **domains;
2644 42 : const char *attrs[] = {
2645 : "flatname",
2646 : "trustPartner",
2647 : "securityIdentifier",
2648 : "trustDirection",
2649 : "trustType",
2650 : "trustAttributes",
2651 : NULL
2652 : };
2653 0 : NTSTATUS nt_status;
2654 :
2655 0 : int count, i;
2656 :
2657 42 : *r->out.resume_handle = 0;
2658 :
2659 42 : r->out.domains->domains = NULL;
2660 42 : r->out.domains->count = 0;
2661 :
2662 42 : DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
2663 :
2664 42 : policy_state = policy_handle->data;
2665 :
2666 : /* search for all users in this domain. This could possibly be cached and
2667 : resumed based on resume_key */
2668 42 : count = gendb_search(policy_state->sam_ldb, mem_ctx, policy_state->system_dn, &domains, attrs,
2669 : "objectclass=trustedDomain");
2670 42 : if (count < 0) {
2671 0 : return NT_STATUS_INTERNAL_DB_CORRUPTION;
2672 : }
2673 :
2674 : /* convert to lsa_DomainInformation format */
2675 42 : entries = talloc_array(mem_ctx, struct lsa_TrustDomainInfoInfoEx, count);
2676 42 : if (!entries) {
2677 0 : return NT_STATUS_NO_MEMORY;
2678 : }
2679 474 : for (i=0;i<count;i++) {
2680 432 : nt_status = fill_trust_domain_ex(mem_ctx, domains[i], &entries[i]);
2681 432 : if (!NT_STATUS_IS_OK(nt_status)) {
2682 0 : return nt_status;
2683 : }
2684 : }
2685 :
2686 : /* sort the results by name */
2687 42 : TYPESAFE_QSORT(entries, count, compare_TrustDomainInfoInfoEx);
2688 :
2689 42 : if (*r->in.resume_handle >= count) {
2690 6 : *r->out.resume_handle = -1;
2691 :
2692 6 : return NT_STATUS_NO_MORE_ENTRIES;
2693 : }
2694 :
2695 : /* return the rest, limit by max_size. Note that we
2696 : use the w2k3 element size value of 60 */
2697 36 : r->out.domains->count = count - *r->in.resume_handle;
2698 36 : r->out.domains->count = MIN(r->out.domains->count,
2699 : 1+(r->in.max_size/LSA_ENUM_TRUST_DOMAIN_EX_MULTIPLIER));
2700 :
2701 36 : r->out.domains->domains = entries + *r->in.resume_handle;
2702 :
2703 36 : if (r->out.domains->count < count - *r->in.resume_handle) {
2704 27 : *r->out.resume_handle = *r->in.resume_handle + r->out.domains->count;
2705 27 : return STATUS_MORE_ENTRIES;
2706 : }
2707 :
2708 9 : *r->out.resume_handle = *r->in.resume_handle + r->out.domains->count;
2709 :
2710 9 : return NT_STATUS_OK;
2711 : }
2712 :
2713 :
2714 : /*
2715 : lsa_OpenAccount
2716 : */
2717 26 : static NTSTATUS dcesrv_lsa_OpenAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2718 : struct lsa_OpenAccount *r)
2719 : {
2720 0 : struct dcesrv_handle *h, *ah;
2721 0 : struct lsa_policy_state *state;
2722 0 : struct lsa_account_state *astate;
2723 :
2724 26 : ZERO_STRUCTP(r->out.acct_handle);
2725 :
2726 26 : DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
2727 :
2728 26 : state = h->data;
2729 :
2730 26 : astate = talloc(dce_call->conn, struct lsa_account_state);
2731 26 : if (astate == NULL) {
2732 0 : return NT_STATUS_NO_MEMORY;
2733 : }
2734 :
2735 26 : astate->account_sid = dom_sid_dup(astate, r->in.sid);
2736 26 : if (astate->account_sid == NULL) {
2737 0 : talloc_free(astate);
2738 0 : return NT_STATUS_NO_MEMORY;
2739 : }
2740 :
2741 26 : astate->policy = talloc_reference(astate, state);
2742 26 : astate->access_mask = r->in.access_mask;
2743 :
2744 : /*
2745 : * For now we grant all requested access.
2746 : *
2747 : * We will fail at the ldb layer later.
2748 : */
2749 26 : if (astate->access_mask & SEC_FLAG_MAXIMUM_ALLOWED) {
2750 26 : astate->access_mask &= ~SEC_FLAG_MAXIMUM_ALLOWED;
2751 26 : astate->access_mask |= LSA_ACCOUNT_ALL_ACCESS;
2752 : }
2753 26 : se_map_generic(&astate->access_mask, &dcesrv_lsa_account_mapping);
2754 :
2755 26 : DEBUG(10,("%s: %s access desired[0x%08X] granted[0x%08X] - success.\n",
2756 : __func__, dom_sid_string(mem_ctx, astate->account_sid),
2757 : (unsigned)r->in.access_mask,
2758 : (unsigned)astate->access_mask));
2759 :
2760 26 : ah = dcesrv_handle_create(dce_call, LSA_HANDLE_ACCOUNT);
2761 26 : if (!ah) {
2762 0 : talloc_free(astate);
2763 0 : return NT_STATUS_NO_MEMORY;
2764 : }
2765 :
2766 26 : ah->data = talloc_steal(ah, astate);
2767 :
2768 26 : *r->out.acct_handle = ah->wire_handle;
2769 :
2770 26 : return NT_STATUS_OK;
2771 : }
2772 :
2773 :
2774 : /*
2775 : lsa_EnumPrivsAccount
2776 : */
2777 18 : static NTSTATUS dcesrv_lsa_EnumPrivsAccount(struct dcesrv_call_state *dce_call,
2778 : TALLOC_CTX *mem_ctx,
2779 : struct lsa_EnumPrivsAccount *r)
2780 : {
2781 0 : struct dcesrv_handle *h;
2782 0 : struct lsa_account_state *astate;
2783 0 : int ret;
2784 0 : unsigned int i, j;
2785 0 : struct ldb_message **res;
2786 18 : const char * const attrs[] = { "privilege", NULL};
2787 0 : struct ldb_message_element *el;
2788 0 : const char *sidstr;
2789 0 : struct lsa_PrivilegeSet *privs;
2790 :
2791 18 : DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
2792 :
2793 18 : astate = h->data;
2794 :
2795 18 : privs = talloc(mem_ctx, struct lsa_PrivilegeSet);
2796 18 : if (privs == NULL) {
2797 0 : return NT_STATUS_NO_MEMORY;
2798 : }
2799 18 : privs->count = 0;
2800 18 : privs->unknown = 0;
2801 18 : privs->set = NULL;
2802 :
2803 18 : *r->out.privs = privs;
2804 :
2805 18 : sidstr = ldap_encode_ndr_dom_sid(mem_ctx, astate->account_sid);
2806 18 : if (sidstr == NULL) {
2807 0 : return NT_STATUS_NO_MEMORY;
2808 : }
2809 :
2810 18 : ret = gendb_search(astate->policy->pdb, mem_ctx, NULL, &res, attrs,
2811 : "objectSid=%s", sidstr);
2812 18 : if (ret < 0) {
2813 0 : return NT_STATUS_INTERNAL_DB_CORRUPTION;
2814 : }
2815 18 : if (ret != 1) {
2816 0 : return NT_STATUS_OK;
2817 : }
2818 :
2819 18 : el = ldb_msg_find_element(res[0], "privilege");
2820 18 : if (el == NULL || el->num_values == 0) {
2821 0 : return NT_STATUS_OK;
2822 : }
2823 :
2824 18 : privs->set = talloc_array(privs,
2825 : struct lsa_LUIDAttribute, el->num_values);
2826 18 : if (privs->set == NULL) {
2827 0 : return NT_STATUS_NO_MEMORY;
2828 : }
2829 :
2830 18 : j = 0;
2831 138 : for (i=0;i<el->num_values;i++) {
2832 120 : int id = sec_privilege_id((const char *)el->values[i].data);
2833 120 : if (id == SEC_PRIV_INVALID) {
2834 : /* Perhaps an account right, not a privilege */
2835 24 : continue;
2836 : }
2837 96 : privs->set[j].attribute = 0;
2838 96 : privs->set[j].luid.low = id;
2839 96 : privs->set[j].luid.high = 0;
2840 96 : j++;
2841 : }
2842 :
2843 18 : privs->count = j;
2844 :
2845 18 : return NT_STATUS_OK;
2846 : }
2847 :
2848 : /*
2849 : lsa_EnumAccountRights
2850 : */
2851 78 : static NTSTATUS dcesrv_lsa_EnumAccountRights(struct dcesrv_call_state *dce_call,
2852 : TALLOC_CTX *mem_ctx,
2853 : struct lsa_EnumAccountRights *r)
2854 : {
2855 0 : struct dcesrv_handle *h;
2856 0 : struct lsa_policy_state *state;
2857 0 : int ret;
2858 0 : unsigned int i;
2859 0 : struct ldb_message **res;
2860 78 : const char * const attrs[] = { "privilege", NULL};
2861 0 : const char *sidstr;
2862 0 : struct ldb_message_element *el;
2863 :
2864 78 : DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
2865 :
2866 78 : state = h->data;
2867 :
2868 78 : sidstr = ldap_encode_ndr_dom_sid(mem_ctx, r->in.sid);
2869 78 : if (sidstr == NULL) {
2870 0 : return NT_STATUS_NO_MEMORY;
2871 : }
2872 :
2873 78 : ret = gendb_search(state->pdb, mem_ctx, NULL, &res, attrs,
2874 : "(&(objectSid=%s)(privilege=*))", sidstr);
2875 78 : if (ret == 0) {
2876 17 : return NT_STATUS_OBJECT_NAME_NOT_FOUND;
2877 : }
2878 61 : if (ret != 1) {
2879 0 : DEBUG(3, ("searching for account rights for SID: %s failed: %s\n",
2880 : dom_sid_string(mem_ctx, r->in.sid),
2881 : ldb_errstring(state->pdb)));
2882 0 : return NT_STATUS_INTERNAL_DB_CORRUPTION;
2883 : }
2884 :
2885 61 : el = ldb_msg_find_element(res[0], "privilege");
2886 61 : if (el == NULL || el->num_values == 0) {
2887 0 : return NT_STATUS_OBJECT_NAME_NOT_FOUND;
2888 : }
2889 :
2890 61 : r->out.rights->count = el->num_values;
2891 61 : r->out.rights->names = talloc_array(r->out.rights,
2892 : struct lsa_StringLarge, r->out.rights->count);
2893 61 : if (r->out.rights->names == NULL) {
2894 0 : return NT_STATUS_NO_MEMORY;
2895 : }
2896 :
2897 599 : for (i=0;i<el->num_values;i++) {
2898 538 : r->out.rights->names[i].string = (const char *)el->values[i].data;
2899 : }
2900 :
2901 61 : return NT_STATUS_OK;
2902 : }
2903 :
2904 :
2905 :
2906 : /*
2907 : helper for lsa_AddAccountRights and lsa_RemoveAccountRights
2908 : */
2909 44 : static NTSTATUS dcesrv_lsa_AddRemoveAccountRights(struct dcesrv_call_state *dce_call,
2910 : TALLOC_CTX *mem_ctx,
2911 : struct lsa_policy_state *state,
2912 : int ldb_flag,
2913 : struct dom_sid *sid,
2914 : const struct lsa_RightSet *rights)
2915 : {
2916 0 : struct auth_session_info *session_info =
2917 44 : dcesrv_call_session_info(dce_call);
2918 0 : const char *sidstr, *sidndrstr;
2919 0 : struct ldb_message *msg;
2920 0 : struct ldb_message_element *el;
2921 0 : int ret;
2922 0 : uint32_t i;
2923 0 : struct lsa_EnumAccountRights r2;
2924 0 : char *dnstr;
2925 :
2926 44 : if (security_session_user_level(session_info, NULL) <
2927 : SECURITY_ADMINISTRATOR) {
2928 0 : DEBUG(0,("lsa_AddRemoveAccount refused for supplied security token\n"));
2929 0 : return NT_STATUS_ACCESS_DENIED;
2930 : }
2931 :
2932 44 : msg = ldb_msg_new(mem_ctx);
2933 44 : if (msg == NULL) {
2934 0 : return NT_STATUS_NO_MEMORY;
2935 : }
2936 :
2937 44 : sidndrstr = ldap_encode_ndr_dom_sid(msg, sid);
2938 44 : if (sidndrstr == NULL) {
2939 0 : TALLOC_FREE(msg);
2940 0 : return NT_STATUS_NO_MEMORY;
2941 : }
2942 :
2943 44 : sidstr = dom_sid_string(msg, sid);
2944 44 : if (sidstr == NULL) {
2945 0 : TALLOC_FREE(msg);
2946 0 : return NT_STATUS_NO_MEMORY;
2947 : }
2948 :
2949 44 : dnstr = talloc_asprintf(msg, "sid=%s", sidstr);
2950 44 : if (dnstr == NULL) {
2951 0 : TALLOC_FREE(msg);
2952 0 : return NT_STATUS_NO_MEMORY;
2953 : }
2954 :
2955 44 : msg->dn = ldb_dn_new(msg, state->pdb, dnstr);
2956 44 : if (msg->dn == NULL) {
2957 0 : TALLOC_FREE(msg);
2958 0 : return NT_STATUS_NO_MEMORY;
2959 : }
2960 :
2961 44 : if (LDB_FLAG_MOD_TYPE(ldb_flag) == LDB_FLAG_MOD_ADD) {
2962 0 : NTSTATUS status;
2963 :
2964 25 : r2.in.handle = &state->handle->wire_handle;
2965 25 : r2.in.sid = sid;
2966 25 : r2.out.rights = talloc(mem_ctx, struct lsa_RightSet);
2967 :
2968 25 : status = dcesrv_lsa_EnumAccountRights(dce_call, mem_ctx, &r2);
2969 25 : if (!NT_STATUS_IS_OK(status)) {
2970 6 : ZERO_STRUCTP(r2.out.rights);
2971 : }
2972 : }
2973 :
2974 92 : for (i=0;i<rights->count;i++) {
2975 0 : bool ok;
2976 :
2977 48 : ok = dcesrc_lsa_valid_AccountRight(rights->names[i].string);
2978 48 : if (!ok) {
2979 0 : talloc_free(msg);
2980 0 : return NT_STATUS_NO_SUCH_PRIVILEGE;
2981 : }
2982 :
2983 48 : if (LDB_FLAG_MOD_TYPE(ldb_flag) == LDB_FLAG_MOD_ADD) {
2984 : uint32_t j;
2985 131 : for (j=0;j<r2.out.rights->count;j++) {
2986 106 : if (strcasecmp_m(r2.out.rights->names[j].string,
2987 106 : rights->names[i].string) == 0) {
2988 0 : break;
2989 : }
2990 : }
2991 25 : if (j != r2.out.rights->count) continue;
2992 : }
2993 :
2994 48 : ret = ldb_msg_add_string(msg, "privilege", rights->names[i].string);
2995 48 : if (ret != LDB_SUCCESS) {
2996 0 : talloc_free(msg);
2997 0 : return NT_STATUS_NO_MEMORY;
2998 : }
2999 : }
3000 :
3001 44 : el = ldb_msg_find_element(msg, "privilege");
3002 44 : if (!el) {
3003 0 : talloc_free(msg);
3004 0 : return NT_STATUS_OK;
3005 : }
3006 :
3007 44 : el->flags = ldb_flag;
3008 :
3009 44 : ret = ldb_modify(state->pdb, msg);
3010 44 : if (ret == LDB_ERR_NO_SUCH_OBJECT) {
3011 6 : if (samdb_msg_add_dom_sid(state->pdb, msg, msg, "objectSid", sid) != LDB_SUCCESS) {
3012 0 : talloc_free(msg);
3013 0 : return NT_STATUS_NO_MEMORY;
3014 : }
3015 6 : ldb_msg_add_string(msg, "comment", "added via LSA");
3016 6 : ret = ldb_add(state->pdb, msg);
3017 : }
3018 44 : if (ret != LDB_SUCCESS) {
3019 0 : if (LDB_FLAG_MOD_TYPE(ldb_flag) == LDB_FLAG_MOD_DELETE && ret == LDB_ERR_NO_SUCH_ATTRIBUTE) {
3020 0 : talloc_free(msg);
3021 0 : return NT_STATUS_OK;
3022 : }
3023 0 : DEBUG(3, ("Could not %s attributes from %s: %s\n",
3024 : LDB_FLAG_MOD_TYPE(ldb_flag) == LDB_FLAG_MOD_DELETE ? "delete" : "add",
3025 : ldb_dn_get_linearized(msg->dn), ldb_errstring(state->pdb)));
3026 0 : talloc_free(msg);
3027 0 : return NT_STATUS_UNEXPECTED_IO_ERROR;
3028 : }
3029 :
3030 44 : talloc_free(msg);
3031 44 : return NT_STATUS_OK;
3032 : }
3033 :
3034 : /*
3035 : lsa_AddPrivilegesToAccount
3036 : */
3037 15 : static NTSTATUS dcesrv_lsa_AddPrivilegesToAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3038 : struct lsa_AddPrivilegesToAccount *r)
3039 : {
3040 0 : struct lsa_RightSet rights;
3041 0 : struct dcesrv_handle *h;
3042 0 : struct lsa_account_state *astate;
3043 0 : uint32_t i;
3044 :
3045 15 : DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
3046 :
3047 15 : astate = h->data;
3048 :
3049 15 : rights.count = r->in.privs->count;
3050 15 : rights.names = talloc_array(mem_ctx, struct lsa_StringLarge, rights.count);
3051 15 : if (rights.names == NULL) {
3052 0 : return NT_STATUS_NO_MEMORY;
3053 : }
3054 30 : for (i=0;i<rights.count;i++) {
3055 15 : int id = r->in.privs->set[i].luid.low;
3056 15 : if (r->in.privs->set[i].luid.high) {
3057 0 : return NT_STATUS_NO_SUCH_PRIVILEGE;
3058 : }
3059 15 : rights.names[i].string = sec_privilege_name(id);
3060 15 : if (rights.names[i].string == NULL) {
3061 0 : return NT_STATUS_NO_SUCH_PRIVILEGE;
3062 : }
3063 : }
3064 :
3065 15 : return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, astate->policy,
3066 : LDB_FLAG_MOD_ADD, astate->account_sid,
3067 : &rights);
3068 : }
3069 :
3070 :
3071 : /*
3072 : lsa_RemovePrivilegesFromAccount
3073 : */
3074 15 : static NTSTATUS dcesrv_lsa_RemovePrivilegesFromAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3075 : struct lsa_RemovePrivilegesFromAccount *r)
3076 : {
3077 0 : struct lsa_RightSet *rights;
3078 0 : struct dcesrv_handle *h;
3079 0 : struct lsa_account_state *astate;
3080 0 : uint32_t i;
3081 :
3082 15 : DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
3083 :
3084 15 : astate = h->data;
3085 :
3086 15 : rights = talloc(mem_ctx, struct lsa_RightSet);
3087 :
3088 15 : if (r->in.remove_all == 1 &&
3089 0 : r->in.privs == NULL) {
3090 0 : struct lsa_EnumAccountRights r2;
3091 0 : NTSTATUS status;
3092 :
3093 0 : r2.in.handle = &astate->policy->handle->wire_handle;
3094 0 : r2.in.sid = astate->account_sid;
3095 0 : r2.out.rights = rights;
3096 :
3097 0 : status = dcesrv_lsa_EnumAccountRights(dce_call, mem_ctx, &r2);
3098 0 : if (!NT_STATUS_IS_OK(status)) {
3099 0 : return status;
3100 : }
3101 :
3102 0 : return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, astate->policy,
3103 : LDB_FLAG_MOD_DELETE, astate->account_sid,
3104 0 : r2.out.rights);
3105 : }
3106 :
3107 15 : if (r->in.remove_all != 0) {
3108 0 : return NT_STATUS_INVALID_PARAMETER;
3109 : }
3110 :
3111 15 : rights->count = r->in.privs->count;
3112 15 : rights->names = talloc_array(mem_ctx, struct lsa_StringLarge, rights->count);
3113 15 : if (rights->names == NULL) {
3114 0 : return NT_STATUS_NO_MEMORY;
3115 : }
3116 30 : for (i=0;i<rights->count;i++) {
3117 15 : int id = r->in.privs->set[i].luid.low;
3118 15 : if (r->in.privs->set[i].luid.high) {
3119 0 : return NT_STATUS_NO_SUCH_PRIVILEGE;
3120 : }
3121 15 : rights->names[i].string = sec_privilege_name(id);
3122 15 : if (rights->names[i].string == NULL) {
3123 0 : return NT_STATUS_NO_SUCH_PRIVILEGE;
3124 : }
3125 : }
3126 :
3127 15 : return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, astate->policy,
3128 : LDB_FLAG_MOD_DELETE, astate->account_sid,
3129 : rights);
3130 : }
3131 :
3132 :
3133 : /*
3134 : lsa_GetQuotasForAccount
3135 : */
3136 0 : static NTSTATUS dcesrv_lsa_GetQuotasForAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3137 : struct lsa_GetQuotasForAccount *r)
3138 : {
3139 0 : DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3140 : }
3141 :
3142 :
3143 : /*
3144 : lsa_SetQuotasForAccount
3145 : */
3146 0 : static NTSTATUS dcesrv_lsa_SetQuotasForAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3147 : struct lsa_SetQuotasForAccount *r)
3148 : {
3149 0 : DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3150 : }
3151 :
3152 :
3153 : /*
3154 : lsa_GetSystemAccessAccount
3155 : */
3156 26 : static NTSTATUS dcesrv_lsa_GetSystemAccessAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3157 : struct lsa_GetSystemAccessAccount *r)
3158 : {
3159 0 : struct dcesrv_handle *h;
3160 0 : struct lsa_account_state *astate;
3161 0 : int ret;
3162 0 : unsigned int i;
3163 0 : struct ldb_message **res;
3164 26 : const char * const attrs[] = { "privilege", NULL};
3165 0 : struct ldb_message_element *el;
3166 0 : const char *sidstr;
3167 :
3168 26 : *(r->out.access_mask) = 0x00000000;
3169 :
3170 26 : DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
3171 :
3172 26 : astate = h->data;
3173 :
3174 26 : sidstr = ldap_encode_ndr_dom_sid(mem_ctx, astate->account_sid);
3175 26 : if (sidstr == NULL) {
3176 0 : return NT_STATUS_NO_MEMORY;
3177 : }
3178 :
3179 26 : ret = gendb_search(astate->policy->pdb, mem_ctx, NULL, &res, attrs,
3180 : "objectSid=%s", sidstr);
3181 26 : if (ret < 0) {
3182 0 : return NT_STATUS_INTERNAL_DB_CORRUPTION;
3183 : }
3184 26 : if (ret != 1) {
3185 0 : return NT_STATUS_OK;
3186 : }
3187 :
3188 26 : el = ldb_msg_find_element(res[0], "privilege");
3189 26 : if (el == NULL || el->num_values == 0) {
3190 0 : return NT_STATUS_OK;
3191 : }
3192 :
3193 162 : for (i=0;i<el->num_values;i++) {
3194 136 : uint32_t right_bit = sec_right_bit((const char *)el->values[i].data);
3195 136 : if (right_bit == 0) {
3196 : /* Perhaps an privilege, not a right */
3197 104 : continue;
3198 : }
3199 32 : *(r->out.access_mask) |= right_bit;
3200 : }
3201 :
3202 26 : return NT_STATUS_OK;
3203 : }
3204 :
3205 :
3206 : /*
3207 : lsa_SetSystemAccessAccount
3208 : */
3209 0 : static NTSTATUS dcesrv_lsa_SetSystemAccessAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3210 : struct lsa_SetSystemAccessAccount *r)
3211 : {
3212 0 : DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3213 : }
3214 : /*
3215 : lsa_CreateSecret
3216 : */
3217 1676 : static NTSTATUS dcesrv_lsa_CreateSecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3218 : struct lsa_CreateSecret *r)
3219 : {
3220 0 : struct auth_session_info *session_info =
3221 1676 : dcesrv_call_session_info(dce_call);
3222 0 : struct dcesrv_handle *policy_handle;
3223 0 : struct lsa_policy_state *policy_state;
3224 0 : struct lsa_secret_state *secret_state;
3225 0 : struct dcesrv_handle *handle;
3226 0 : struct ldb_message **msgs, *msg;
3227 1676 : const char *attrs[] = {
3228 : NULL
3229 : };
3230 :
3231 0 : const char *name;
3232 :
3233 0 : int ret;
3234 :
3235 1676 : DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
3236 1676 : ZERO_STRUCTP(r->out.sec_handle);
3237 :
3238 1676 : switch (security_session_user_level(session_info, NULL))
3239 : {
3240 1676 : case SECURITY_SYSTEM:
3241 : case SECURITY_ADMINISTRATOR:
3242 1676 : break;
3243 0 : default:
3244 : /* Users and anonymous are not allowed create secrets */
3245 0 : return NT_STATUS_ACCESS_DENIED;
3246 : }
3247 :
3248 1676 : policy_state = policy_handle->data;
3249 :
3250 1676 : if (!r->in.name.string) {
3251 0 : return NT_STATUS_INVALID_PARAMETER;
3252 : }
3253 :
3254 1676 : secret_state = talloc(mem_ctx, struct lsa_secret_state);
3255 1676 : NT_STATUS_HAVE_NO_MEMORY(secret_state);
3256 1676 : secret_state->policy = policy_state;
3257 :
3258 1676 : msg = ldb_msg_new(mem_ctx);
3259 1676 : if (msg == NULL) {
3260 0 : return NT_STATUS_NO_MEMORY;
3261 : }
3262 :
3263 1676 : if (strncmp("G$", r->in.name.string, 2) == 0) {
3264 0 : const char *name2;
3265 :
3266 20 : secret_state->global = true;
3267 :
3268 20 : name = &r->in.name.string[2];
3269 20 : if (strlen(name) == 0) {
3270 0 : return NT_STATUS_INVALID_PARAMETER;
3271 : }
3272 :
3273 20 : name2 = talloc_asprintf(mem_ctx, "%s Secret",
3274 : ldb_binary_encode_string(mem_ctx, name));
3275 20 : NT_STATUS_HAVE_NO_MEMORY(name2);
3276 :
3277 : /*
3278 : * We need to connect to the database as system, as this is
3279 : * one of the rare RPC calls that must read the secrets
3280 : * (and this is denied otherwise)
3281 : *
3282 : * We also save the current remote session details so they can
3283 : * used by the audit logging module. This allows the audit
3284 : * logging to report the remote users details, rather than the
3285 : * system users details.
3286 : */
3287 20 : secret_state->sam_ldb =
3288 20 : dcesrv_samdb_connect_as_system(secret_state, dce_call);
3289 20 : NT_STATUS_HAVE_NO_MEMORY(secret_state->sam_ldb);
3290 :
3291 : /* search for the secret record */
3292 20 : ret = gendb_search(secret_state->sam_ldb,
3293 : mem_ctx, policy_state->system_dn, &msgs, attrs,
3294 : "(&(cn=%s)(objectclass=secret))",
3295 : name2);
3296 20 : if (ret > 0) {
3297 9 : return NT_STATUS_OBJECT_NAME_COLLISION;
3298 : }
3299 :
3300 11 : if (ret < 0) {
3301 0 : DEBUG(0,("Failure searching for CN=%s: %s\n",
3302 : name2, ldb_errstring(secret_state->sam_ldb)));
3303 0 : return NT_STATUS_INTERNAL_DB_CORRUPTION;
3304 : }
3305 :
3306 11 : msg->dn = ldb_dn_copy(mem_ctx, policy_state->system_dn);
3307 11 : NT_STATUS_HAVE_NO_MEMORY(msg->dn);
3308 11 : if (!ldb_dn_add_child_fmt(msg->dn, "cn=%s", name2)) {
3309 0 : return NT_STATUS_NO_MEMORY;
3310 : }
3311 :
3312 11 : ret = ldb_msg_add_string(msg, "cn", name2);
3313 11 : if (ret != LDB_SUCCESS) return NT_STATUS_NO_MEMORY;
3314 : } else {
3315 1656 : secret_state->global = false;
3316 :
3317 1656 : name = r->in.name.string;
3318 1656 : if (strlen(name) == 0) {
3319 0 : return NT_STATUS_INVALID_PARAMETER;
3320 : }
3321 :
3322 3312 : secret_state->sam_ldb = secrets_db_connect(secret_state,
3323 1656 : dce_call->conn->dce_ctx->lp_ctx);
3324 1656 : NT_STATUS_HAVE_NO_MEMORY(secret_state->sam_ldb);
3325 :
3326 : /* search for the secret record */
3327 1656 : ret = gendb_search(secret_state->sam_ldb, mem_ctx,
3328 : ldb_dn_new(mem_ctx, secret_state->sam_ldb, "cn=LSA Secrets"),
3329 : &msgs, attrs,
3330 : "(&(cn=%s)(objectclass=secret))",
3331 : ldb_binary_encode_string(mem_ctx, name));
3332 1656 : if (ret > 0) {
3333 12 : return NT_STATUS_OBJECT_NAME_COLLISION;
3334 : }
3335 :
3336 1644 : if (ret < 0) {
3337 0 : DEBUG(0,("Failure searching for CN=%s: %s\n",
3338 : name, ldb_errstring(secret_state->sam_ldb)));
3339 0 : return NT_STATUS_INTERNAL_DB_CORRUPTION;
3340 : }
3341 :
3342 1644 : msg->dn = ldb_dn_new_fmt(mem_ctx, secret_state->sam_ldb,
3343 : "cn=%s,cn=LSA Secrets", name);
3344 1644 : NT_STATUS_HAVE_NO_MEMORY(msg->dn);
3345 1644 : ret = ldb_msg_add_string(msg, "cn", name);
3346 1644 : if (ret != LDB_SUCCESS) return NT_STATUS_NO_MEMORY;
3347 : }
3348 :
3349 1655 : ret = ldb_msg_add_string(msg, "objectClass", "secret");
3350 1655 : if (ret != LDB_SUCCESS) return NT_STATUS_NO_MEMORY;
3351 :
3352 1655 : secret_state->secret_dn = talloc_reference(secret_state, msg->dn);
3353 1655 : NT_STATUS_HAVE_NO_MEMORY(secret_state->secret_dn);
3354 :
3355 : /* create the secret */
3356 1655 : ret = ldb_add(secret_state->sam_ldb, msg);
3357 1655 : if (ret != LDB_SUCCESS) {
3358 0 : DEBUG(0,("Failed to create secret record %s: %s\n",
3359 : ldb_dn_get_linearized(msg->dn),
3360 : ldb_errstring(secret_state->sam_ldb)));
3361 0 : return NT_STATUS_ACCESS_DENIED;
3362 : }
3363 :
3364 1655 : handle = dcesrv_handle_create(dce_call, LSA_HANDLE_SECRET);
3365 1655 : NT_STATUS_HAVE_NO_MEMORY(handle);
3366 :
3367 1655 : handle->data = talloc_steal(handle, secret_state);
3368 :
3369 1655 : secret_state->access_mask = r->in.access_mask;
3370 1655 : secret_state->policy = talloc_reference(secret_state, policy_state);
3371 1655 : NT_STATUS_HAVE_NO_MEMORY(secret_state->policy);
3372 :
3373 1655 : *r->out.sec_handle = handle->wire_handle;
3374 :
3375 1655 : return NT_STATUS_OK;
3376 : }
3377 :
3378 :
3379 : /*
3380 : lsa_OpenSecret
3381 : */
3382 46 : static NTSTATUS dcesrv_lsa_OpenSecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3383 : struct lsa_OpenSecret *r)
3384 : {
3385 0 : struct auth_session_info *session_info =
3386 46 : dcesrv_call_session_info(dce_call);
3387 0 : struct dcesrv_handle *policy_handle;
3388 0 : struct lsa_policy_state *policy_state;
3389 0 : struct lsa_secret_state *secret_state;
3390 0 : struct dcesrv_handle *handle;
3391 0 : struct ldb_message **msgs;
3392 46 : const char *attrs[] = {
3393 : NULL
3394 : };
3395 0 : const char *name;
3396 0 : int ret;
3397 :
3398 46 : DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
3399 46 : ZERO_STRUCTP(r->out.sec_handle);
3400 46 : policy_state = policy_handle->data;
3401 :
3402 46 : if (!r->in.name.string) {
3403 0 : return NT_STATUS_INVALID_PARAMETER;
3404 : }
3405 :
3406 46 : switch (security_session_user_level(session_info, NULL))
3407 : {
3408 46 : case SECURITY_SYSTEM:
3409 : case SECURITY_ADMINISTRATOR:
3410 46 : break;
3411 0 : default:
3412 : /* Users and anonymous are not allowed to access secrets */
3413 0 : return NT_STATUS_ACCESS_DENIED;
3414 : }
3415 :
3416 46 : secret_state = talloc(mem_ctx, struct lsa_secret_state);
3417 46 : if (!secret_state) {
3418 0 : return NT_STATUS_NO_MEMORY;
3419 : }
3420 46 : secret_state->policy = policy_state;
3421 :
3422 46 : if (strncmp("G$", r->in.name.string, 2) == 0) {
3423 25 : name = &r->in.name.string[2];
3424 : /*
3425 : * We need to connect to the database as system, as this is
3426 : * one of the rare RPC calls that must read the secrets
3427 : * (and this is denied otherwise)
3428 : *
3429 : * We also save the current remote session details so they can
3430 : * used by the audit logging module. This allows the audit
3431 : * logging to report the remote users details, rather than the
3432 : * system users details.
3433 : */
3434 25 : secret_state->sam_ldb =
3435 25 : dcesrv_samdb_connect_as_system(secret_state, dce_call);
3436 25 : NT_STATUS_HAVE_NO_MEMORY(secret_state->sam_ldb);
3437 25 : secret_state->global = true;
3438 :
3439 25 : if (strlen(name) < 1) {
3440 0 : return NT_STATUS_INVALID_PARAMETER;
3441 : }
3442 :
3443 : /* search for the secret record */
3444 25 : ret = gendb_search(secret_state->sam_ldb,
3445 : mem_ctx, policy_state->system_dn, &msgs, attrs,
3446 : "(&(cn=%s Secret)(objectclass=secret))",
3447 : ldb_binary_encode_string(mem_ctx, name));
3448 25 : if (ret == 0) {
3449 9 : return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3450 : }
3451 :
3452 16 : if (ret != 1) {
3453 0 : DEBUG(0,("Found %d records matching DN %s\n", ret,
3454 : ldb_dn_get_linearized(policy_state->system_dn)));
3455 0 : return NT_STATUS_INTERNAL_DB_CORRUPTION;
3456 : }
3457 : } else {
3458 21 : secret_state->global = false;
3459 42 : secret_state->sam_ldb = secrets_db_connect(secret_state,
3460 21 : dce_call->conn->dce_ctx->lp_ctx);
3461 21 : NT_STATUS_HAVE_NO_MEMORY(secret_state->sam_ldb);
3462 :
3463 21 : name = r->in.name.string;
3464 21 : if (strlen(name) < 1) {
3465 0 : return NT_STATUS_INVALID_PARAMETER;
3466 : }
3467 :
3468 : /* search for the secret record */
3469 21 : ret = gendb_search(secret_state->sam_ldb, mem_ctx,
3470 : ldb_dn_new(mem_ctx, secret_state->sam_ldb, "cn=LSA Secrets"),
3471 : &msgs, attrs,
3472 : "(&(cn=%s)(objectclass=secret))",
3473 : ldb_binary_encode_string(mem_ctx, name));
3474 21 : if (ret == 0) {
3475 9 : return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3476 : }
3477 :
3478 12 : if (ret != 1) {
3479 0 : DEBUG(0,("Found %d records matching CN=%s\n",
3480 : ret, ldb_binary_encode_string(mem_ctx, name)));
3481 0 : return NT_STATUS_INTERNAL_DB_CORRUPTION;
3482 : }
3483 : }
3484 :
3485 28 : secret_state->secret_dn = talloc_reference(secret_state, msgs[0]->dn);
3486 :
3487 28 : handle = dcesrv_handle_create(dce_call, LSA_HANDLE_SECRET);
3488 28 : if (!handle) {
3489 0 : return NT_STATUS_NO_MEMORY;
3490 : }
3491 :
3492 28 : handle->data = talloc_steal(handle, secret_state);
3493 :
3494 28 : secret_state->access_mask = r->in.access_mask;
3495 28 : secret_state->policy = talloc_reference(secret_state, policy_state);
3496 :
3497 28 : *r->out.sec_handle = handle->wire_handle;
3498 :
3499 28 : return NT_STATUS_OK;
3500 : }
3501 :
3502 :
3503 : /*
3504 : lsa_SetSecret
3505 : */
3506 2376 : static NTSTATUS dcesrv_lsa_SetSecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3507 : struct lsa_SetSecret *r)
3508 : {
3509 :
3510 0 : struct dcesrv_handle *h;
3511 0 : struct lsa_secret_state *secret_state;
3512 0 : struct ldb_message *msg;
3513 0 : DATA_BLOB session_key;
3514 0 : DATA_BLOB crypt_secret, secret;
3515 0 : struct ldb_val val;
3516 0 : int ret;
3517 2376 : NTSTATUS status = NT_STATUS_OK;
3518 :
3519 2376 : struct timeval now = timeval_current();
3520 2376 : NTTIME nt_now = timeval_to_nttime(&now);
3521 :
3522 2376 : DCESRV_PULL_HANDLE(h, r->in.sec_handle, LSA_HANDLE_SECRET);
3523 :
3524 2376 : secret_state = h->data;
3525 :
3526 2376 : msg = ldb_msg_new(mem_ctx);
3527 2376 : if (msg == NULL) {
3528 0 : return NT_STATUS_NO_MEMORY;
3529 : }
3530 :
3531 2376 : msg->dn = talloc_reference(mem_ctx, secret_state->secret_dn);
3532 2376 : if (!msg->dn) {
3533 0 : return NT_STATUS_NO_MEMORY;
3534 : }
3535 2376 : status = dcesrv_transport_session_key(dce_call, &session_key);
3536 2376 : if (!NT_STATUS_IS_OK(status)) {
3537 0 : return status;
3538 : }
3539 :
3540 2376 : if (r->in.old_val) {
3541 : /* Decrypt */
3542 18 : crypt_secret.data = r->in.old_val->data;
3543 18 : crypt_secret.length = r->in.old_val->size;
3544 :
3545 18 : status = sess_decrypt_blob(mem_ctx, &crypt_secret, &session_key, &secret);
3546 18 : if (!NT_STATUS_IS_OK(status)) {
3547 0 : return status;
3548 : }
3549 :
3550 18 : val.data = secret.data;
3551 18 : val.length = secret.length;
3552 :
3553 : /* set value */
3554 18 : if (ldb_msg_add_value(msg, "priorValue", &val, NULL) != LDB_SUCCESS) {
3555 0 : return NT_STATUS_NO_MEMORY;
3556 : }
3557 :
3558 : /* set old value mtime */
3559 18 : if (samdb_msg_add_uint64(secret_state->sam_ldb,
3560 : mem_ctx, msg, "priorSetTime", nt_now) != LDB_SUCCESS) {
3561 0 : return NT_STATUS_NO_MEMORY;
3562 : }
3563 :
3564 : } else {
3565 : /* If the old value is not set, then migrate the
3566 : * current value to the old value */
3567 0 : const struct ldb_val *old_val;
3568 0 : NTTIME last_set_time;
3569 0 : struct ldb_message **res;
3570 2358 : const char *attrs[] = {
3571 : "currentValue",
3572 : "lastSetTime",
3573 : NULL
3574 : };
3575 :
3576 : /* search for the secret record */
3577 2358 : ret = gendb_search_dn(secret_state->sam_ldb,mem_ctx,
3578 : secret_state->secret_dn, &res, attrs);
3579 2358 : if (ret == 0) {
3580 0 : return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3581 : }
3582 :
3583 2358 : if (ret != 1) {
3584 0 : DEBUG(0,("Found %d records matching dn=%s\n", ret,
3585 : ldb_dn_get_linearized(secret_state->secret_dn)));
3586 0 : return NT_STATUS_INTERNAL_DB_CORRUPTION;
3587 : }
3588 :
3589 2358 : old_val = ldb_msg_find_ldb_val(res[0], "currentValue");
3590 2358 : last_set_time = ldb_msg_find_attr_as_uint64(res[0], "lastSetTime", 0);
3591 :
3592 2358 : if (old_val) {
3593 : /* set old value */
3594 1188 : if (ldb_msg_add_value(msg, "priorValue",
3595 : old_val, NULL) != LDB_SUCCESS) {
3596 0 : return NT_STATUS_NO_MEMORY;
3597 : }
3598 : } else {
3599 1170 : if (samdb_msg_add_delete(secret_state->sam_ldb,
3600 : mem_ctx, msg, "priorValue") != LDB_SUCCESS) {
3601 0 : return NT_STATUS_NO_MEMORY;
3602 : }
3603 : }
3604 :
3605 : /* set old value mtime */
3606 2358 : if (ldb_msg_find_ldb_val(res[0], "lastSetTime")) {
3607 1188 : if (samdb_msg_add_uint64(secret_state->sam_ldb,
3608 : mem_ctx, msg, "priorSetTime", last_set_time) != LDB_SUCCESS) {
3609 0 : return NT_STATUS_NO_MEMORY;
3610 : }
3611 : } else {
3612 1170 : if (samdb_msg_add_uint64(secret_state->sam_ldb,
3613 : mem_ctx, msg, "priorSetTime", nt_now) != LDB_SUCCESS) {
3614 0 : return NT_STATUS_NO_MEMORY;
3615 : }
3616 : }
3617 : }
3618 :
3619 2376 : if (r->in.new_val) {
3620 : /* Decrypt */
3621 2358 : crypt_secret.data = r->in.new_val->data;
3622 2358 : crypt_secret.length = r->in.new_val->size;
3623 :
3624 2358 : status = sess_decrypt_blob(mem_ctx, &crypt_secret, &session_key, &secret);
3625 2358 : if (!NT_STATUS_IS_OK(status)) {
3626 1170 : return status;
3627 : }
3628 :
3629 1188 : val.data = secret.data;
3630 1188 : val.length = secret.length;
3631 :
3632 : /* set value */
3633 1188 : if (ldb_msg_add_value(msg, "currentValue", &val, NULL) != LDB_SUCCESS) {
3634 0 : return NT_STATUS_NO_MEMORY;
3635 : }
3636 :
3637 : /* set new value mtime */
3638 1188 : if (samdb_msg_add_uint64(secret_state->sam_ldb,
3639 : mem_ctx, msg, "lastSetTime", nt_now) != LDB_SUCCESS) {
3640 0 : return NT_STATUS_NO_MEMORY;
3641 : }
3642 : } else {
3643 : /* NULL out the NEW value */
3644 18 : if (samdb_msg_add_uint64(secret_state->sam_ldb,
3645 : mem_ctx, msg, "lastSetTime", nt_now) != LDB_SUCCESS) {
3646 0 : return NT_STATUS_NO_MEMORY;
3647 : }
3648 18 : if (samdb_msg_add_delete(secret_state->sam_ldb,
3649 : mem_ctx, msg, "currentValue") != LDB_SUCCESS) {
3650 0 : return NT_STATUS_NO_MEMORY;
3651 : }
3652 : }
3653 :
3654 : /* modify the samdb record */
3655 1206 : ret = dsdb_replace(secret_state->sam_ldb, msg, 0);
3656 1206 : if (ret != LDB_SUCCESS) {
3657 0 : return dsdb_ldb_err_to_ntstatus(ret);
3658 : }
3659 :
3660 1206 : return NT_STATUS_OK;
3661 : }
3662 :
3663 :
3664 : /*
3665 : lsa_QuerySecret
3666 : */
3667 1212 : static NTSTATUS dcesrv_lsa_QuerySecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3668 : struct lsa_QuerySecret *r)
3669 : {
3670 0 : struct auth_session_info *session_info =
3671 1212 : dcesrv_call_session_info(dce_call);
3672 0 : struct dcesrv_handle *h;
3673 0 : struct lsa_secret_state *secret_state;
3674 0 : struct ldb_message *msg;
3675 0 : DATA_BLOB session_key;
3676 0 : DATA_BLOB crypt_secret, secret;
3677 0 : int ret;
3678 0 : struct ldb_message **res;
3679 1212 : const char *attrs[] = {
3680 : "currentValue",
3681 : "priorValue",
3682 : "lastSetTime",
3683 : "priorSetTime",
3684 : NULL
3685 : };
3686 :
3687 0 : NTSTATUS nt_status;
3688 :
3689 1212 : DCESRV_PULL_HANDLE(h, r->in.sec_handle, LSA_HANDLE_SECRET);
3690 :
3691 : /* Ensure user is permitted to read this... */
3692 1212 : switch (security_session_user_level(session_info, NULL))
3693 : {
3694 1212 : case SECURITY_SYSTEM:
3695 : case SECURITY_ADMINISTRATOR:
3696 1212 : break;
3697 0 : default:
3698 : /* Users and anonymous are not allowed to read secrets */
3699 0 : return NT_STATUS_ACCESS_DENIED;
3700 : }
3701 :
3702 1212 : secret_state = h->data;
3703 :
3704 : /* pull all the user attributes */
3705 1212 : ret = gendb_search_dn(secret_state->sam_ldb, mem_ctx,
3706 : secret_state->secret_dn, &res, attrs);
3707 1212 : if (ret != 1) {
3708 0 : return NT_STATUS_INTERNAL_DB_CORRUPTION;
3709 : }
3710 1212 : msg = res[0];
3711 :
3712 1212 : nt_status = dcesrv_transport_session_key(dce_call, &session_key);
3713 1212 : if (!NT_STATUS_IS_OK(nt_status)) {
3714 0 : return nt_status;
3715 : }
3716 :
3717 1212 : if (r->in.old_val) {
3718 0 : const struct ldb_val *prior_val;
3719 36 : r->out.old_val = talloc_zero(mem_ctx, struct lsa_DATA_BUF_PTR);
3720 36 : if (!r->out.old_val) {
3721 0 : return NT_STATUS_NO_MEMORY;
3722 : }
3723 36 : prior_val = ldb_msg_find_ldb_val(msg, "priorValue");
3724 :
3725 36 : if (prior_val && prior_val->length) {
3726 36 : secret.data = prior_val->data;
3727 36 : secret.length = prior_val->length;
3728 :
3729 : /* Encrypt */
3730 36 : crypt_secret = sess_encrypt_blob(mem_ctx, &secret, &session_key);
3731 36 : if (!crypt_secret.length) {
3732 0 : return NT_STATUS_NO_MEMORY;
3733 : }
3734 36 : r->out.old_val->buf = talloc(mem_ctx, struct lsa_DATA_BUF);
3735 36 : if (!r->out.old_val->buf) {
3736 0 : return NT_STATUS_NO_MEMORY;
3737 : }
3738 36 : r->out.old_val->buf->size = crypt_secret.length;
3739 36 : r->out.old_val->buf->length = crypt_secret.length;
3740 36 : r->out.old_val->buf->data = crypt_secret.data;
3741 : }
3742 : }
3743 :
3744 1212 : if (r->in.old_mtime) {
3745 36 : r->out.old_mtime = talloc(mem_ctx, NTTIME);
3746 36 : if (!r->out.old_mtime) {
3747 0 : return NT_STATUS_NO_MEMORY;
3748 : }
3749 36 : *r->out.old_mtime = ldb_msg_find_attr_as_uint64(msg, "priorSetTime", 0);
3750 : }
3751 :
3752 1212 : if (r->in.new_val) {
3753 0 : const struct ldb_val *new_val;
3754 1212 : r->out.new_val = talloc_zero(mem_ctx, struct lsa_DATA_BUF_PTR);
3755 1212 : if (!r->out.new_val) {
3756 0 : return NT_STATUS_NO_MEMORY;
3757 : }
3758 :
3759 1212 : new_val = ldb_msg_find_ldb_val(msg, "currentValue");
3760 :
3761 1212 : if (new_val && new_val->length) {
3762 1194 : secret.data = new_val->data;
3763 1194 : secret.length = new_val->length;
3764 :
3765 : /* Encrypt */
3766 1194 : crypt_secret = sess_encrypt_blob(mem_ctx, &secret, &session_key);
3767 1194 : if (!crypt_secret.length) {
3768 0 : return NT_STATUS_NO_MEMORY;
3769 : }
3770 1194 : r->out.new_val->buf = talloc(mem_ctx, struct lsa_DATA_BUF);
3771 1194 : if (!r->out.new_val->buf) {
3772 0 : return NT_STATUS_NO_MEMORY;
3773 : }
3774 1194 : r->out.new_val->buf->length = crypt_secret.length;
3775 1194 : r->out.new_val->buf->size = crypt_secret.length;
3776 1194 : r->out.new_val->buf->data = crypt_secret.data;
3777 : }
3778 : }
3779 :
3780 1212 : if (r->in.new_mtime) {
3781 1206 : r->out.new_mtime = talloc(mem_ctx, NTTIME);
3782 1206 : if (!r->out.new_mtime) {
3783 0 : return NT_STATUS_NO_MEMORY;
3784 : }
3785 1206 : *r->out.new_mtime = ldb_msg_find_attr_as_uint64(msg, "lastSetTime", 0);
3786 : }
3787 :
3788 1212 : return NT_STATUS_OK;
3789 : }
3790 :
3791 :
3792 : /*
3793 : lsa_LookupPrivValue
3794 : */
3795 77 : static NTSTATUS dcesrv_lsa_LookupPrivValue(struct dcesrv_call_state *dce_call,
3796 : TALLOC_CTX *mem_ctx,
3797 : struct lsa_LookupPrivValue *r)
3798 : {
3799 0 : struct dcesrv_handle *h;
3800 0 : int id;
3801 :
3802 77 : DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3803 :
3804 77 : id = sec_privilege_id(r->in.name->string);
3805 77 : if (id == SEC_PRIV_INVALID) {
3806 0 : return NT_STATUS_NO_SUCH_PRIVILEGE;
3807 : }
3808 :
3809 77 : r->out.luid->low = id;
3810 77 : r->out.luid->high = 0;
3811 :
3812 77 : return NT_STATUS_OK;
3813 : }
3814 :
3815 :
3816 : /*
3817 : lsa_LookupPrivName
3818 : */
3819 96 : static NTSTATUS dcesrv_lsa_LookupPrivName(struct dcesrv_call_state *dce_call,
3820 : TALLOC_CTX *mem_ctx,
3821 : struct lsa_LookupPrivName *r)
3822 : {
3823 0 : struct dcesrv_handle *h;
3824 0 : struct lsa_StringLarge *name;
3825 0 : const char *privname;
3826 :
3827 96 : DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3828 :
3829 96 : if (r->in.luid->high != 0) {
3830 0 : return NT_STATUS_NO_SUCH_PRIVILEGE;
3831 : }
3832 :
3833 96 : privname = sec_privilege_name(r->in.luid->low);
3834 96 : if (privname == NULL) {
3835 0 : return NT_STATUS_NO_SUCH_PRIVILEGE;
3836 : }
3837 :
3838 96 : name = talloc(mem_ctx, struct lsa_StringLarge);
3839 96 : if (name == NULL) {
3840 0 : return NT_STATUS_NO_MEMORY;
3841 : }
3842 :
3843 96 : name->string = privname;
3844 :
3845 96 : *r->out.name = name;
3846 :
3847 96 : return NT_STATUS_OK;
3848 : }
3849 :
3850 :
3851 : /*
3852 : lsa_LookupPrivDisplayName
3853 : */
3854 75 : static NTSTATUS dcesrv_lsa_LookupPrivDisplayName(struct dcesrv_call_state *dce_call,
3855 : TALLOC_CTX *mem_ctx,
3856 : struct lsa_LookupPrivDisplayName *r)
3857 : {
3858 0 : struct dcesrv_handle *h;
3859 75 : struct lsa_StringLarge *disp_name = NULL;
3860 0 : enum sec_privilege id;
3861 :
3862 75 : DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3863 :
3864 75 : id = sec_privilege_id(r->in.name->string);
3865 75 : if (id == SEC_PRIV_INVALID) {
3866 0 : return NT_STATUS_NO_SUCH_PRIVILEGE;
3867 : }
3868 :
3869 75 : disp_name = talloc(mem_ctx, struct lsa_StringLarge);
3870 75 : if (disp_name == NULL) {
3871 0 : return NT_STATUS_NO_MEMORY;
3872 : }
3873 :
3874 75 : disp_name->string = sec_privilege_display_name(id, &r->in.language_id);
3875 75 : if (disp_name->string == NULL) {
3876 0 : return NT_STATUS_INTERNAL_ERROR;
3877 : }
3878 :
3879 75 : *r->out.disp_name = disp_name;
3880 75 : *r->out.returned_language_id = 0;
3881 :
3882 75 : return NT_STATUS_OK;
3883 : }
3884 :
3885 :
3886 : /*
3887 : lsa_EnumAccountsWithUserRight
3888 : */
3889 75 : static NTSTATUS dcesrv_lsa_EnumAccountsWithUserRight(struct dcesrv_call_state *dce_call,
3890 : TALLOC_CTX *mem_ctx,
3891 : struct lsa_EnumAccountsWithUserRight *r)
3892 : {
3893 0 : struct dcesrv_handle *h;
3894 0 : struct lsa_policy_state *state;
3895 0 : int ret, i;
3896 0 : struct ldb_message **res;
3897 75 : const char * const attrs[] = { "objectSid", NULL};
3898 0 : const char *privname;
3899 0 : bool ok;
3900 :
3901 75 : DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3902 :
3903 75 : state = h->data;
3904 :
3905 75 : if (r->in.name == NULL) {
3906 0 : return NT_STATUS_NO_SUCH_PRIVILEGE;
3907 : }
3908 :
3909 75 : privname = r->in.name->string;
3910 :
3911 75 : ok = dcesrc_lsa_valid_AccountRight(privname);
3912 75 : if (!ok) {
3913 0 : return NT_STATUS_NO_SUCH_PRIVILEGE;
3914 : }
3915 :
3916 75 : ret = gendb_search(state->pdb, mem_ctx, NULL, &res, attrs,
3917 : "privilege=%s", privname);
3918 75 : if (ret < 0) {
3919 0 : return NT_STATUS_INTERNAL_DB_CORRUPTION;
3920 : }
3921 75 : if (ret == 0) {
3922 12 : return NT_STATUS_NO_MORE_ENTRIES;
3923 : }
3924 :
3925 63 : r->out.sids->sids = talloc_array(r->out.sids, struct lsa_SidPtr, ret);
3926 63 : if (r->out.sids->sids == NULL) {
3927 0 : return NT_STATUS_NO_MEMORY;
3928 : }
3929 159 : for (i=0;i<ret;i++) {
3930 192 : r->out.sids->sids[i].sid = samdb_result_dom_sid(r->out.sids->sids,
3931 96 : res[i], "objectSid");
3932 96 : NT_STATUS_HAVE_NO_MEMORY(r->out.sids->sids[i].sid);
3933 : }
3934 63 : r->out.sids->num_sids = ret;
3935 :
3936 63 : return NT_STATUS_OK;
3937 : }
3938 :
3939 :
3940 : /*
3941 : lsa_AddAccountRights
3942 : */
3943 10 : static NTSTATUS dcesrv_lsa_AddAccountRights(struct dcesrv_call_state *dce_call,
3944 : TALLOC_CTX *mem_ctx,
3945 : struct lsa_AddAccountRights *r)
3946 : {
3947 0 : struct dcesrv_handle *h;
3948 0 : struct lsa_policy_state *state;
3949 :
3950 10 : DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3951 :
3952 10 : state = h->data;
3953 :
3954 10 : return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, state,
3955 : LDB_FLAG_MOD_ADD,
3956 10 : r->in.sid, r->in.rights);
3957 : }
3958 :
3959 :
3960 : /*
3961 : lsa_RemoveAccountRights
3962 : */
3963 0 : static NTSTATUS dcesrv_lsa_RemoveAccountRights(struct dcesrv_call_state *dce_call,
3964 : TALLOC_CTX *mem_ctx,
3965 : struct lsa_RemoveAccountRights *r)
3966 : {
3967 0 : struct dcesrv_handle *h;
3968 0 : struct lsa_policy_state *state;
3969 :
3970 0 : DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3971 :
3972 0 : state = h->data;
3973 :
3974 0 : return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, state,
3975 : LDB_FLAG_MOD_DELETE,
3976 0 : r->in.sid, r->in.rights);
3977 : }
3978 :
3979 :
3980 : /*
3981 : lsa_StorePrivateData
3982 : */
3983 0 : static NTSTATUS dcesrv_lsa_StorePrivateData(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3984 : struct lsa_StorePrivateData *r)
3985 : {
3986 0 : DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3987 : }
3988 :
3989 :
3990 : /*
3991 : lsa_RetrievePrivateData
3992 : */
3993 0 : static NTSTATUS dcesrv_lsa_RetrievePrivateData(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3994 : struct lsa_RetrievePrivateData *r)
3995 : {
3996 0 : DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3997 : }
3998 :
3999 :
4000 : /*
4001 : lsa_GetUserName
4002 : */
4003 519 : static NTSTATUS dcesrv_lsa_GetUserName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4004 : struct lsa_GetUserName *r)
4005 : {
4006 48 : enum dcerpc_transport_t transport =
4007 519 : dcerpc_binding_get_transport(dce_call->conn->endpoint->ep_description);
4008 48 : struct auth_session_info *session_info =
4009 519 : dcesrv_call_session_info(dce_call);
4010 519 : NTSTATUS status = NT_STATUS_OK;
4011 48 : const char *account_name;
4012 48 : const char *authority_name;
4013 48 : struct lsa_String *_account_name;
4014 519 : struct lsa_String *_authority_name = NULL;
4015 :
4016 519 : if (transport != NCACN_NP && transport != NCALRPC) {
4017 3 : DCESRV_FAULT(DCERPC_FAULT_ACCESS_DENIED);
4018 : }
4019 :
4020 : /* this is what w2k3 does */
4021 516 : r->out.account_name = r->in.account_name;
4022 516 : r->out.authority_name = r->in.authority_name;
4023 :
4024 516 : if (r->in.account_name
4025 516 : && *r->in.account_name
4026 : /* && *(*r->in.account_name)->string */
4027 : ) {
4028 0 : return NT_STATUS_INVALID_PARAMETER;
4029 : }
4030 :
4031 516 : if (r->in.authority_name
4032 468 : && *r->in.authority_name
4033 : /* && *(*r->in.authority_name)->string */
4034 : ) {
4035 0 : return NT_STATUS_INVALID_PARAMETER;
4036 : }
4037 :
4038 516 : account_name = talloc_reference(mem_ctx, session_info->info->account_name);
4039 516 : authority_name = talloc_reference(mem_ctx, session_info->info->domain_name);
4040 :
4041 516 : _account_name = talloc(mem_ctx, struct lsa_String);
4042 516 : NT_STATUS_HAVE_NO_MEMORY(_account_name);
4043 516 : _account_name->string = account_name;
4044 :
4045 516 : if (r->in.authority_name) {
4046 468 : _authority_name = talloc(mem_ctx, struct lsa_String);
4047 468 : NT_STATUS_HAVE_NO_MEMORY(_authority_name);
4048 468 : _authority_name->string = authority_name;
4049 : }
4050 :
4051 516 : *r->out.account_name = _account_name;
4052 516 : if (r->out.authority_name) {
4053 468 : *r->out.authority_name = _authority_name;
4054 : }
4055 :
4056 516 : return status;
4057 : }
4058 :
4059 : /*
4060 : lsa_SetInfoPolicy2
4061 : */
4062 0 : static NTSTATUS dcesrv_lsa_SetInfoPolicy2(struct dcesrv_call_state *dce_call,
4063 : TALLOC_CTX *mem_ctx,
4064 : struct lsa_SetInfoPolicy2 *r)
4065 : {
4066 : /* need to support these */
4067 0 : DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4068 : }
4069 :
4070 12 : static void kdc_get_policy(TALLOC_CTX *mem_ctx,
4071 : struct loadparm_context *lp_ctx,
4072 : struct smb_krb5_context *smb_krb5_context,
4073 : struct lsa_DomainInfoKerberos *k)
4074 : {
4075 0 : time_t svc_tkt_lifetime;
4076 0 : time_t usr_tkt_lifetime;
4077 0 : time_t renewal_lifetime;
4078 :
4079 : /* Our KDC always re-validates the client */
4080 12 : k->authentication_options = LSA_POLICY_KERBEROS_VALIDATE_CLIENT;
4081 :
4082 12 : lpcfg_default_kdc_policy(mem_ctx, lp_ctx, &svc_tkt_lifetime,
4083 : &usr_tkt_lifetime, &renewal_lifetime);
4084 :
4085 12 : unix_to_nt_time(&k->service_tkt_lifetime, svc_tkt_lifetime);
4086 12 : unix_to_nt_time(&k->user_tkt_lifetime, usr_tkt_lifetime);
4087 12 : unix_to_nt_time(&k->user_tkt_renewaltime, renewal_lifetime);
4088 : #ifdef SAMBA4_USES_HEIMDAL /* MIT lacks krb5_get_max_time_skew.
4089 : However in the parent function we basically just did a full
4090 : krb5_context init with the only purpose of getting a global
4091 : config option (the max skew), it would probably make more sense
4092 : to have a lp_ or ldb global option as the samba default */
4093 9 : if (smb_krb5_context) {
4094 9 : unix_to_nt_time(&k->clock_skew,
4095 : krb5_get_max_time_skew(smb_krb5_context->krb5_context));
4096 : }
4097 : #endif
4098 12 : k->reserved = 0;
4099 12 : }
4100 : /*
4101 : lsa_QueryDomainInformationPolicy
4102 : */
4103 24 : static NTSTATUS dcesrv_lsa_QueryDomainInformationPolicy(struct dcesrv_call_state *dce_call,
4104 : TALLOC_CTX *mem_ctx,
4105 : struct lsa_QueryDomainInformationPolicy *r)
4106 : {
4107 0 : union lsa_DomainInformationPolicy *info;
4108 :
4109 24 : info = talloc_zero(r->out.info, union lsa_DomainInformationPolicy);
4110 24 : if (!info) {
4111 0 : return NT_STATUS_NO_MEMORY;
4112 : }
4113 :
4114 24 : switch (r->in.level) {
4115 12 : case LSA_DOMAIN_INFO_POLICY_EFS:
4116 12 : talloc_free(info);
4117 12 : *r->out.info = NULL;
4118 12 : return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4119 12 : case LSA_DOMAIN_INFO_POLICY_KERBEROS:
4120 : {
4121 12 : struct lsa_DomainInfoKerberos *k = &info->kerberos_info;
4122 0 : struct smb_krb5_context *smb_krb5_context;
4123 12 : int ret = smb_krb5_init_context(mem_ctx,
4124 12 : dce_call->conn->dce_ctx->lp_ctx,
4125 : &smb_krb5_context);
4126 12 : if (ret != 0) {
4127 0 : talloc_free(info);
4128 0 : *r->out.info = NULL;
4129 0 : return NT_STATUS_INTERNAL_ERROR;
4130 : }
4131 12 : kdc_get_policy(mem_ctx, dce_call->conn->dce_ctx->lp_ctx,
4132 : smb_krb5_context,
4133 : k);
4134 12 : talloc_free(smb_krb5_context);
4135 12 : *r->out.info = info;
4136 12 : return NT_STATUS_OK;
4137 : }
4138 0 : default:
4139 0 : talloc_free(info);
4140 0 : *r->out.info = NULL;
4141 0 : return NT_STATUS_INVALID_INFO_CLASS;
4142 : }
4143 : }
4144 :
4145 : /*
4146 : lsa_SetDomInfoPolicy
4147 : */
4148 0 : static NTSTATUS dcesrv_lsa_SetDomainInformationPolicy(struct dcesrv_call_state *dce_call,
4149 : TALLOC_CTX *mem_ctx,
4150 : struct lsa_SetDomainInformationPolicy *r)
4151 : {
4152 0 : DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4153 : }
4154 :
4155 : /*
4156 : lsa_TestCall
4157 : */
4158 0 : static NTSTATUS dcesrv_lsa_TestCall(struct dcesrv_call_state *dce_call,
4159 : TALLOC_CTX *mem_ctx,
4160 : struct lsa_TestCall *r)
4161 : {
4162 0 : DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4163 : }
4164 :
4165 : /*
4166 : lsa_CREDRWRITE
4167 : */
4168 0 : static NTSTATUS dcesrv_lsa_CREDRWRITE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4169 : struct lsa_CREDRWRITE *r)
4170 : {
4171 0 : DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4172 : }
4173 :
4174 :
4175 : /*
4176 : lsa_CREDRREAD
4177 : */
4178 0 : static NTSTATUS dcesrv_lsa_CREDRREAD(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4179 : struct lsa_CREDRREAD *r)
4180 : {
4181 0 : DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4182 : }
4183 :
4184 :
4185 : /*
4186 : lsa_CREDRENUMERATE
4187 : */
4188 0 : static NTSTATUS dcesrv_lsa_CREDRENUMERATE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4189 : struct lsa_CREDRENUMERATE *r)
4190 : {
4191 0 : DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4192 : }
4193 :
4194 :
4195 : /*
4196 : lsa_CREDRWRITEDOMAINCREDENTIALS
4197 : */
4198 0 : static NTSTATUS dcesrv_lsa_CREDRWRITEDOMAINCREDENTIALS(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4199 : struct lsa_CREDRWRITEDOMAINCREDENTIALS *r)
4200 : {
4201 0 : DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4202 : }
4203 :
4204 :
4205 : /*
4206 : lsa_CREDRREADDOMAINCREDENTIALS
4207 : */
4208 0 : static NTSTATUS dcesrv_lsa_CREDRREADDOMAINCREDENTIALS(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4209 : struct lsa_CREDRREADDOMAINCREDENTIALS *r)
4210 : {
4211 0 : DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4212 : }
4213 :
4214 :
4215 : /*
4216 : lsa_CREDRDELETE
4217 : */
4218 0 : static NTSTATUS dcesrv_lsa_CREDRDELETE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4219 : struct lsa_CREDRDELETE *r)
4220 : {
4221 0 : DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4222 : }
4223 :
4224 :
4225 : /*
4226 : lsa_CREDRGETTARGETINFO
4227 : */
4228 0 : static NTSTATUS dcesrv_lsa_CREDRGETTARGETINFO(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4229 : struct lsa_CREDRGETTARGETINFO *r)
4230 : {
4231 0 : DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4232 : }
4233 :
4234 :
4235 : /*
4236 : lsa_CREDRPROFILELOADED
4237 : */
4238 0 : static NTSTATUS dcesrv_lsa_CREDRPROFILELOADED(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4239 : struct lsa_CREDRPROFILELOADED *r)
4240 : {
4241 0 : DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4242 : }
4243 :
4244 :
4245 : /*
4246 : lsa_CREDRGETSESSIONTYPES
4247 : */
4248 0 : static NTSTATUS dcesrv_lsa_CREDRGETSESSIONTYPES(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4249 : struct lsa_CREDRGETSESSIONTYPES *r)
4250 : {
4251 0 : DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4252 : }
4253 :
4254 :
4255 : /*
4256 : lsa_LSARREGISTERAUDITEVENT
4257 : */
4258 0 : static NTSTATUS dcesrv_lsa_LSARREGISTERAUDITEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4259 : struct lsa_LSARREGISTERAUDITEVENT *r)
4260 : {
4261 0 : DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4262 : }
4263 :
4264 :
4265 : /*
4266 : lsa_LSARGENAUDITEVENT
4267 : */
4268 0 : static NTSTATUS dcesrv_lsa_LSARGENAUDITEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4269 : struct lsa_LSARGENAUDITEVENT *r)
4270 : {
4271 0 : DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4272 : }
4273 :
4274 :
4275 : /*
4276 : lsa_LSARUNREGISTERAUDITEVENT
4277 : */
4278 0 : static NTSTATUS dcesrv_lsa_LSARUNREGISTERAUDITEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4279 : struct lsa_LSARUNREGISTERAUDITEVENT *r)
4280 : {
4281 0 : DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4282 : }
4283 :
4284 :
4285 : /*
4286 : lsa_lsaRQueryForestTrustInformation
4287 : */
4288 164 : static NTSTATUS dcesrv_lsa_lsaRQueryForestTrustInformation(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4289 : struct lsa_lsaRQueryForestTrustInformation *r)
4290 : {
4291 164 : struct dcesrv_handle *h = NULL;
4292 164 : struct lsa_policy_state *p_state = NULL;
4293 164 : int forest_level = DS_DOMAIN_FUNCTION_2000;
4294 164 : const char * const trust_attrs[] = {
4295 : "securityIdentifier",
4296 : "flatName",
4297 : "trustPartner",
4298 : "trustAttributes",
4299 : "trustDirection",
4300 : "trustType",
4301 : "msDS-TrustForestTrustInfo",
4302 : NULL
4303 : };
4304 164 : struct ldb_message *trust_tdo_msg = NULL;
4305 164 : struct lsa_TrustDomainInfoInfoEx *trust_tdo = NULL;
4306 164 : struct ForestTrustInfo *trust_fti = NULL;
4307 164 : struct lsa_ForestTrustInformation *trust_lfti = NULL;
4308 0 : NTSTATUS status;
4309 :
4310 164 : DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
4311 :
4312 164 : p_state = h->data;
4313 :
4314 164 : if (strcmp(p_state->domain_dns, p_state->forest_dns)) {
4315 0 : return NT_STATUS_INVALID_DOMAIN_STATE;
4316 : }
4317 :
4318 164 : forest_level = dsdb_forest_functional_level(p_state->sam_ldb);
4319 164 : if (forest_level < DS_DOMAIN_FUNCTION_2003) {
4320 0 : return NT_STATUS_INVALID_DOMAIN_STATE;
4321 : }
4322 :
4323 164 : if (r->in.trusted_domain_name->string == NULL) {
4324 0 : return NT_STATUS_NO_SUCH_DOMAIN;
4325 : }
4326 :
4327 164 : status = dsdb_trust_search_tdo(p_state->sam_ldb,
4328 164 : r->in.trusted_domain_name->string,
4329 164 : r->in.trusted_domain_name->string,
4330 : trust_attrs, mem_ctx, &trust_tdo_msg);
4331 164 : if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
4332 0 : return NT_STATUS_NO_SUCH_DOMAIN;
4333 : }
4334 164 : if (!NT_STATUS_IS_OK(status)) {
4335 0 : return status;
4336 : }
4337 :
4338 164 : status = dsdb_trust_parse_tdo_info(mem_ctx, trust_tdo_msg, &trust_tdo);
4339 164 : if (!NT_STATUS_IS_OK(status)) {
4340 0 : return status;
4341 : }
4342 :
4343 164 : if (!(trust_tdo->trust_attributes & LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE)) {
4344 0 : return NT_STATUS_INVALID_PARAMETER;
4345 : }
4346 :
4347 164 : if (r->in.highest_record_type >= LSA_FOREST_TRUST_RECORD_TYPE_LAST) {
4348 0 : return NT_STATUS_INVALID_PARAMETER;
4349 : }
4350 :
4351 164 : status = dsdb_trust_parse_forest_info(mem_ctx,
4352 : trust_tdo_msg,
4353 : &trust_fti);
4354 164 : if (!NT_STATUS_IS_OK(status)) {
4355 8 : return status;
4356 : }
4357 :
4358 156 : status = dsdb_trust_forest_info_to_lsa(mem_ctx, trust_fti,
4359 : &trust_lfti);
4360 156 : if (!NT_STATUS_IS_OK(status)) {
4361 0 : return status;
4362 : }
4363 :
4364 156 : *r->out.forest_trust_info = trust_lfti;
4365 156 : return NT_STATUS_OK;
4366 : }
4367 :
4368 : /*
4369 : lsa_lsaRSetForestTrustInformation
4370 : */
4371 87 : static NTSTATUS dcesrv_lsa_lsaRSetForestTrustInformation(struct dcesrv_call_state *dce_call,
4372 : TALLOC_CTX *mem_ctx,
4373 : struct lsa_lsaRSetForestTrustInformation *r)
4374 : {
4375 0 : struct dcesrv_handle *h;
4376 0 : struct lsa_policy_state *p_state;
4377 87 : const char * const trust_attrs[] = {
4378 : "securityIdentifier",
4379 : "flatName",
4380 : "trustPartner",
4381 : "trustAttributes",
4382 : "trustDirection",
4383 : "trustType",
4384 : "msDS-TrustForestTrustInfo",
4385 : NULL
4386 : };
4387 87 : struct ldb_message *trust_tdo_msg = NULL;
4388 87 : struct lsa_TrustDomainInfoInfoEx *trust_tdo = NULL;
4389 87 : struct lsa_ForestTrustInformation *step1_lfti = NULL;
4390 87 : struct lsa_ForestTrustInformation *step2_lfti = NULL;
4391 87 : struct ForestTrustInfo *trust_fti = NULL;
4392 87 : struct ldb_result *trusts_res = NULL;
4393 0 : unsigned int i;
4394 87 : struct lsa_TrustDomainInfoInfoEx *xref_tdo = NULL;
4395 87 : struct lsa_ForestTrustInformation *xref_lfti = NULL;
4396 87 : struct lsa_ForestTrustCollisionInfo *c_info = NULL;
4397 87 : DATA_BLOB ft_blob = {};
4398 87 : struct ldb_message *msg = NULL;
4399 87 : struct server_id *server_ids = NULL;
4400 87 : uint32_t num_server_ids = 0;
4401 0 : NTSTATUS status;
4402 0 : enum ndr_err_code ndr_err;
4403 0 : int ret;
4404 87 : bool in_transaction = false;
4405 0 : struct imessaging_context *imsg_ctx =
4406 87 : dcesrv_imessaging_context(dce_call->conn);
4407 :
4408 87 : DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
4409 :
4410 87 : p_state = h->data;
4411 :
4412 87 : if (strcmp(p_state->domain_dns, p_state->forest_dns)) {
4413 0 : return NT_STATUS_INVALID_DOMAIN_STATE;
4414 : }
4415 :
4416 87 : if (r->in.check_only == 0) {
4417 79 : ret = ldb_transaction_start(p_state->sam_ldb);
4418 79 : if (ret != LDB_SUCCESS) {
4419 0 : return NT_STATUS_INTERNAL_DB_CORRUPTION;
4420 : }
4421 79 : in_transaction = true;
4422 : }
4423 :
4424 : /*
4425 : * abort if we are not a PDC
4426 : *
4427 : * In future we should use a function like IsEffectiveRoleOwner()
4428 : */
4429 87 : if (!samdb_is_pdc(p_state->sam_ldb)) {
4430 0 : status = NT_STATUS_INVALID_DOMAIN_ROLE;
4431 0 : goto done;
4432 : }
4433 :
4434 87 : if (r->in.trusted_domain_name->string == NULL) {
4435 0 : status = NT_STATUS_NO_SUCH_DOMAIN;
4436 0 : goto done;
4437 : }
4438 :
4439 87 : status = dsdb_trust_search_tdo(p_state->sam_ldb,
4440 87 : r->in.trusted_domain_name->string,
4441 87 : r->in.trusted_domain_name->string,
4442 : trust_attrs, mem_ctx, &trust_tdo_msg);
4443 87 : if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
4444 0 : status = NT_STATUS_NO_SUCH_DOMAIN;
4445 0 : goto done;
4446 : }
4447 87 : if (!NT_STATUS_IS_OK(status)) {
4448 0 : goto done;
4449 : }
4450 :
4451 87 : status = dsdb_trust_parse_tdo_info(mem_ctx, trust_tdo_msg, &trust_tdo);
4452 87 : if (!NT_STATUS_IS_OK(status)) {
4453 0 : goto done;
4454 : }
4455 :
4456 87 : if (!(trust_tdo->trust_attributes & LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE)) {
4457 0 : status = NT_STATUS_INVALID_PARAMETER;
4458 0 : goto done;
4459 : }
4460 :
4461 87 : if (r->in.highest_record_type >= LSA_FOREST_TRUST_RECORD_TYPE_LAST) {
4462 0 : status = NT_STATUS_INVALID_PARAMETER;
4463 0 : goto done;
4464 : }
4465 :
4466 : /*
4467 : * verify and normalize the given forest trust info.
4468 : *
4469 : * Step1: doesn't reorder yet, so step1_lfti might contain
4470 : * NULL entries. This means dsdb_trust_verify_forest_info()
4471 : * can generate collision entries with the callers index.
4472 : */
4473 87 : status = dsdb_trust_normalize_forest_info_step1(mem_ctx,
4474 87 : r->in.forest_trust_info,
4475 : &step1_lfti);
4476 87 : if (!NT_STATUS_IS_OK(status)) {
4477 0 : goto done;
4478 : }
4479 :
4480 87 : c_info = talloc_zero(r->out.collision_info,
4481 : struct lsa_ForestTrustCollisionInfo);
4482 87 : if (c_info == NULL) {
4483 0 : status = NT_STATUS_NO_MEMORY;
4484 0 : goto done;
4485 : }
4486 :
4487 : /*
4488 : * First check our own forest, then other domains/forests
4489 : */
4490 :
4491 87 : status = dsdb_trust_xref_tdo_info(mem_ctx, p_state->sam_ldb,
4492 : &xref_tdo);
4493 87 : if (!NT_STATUS_IS_OK(status)) {
4494 0 : goto done;
4495 : }
4496 87 : status = dsdb_trust_xref_forest_info(mem_ctx, p_state->sam_ldb,
4497 : &xref_lfti);
4498 87 : if (!NT_STATUS_IS_OK(status)) {
4499 0 : goto done;
4500 : }
4501 :
4502 : /*
4503 : * The documentation proposed to generate
4504 : * LSA_FOREST_TRUST_COLLISION_XREF collisions.
4505 : * But Windows always uses LSA_FOREST_TRUST_COLLISION_TDO.
4506 : */
4507 87 : status = dsdb_trust_verify_forest_info(xref_tdo, xref_lfti,
4508 : LSA_FOREST_TRUST_COLLISION_TDO,
4509 : c_info, step1_lfti);
4510 87 : if (!NT_STATUS_IS_OK(status)) {
4511 0 : goto done;
4512 : }
4513 :
4514 : /* fetch all other trusted domain objects */
4515 87 : status = dsdb_trust_search_tdos(p_state->sam_ldb,
4516 87 : trust_tdo->domain_name.string,
4517 : trust_attrs,
4518 : mem_ctx, &trusts_res);
4519 87 : if (!NT_STATUS_IS_OK(status)) {
4520 0 : goto done;
4521 : }
4522 :
4523 : /*
4524 : * now check against the other domains.
4525 : * and generate LSA_FOREST_TRUST_COLLISION_TDO collisions.
4526 : */
4527 87 : for (i = 0; i < trusts_res->count; i++) {
4528 0 : struct lsa_TrustDomainInfoInfoEx *tdo = NULL;
4529 0 : struct ForestTrustInfo *fti = NULL;
4530 0 : struct lsa_ForestTrustInformation *lfti = NULL;
4531 :
4532 0 : status = dsdb_trust_parse_tdo_info(mem_ctx,
4533 0 : trusts_res->msgs[i],
4534 : &tdo);
4535 0 : if (!NT_STATUS_IS_OK(status)) {
4536 0 : goto done;
4537 : }
4538 :
4539 0 : status = dsdb_trust_parse_forest_info(tdo,
4540 0 : trusts_res->msgs[i],
4541 : &fti);
4542 0 : if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
4543 0 : continue;
4544 : }
4545 0 : if (!NT_STATUS_IS_OK(status)) {
4546 0 : goto done;
4547 : }
4548 :
4549 0 : status = dsdb_trust_forest_info_to_lsa(tdo, fti, &lfti);
4550 0 : if (!NT_STATUS_IS_OK(status)) {
4551 0 : goto done;
4552 : }
4553 :
4554 0 : status = dsdb_trust_verify_forest_info(tdo, lfti,
4555 : LSA_FOREST_TRUST_COLLISION_TDO,
4556 : c_info, step1_lfti);
4557 0 : if (!NT_STATUS_IS_OK(status)) {
4558 0 : goto done;
4559 : }
4560 :
4561 0 : TALLOC_FREE(tdo);
4562 : }
4563 :
4564 87 : if (r->in.check_only != 0) {
4565 8 : status = NT_STATUS_OK;
4566 8 : goto done;
4567 : }
4568 :
4569 : /*
4570 : * not just a check, write info back
4571 : */
4572 :
4573 : /*
4574 : * normalize the given forest trust info.
4575 : *
4576 : * Step2: adds TOP_LEVEL_NAME[_EX] in reverse order,
4577 : * followed by DOMAIN_INFO in reverse order. It also removes
4578 : * possible NULL entries from Step1.
4579 : */
4580 79 : status = dsdb_trust_normalize_forest_info_step2(mem_ctx, step1_lfti,
4581 : &step2_lfti);
4582 79 : if (!NT_STATUS_IS_OK(status)) {
4583 0 : goto done;
4584 : }
4585 :
4586 79 : status = dsdb_trust_forest_info_from_lsa(mem_ctx, step2_lfti,
4587 : &trust_fti);
4588 79 : if (!NT_STATUS_IS_OK(status)) {
4589 0 : goto done;
4590 : }
4591 :
4592 79 : ndr_err = ndr_push_struct_blob(&ft_blob, mem_ctx, trust_fti,
4593 : (ndr_push_flags_fn_t)ndr_push_ForestTrustInfo);
4594 79 : if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
4595 0 : status = NT_STATUS_INVALID_PARAMETER;
4596 0 : goto done;
4597 : }
4598 :
4599 79 : msg = ldb_msg_new(mem_ctx);
4600 79 : if (msg == NULL) {
4601 0 : status = NT_STATUS_NO_MEMORY;
4602 0 : goto done;
4603 : }
4604 :
4605 79 : msg->dn = ldb_dn_copy(mem_ctx, trust_tdo_msg->dn);
4606 79 : if (!msg->dn) {
4607 0 : status = NT_STATUS_NO_MEMORY;
4608 0 : goto done;
4609 : }
4610 :
4611 79 : ret = ldb_msg_append_value(msg, "msDS-TrustForestTrustInfo",
4612 : &ft_blob, LDB_FLAG_MOD_REPLACE);
4613 79 : if (ret != LDB_SUCCESS) {
4614 0 : status = NT_STATUS_NO_MEMORY;
4615 0 : goto done;
4616 : }
4617 :
4618 79 : ret = ldb_modify(p_state->sam_ldb, msg);
4619 79 : if (ret != LDB_SUCCESS) {
4620 0 : status = dsdb_ldb_err_to_ntstatus(ret);
4621 :
4622 0 : DEBUG(0, ("Failed to store Forest Trust Info: %s\n",
4623 : ldb_errstring(p_state->sam_ldb)));
4624 :
4625 0 : goto done;
4626 : }
4627 :
4628 : /* ok, all fine, commit transaction and return */
4629 79 : in_transaction = false;
4630 79 : ret = ldb_transaction_commit(p_state->sam_ldb);
4631 79 : if (ret != LDB_SUCCESS) {
4632 0 : status = NT_STATUS_INTERNAL_DB_CORRUPTION;
4633 0 : goto done;
4634 : }
4635 :
4636 : /*
4637 : * Notify winbindd that we have a acquired forest trust info
4638 : */
4639 79 : status = irpc_servers_byname(imsg_ctx,
4640 : mem_ctx,
4641 : "winbind_server",
4642 : &num_server_ids,
4643 : &server_ids);
4644 79 : if (!NT_STATUS_IS_OK(status)) {
4645 0 : DBG_ERR("irpc_servers_byname failed\n");
4646 0 : goto done;
4647 : }
4648 :
4649 79 : imessaging_send(imsg_ctx,
4650 : server_ids[0],
4651 : MSG_WINBIND_RELOAD_TRUSTED_DOMAINS,
4652 : NULL);
4653 :
4654 79 : status = NT_STATUS_OK;
4655 :
4656 87 : done:
4657 87 : if (NT_STATUS_IS_OK(status) && c_info->count != 0) {
4658 20 : *r->out.collision_info = c_info;
4659 : }
4660 :
4661 87 : if (in_transaction) {
4662 0 : ldb_transaction_cancel(p_state->sam_ldb);
4663 : }
4664 :
4665 87 : return status;
4666 : }
4667 :
4668 : /*
4669 : lsa_CREDRRENAME
4670 : */
4671 0 : static NTSTATUS dcesrv_lsa_CREDRRENAME(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4672 : struct lsa_CREDRRENAME *r)
4673 : {
4674 0 : DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4675 : }
4676 :
4677 :
4678 :
4679 : /*
4680 : lsa_LSAROPENPOLICYSCE
4681 : */
4682 0 : static NTSTATUS dcesrv_lsa_LSAROPENPOLICYSCE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4683 : struct lsa_LSAROPENPOLICYSCE *r)
4684 : {
4685 0 : DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4686 : }
4687 :
4688 :
4689 : /*
4690 : lsa_LSARADTREGISTERSECURITYEVENTSOURCE
4691 : */
4692 0 : static NTSTATUS dcesrv_lsa_LSARADTREGISTERSECURITYEVENTSOURCE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4693 : struct lsa_LSARADTREGISTERSECURITYEVENTSOURCE *r)
4694 : {
4695 0 : DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4696 : }
4697 :
4698 :
4699 : /*
4700 : lsa_LSARADTUNREGISTERSECURITYEVENTSOURCE
4701 : */
4702 0 : static NTSTATUS dcesrv_lsa_LSARADTUNREGISTERSECURITYEVENTSOURCE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4703 : struct lsa_LSARADTUNREGISTERSECURITYEVENTSOURCE *r)
4704 : {
4705 0 : DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4706 : }
4707 :
4708 :
4709 : /*
4710 : lsa_LSARADTREPORTSECURITYEVENT
4711 : */
4712 0 : static NTSTATUS dcesrv_lsa_LSARADTREPORTSECURITYEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4713 : struct lsa_LSARADTREPORTSECURITYEVENT *r)
4714 : {
4715 0 : DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4716 : }
4717 :
4718 :
4719 : /* include the generated boilerplate */
4720 : #include "librpc/gen_ndr/ndr_lsa_s.c"
4721 :
4722 :
4723 :
4724 : /*****************************************
4725 : NOTE! The remaining calls below were
4726 : removed in w2k3, so the DCESRV_FAULT()
4727 : replies are the correct implementation. Do
4728 : not try and fill these in with anything else
4729 : ******************************************/
4730 :
4731 : /*
4732 : dssetup_DsRoleDnsNameToFlatName
4733 : */
4734 0 : static WERROR dcesrv_dssetup_DsRoleDnsNameToFlatName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4735 : struct dssetup_DsRoleDnsNameToFlatName *r)
4736 : {
4737 0 : DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4738 : }
4739 :
4740 :
4741 : /*
4742 : dssetup_DsRoleDcAsDc
4743 : */
4744 0 : static WERROR dcesrv_dssetup_DsRoleDcAsDc(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4745 : struct dssetup_DsRoleDcAsDc *r)
4746 : {
4747 0 : DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4748 : }
4749 :
4750 :
4751 : /*
4752 : dssetup_DsRoleDcAsReplica
4753 : */
4754 0 : static WERROR dcesrv_dssetup_DsRoleDcAsReplica(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4755 : struct dssetup_DsRoleDcAsReplica *r)
4756 : {
4757 0 : DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4758 : }
4759 :
4760 :
4761 : /*
4762 : dssetup_DsRoleDemoteDc
4763 : */
4764 0 : static WERROR dcesrv_dssetup_DsRoleDemoteDc(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4765 : struct dssetup_DsRoleDemoteDc *r)
4766 : {
4767 0 : DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4768 : }
4769 :
4770 :
4771 : /*
4772 : dssetup_DsRoleGetDcOperationProgress
4773 : */
4774 0 : static WERROR dcesrv_dssetup_DsRoleGetDcOperationProgress(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4775 : struct dssetup_DsRoleGetDcOperationProgress *r)
4776 : {
4777 0 : DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4778 : }
4779 :
4780 :
4781 : /*
4782 : dssetup_DsRoleGetDcOperationResults
4783 : */
4784 0 : static WERROR dcesrv_dssetup_DsRoleGetDcOperationResults(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4785 : struct dssetup_DsRoleGetDcOperationResults *r)
4786 : {
4787 0 : DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4788 : }
4789 :
4790 :
4791 : /*
4792 : dssetup_DsRoleCancel
4793 : */
4794 0 : static WERROR dcesrv_dssetup_DsRoleCancel(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4795 : struct dssetup_DsRoleCancel *r)
4796 : {
4797 0 : DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4798 : }
4799 :
4800 :
4801 : /*
4802 : dssetup_DsRoleServerSaveStateForUpgrade
4803 : */
4804 0 : static WERROR dcesrv_dssetup_DsRoleServerSaveStateForUpgrade(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4805 : struct dssetup_DsRoleServerSaveStateForUpgrade *r)
4806 : {
4807 0 : DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4808 : }
4809 :
4810 :
4811 : /*
4812 : dssetup_DsRoleUpgradeDownlevelServer
4813 : */
4814 0 : static WERROR dcesrv_dssetup_DsRoleUpgradeDownlevelServer(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4815 : struct dssetup_DsRoleUpgradeDownlevelServer *r)
4816 : {
4817 0 : DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4818 : }
4819 :
4820 :
4821 : /*
4822 : dssetup_DsRoleAbortDownlevelServerUpgrade
4823 : */
4824 0 : static WERROR dcesrv_dssetup_DsRoleAbortDownlevelServerUpgrade(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4825 : struct dssetup_DsRoleAbortDownlevelServerUpgrade *r)
4826 : {
4827 0 : DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4828 : }
4829 :
4830 :
4831 : /* include the generated boilerplate */
4832 : #include "librpc/gen_ndr/ndr_dssetup_s.c"
4833 :
4834 66 : NTSTATUS dcerpc_server_lsa_init(TALLOC_CTX *ctx)
4835 : {
4836 2 : NTSTATUS ret;
4837 :
4838 66 : ret = dcerpc_server_dssetup_init(ctx);
4839 66 : if (!NT_STATUS_IS_OK(ret)) {
4840 0 : return ret;
4841 : }
4842 66 : ret = dcerpc_server_lsarpc_init(ctx);
4843 66 : if (!NT_STATUS_IS_OK(ret)) {
4844 0 : return ret;
4845 : }
4846 66 : return ret;
4847 : }
|