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 3163 : static NTSTATUS dcesrv_interface_lsarpc_bind(struct dcesrv_connection_context *context,
49 : const struct dcesrv_interface *iface)
50 : {
51 3163 : 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 52 : static NTSTATUS dcesrv_interface_lsarpc_init_server(struct dcesrv_context *dce_ctx,
65 : const struct dcesrv_endpoint_server *ep_server)
66 : {
67 52 : 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 52 : 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 121 : static bool dcesrc_lsa_valid_AccountRight(const char *right)
116 : {
117 : enum sec_privilege priv_id;
118 : uint32_t right_bit;
119 :
120 121 : priv_id = sec_privilege_id(right);
121 121 : if (priv_id != SEC_PRIV_INVALID) {
122 113 : 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 : NTSTATUS status;
143 : uint32_t rid;
144 : struct dom_sid *domain_sid, *domain_admins_sid;
145 : 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 706 : static NTSTATUS dcesrv_lsa_Close(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
219 : struct lsa_Close *r)
220 : {
221 556 : enum dcerpc_transport_t transport =
222 706 : dcerpc_binding_get_transport(dce_call->conn->endpoint->ep_description);
223 : struct dcesrv_handle *h;
224 :
225 706 : if (transport != NCACN_NP && transport != NCALRPC) {
226 0 : DCESRV_FAULT(DCERPC_FAULT_ACCESS_DENIED);
227 : }
228 :
229 706 : *r->out.handle = *r->in.handle;
230 :
231 706 : DCESRV_PULL_HANDLE(h, r->in.handle, DCESRV_HANDLE_ANY);
232 :
233 633 : talloc_free(h);
234 :
235 633 : ZERO_STRUCTP(r->out.handle);
236 :
237 633 : return NT_STATUS_OK;
238 : }
239 :
240 :
241 : /*
242 : lsa_Delete
243 : */
244 19 : static NTSTATUS dcesrv_lsa_Delete(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
245 : struct lsa_Delete *r)
246 : {
247 19 : return NT_STATUS_NOT_SUPPORTED;
248 : }
249 :
250 :
251 : /*
252 : lsa_DeleteObject
253 : */
254 1770 : static NTSTATUS dcesrv_lsa_DeleteObject(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
255 : struct lsa_DeleteObject *r)
256 : {
257 1098 : struct auth_session_info *session_info =
258 672 : dcesrv_call_session_info(dce_call);
259 : struct dcesrv_handle *h;
260 : int ret;
261 :
262 1770 : DCESRV_PULL_HANDLE(h, r->in.handle, DCESRV_HANDLE_ANY);
263 :
264 1770 : if (h->wire_handle.handle_type == LSA_HANDLE_SECRET) {
265 1652 : struct lsa_secret_state *secret_state = h->data;
266 :
267 : /* Ensure user is permitted to delete this... */
268 1652 : switch (security_session_user_level(session_info, NULL))
269 : {
270 1652 : case SECURITY_SYSTEM:
271 : case SECURITY_ADMINISTRATOR:
272 1652 : break;
273 0 : default:
274 : /* Users and anonymous are not allowed to delete things */
275 0 : return NT_STATUS_ACCESS_DENIED;
276 : }
277 :
278 1652 : ret = ldb_delete(secret_state->sam_ldb,
279 : secret_state->secret_dn);
280 1652 : if (ret != LDB_SUCCESS) {
281 10 : return NT_STATUS_INVALID_HANDLE;
282 : }
283 :
284 1642 : ZERO_STRUCTP(r->out.handle);
285 :
286 1642 : return NT_STATUS_OK;
287 :
288 118 : } else if (h->wire_handle.handle_type == LSA_HANDLE_TRUSTED_DOMAIN) {
289 111 : struct lsa_trusted_domain_state *trusted_domain_state =
290 111 : talloc_get_type(h->data, struct lsa_trusted_domain_state);
291 111 : ret = ldb_transaction_start(trusted_domain_state->policy->sam_ldb);
292 111 : if (ret != LDB_SUCCESS) {
293 0 : return NT_STATUS_INTERNAL_DB_CORRUPTION;
294 : }
295 :
296 111 : ret = ldb_delete(trusted_domain_state->policy->sam_ldb,
297 : trusted_domain_state->trusted_domain_dn);
298 111 : 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 111 : if (trusted_domain_state->trusted_domain_user_dn) {
304 51 : ret = ldb_delete(trusted_domain_state->policy->sam_ldb,
305 : trusted_domain_state->trusted_domain_user_dn);
306 51 : 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 111 : ret = ldb_transaction_commit(trusted_domain_state->policy->sam_ldb);
313 111 : if (ret != LDB_SUCCESS) {
314 0 : return NT_STATUS_INTERNAL_DB_CORRUPTION;
315 : }
316 :
317 111 : ZERO_STRUCTP(r->out.handle);
318 :
319 111 : return NT_STATUS_OK;
320 :
321 7 : } else if (h->wire_handle.handle_type == LSA_HANDLE_ACCOUNT) {
322 : struct lsa_RightSet *rights;
323 : struct lsa_account_state *astate;
324 : struct lsa_EnumAccountRights r2;
325 : 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 : struct dcesrv_handle *h;
376 : uint32_t i;
377 : enum sec_privilege priv;
378 : 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 156 : while (((priv = sec_privilege_from_index(i)) != SEC_PRIV_INVALID) &&
385 75 : r->out.privs->count < r->in.max_count) {
386 : 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 12 : 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 0 : dcesrv_call_session_info(dce_call);
417 : struct dcesrv_handle *h;
418 12 : const struct security_descriptor *sd = NULL;
419 12 : uint32_t access_granted = 0;
420 12 : struct sec_desc_buf *sdbuf = NULL;
421 : NTSTATUS status;
422 : struct dom_sid *sid;
423 :
424 12 : DCESRV_PULL_HANDLE(h, r->in.handle, DCESRV_HANDLE_ANY);
425 :
426 12 : sid = &session_info->security_token->sids[PRIMARY_USER_SID_INDEX];
427 :
428 12 : if (h->wire_handle.handle_type == LSA_HANDLE_POLICY) {
429 12 : struct lsa_policy_state *pstate = h->data;
430 :
431 12 : sd = pstate->sd;
432 12 : 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 12 : sdbuf = talloc_zero(mem_ctx, struct sec_desc_buf);
450 12 : if (sdbuf == NULL) {
451 0 : return NT_STATUS_NO_MEMORY;
452 : }
453 :
454 12 : status = security_descriptor_for_client(sdbuf, sd, r->in.sec_info,
455 : access_granted, &sdbuf->sd);
456 12 : if (!NT_STATUS_IS_OK(status)) {
457 0 : return status;
458 : }
459 :
460 12 : *r->out.sdbuf = sdbuf;
461 :
462 12 : 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 78 : static WERROR dcesrv_dssetup_DsRoleGetPrimaryDomainInformation(struct dcesrv_call_state *dce_call,
492 : TALLOC_CTX *mem_ctx,
493 : struct dssetup_DsRoleGetPrimaryDomainInformation *r)
494 : {
495 : union dssetup_DsRoleInfo *info;
496 :
497 78 : info = talloc_zero(mem_ctx, union dssetup_DsRoleInfo);
498 78 : W_ERROR_HAVE_NO_MEMORY(info);
499 :
500 78 : switch (r->in.level) {
501 48 : case DS_ROLE_BASIC_INFORMATION:
502 : {
503 48 : enum dssetup_DsRole role = DS_ROLE_STANDALONE_SERVER;
504 48 : uint32_t flags = 0;
505 48 : const char *domain = NULL;
506 48 : const char *dns_domain = NULL;
507 48 : const char *forest = NULL;
508 : struct GUID domain_guid;
509 : struct lsa_policy_state *state;
510 :
511 48 : NTSTATUS status = dcesrv_lsa_get_policy_state(dce_call, mem_ctx,
512 : 0, /* we skip access checks */
513 : &state);
514 48 : if (!NT_STATUS_IS_OK(status)) {
515 0 : return ntstatus_to_werror(status);
516 : }
517 :
518 48 : ZERO_STRUCT(domain_guid);
519 :
520 48 : 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 44 : case ROLE_ACTIVE_DIRECTORY_DC:
528 44 : if (samdb_is_pdc(state->sam_ldb)) {
529 44 : role = DS_ROLE_PRIMARY_DC;
530 : } else {
531 0 : role = DS_ROLE_BACKUP_DC;
532 : }
533 44 : break;
534 : }
535 :
536 48 : 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 44 : case ROLE_ACTIVE_DIRECTORY_DC:
547 44 : flags = DS_ROLE_PRIMARY_DS_RUNNING;
548 :
549 44 : if (state->mixed_domain == 1) {
550 0 : flags |= DS_ROLE_PRIMARY_DS_MIXED_MODE;
551 : }
552 :
553 44 : domain = state->domain_name;
554 44 : dns_domain = state->domain_dns;
555 44 : forest = state->forest_dns;
556 :
557 44 : domain_guid = state->domain_guid;
558 44 : flags |= DS_ROLE_PRIMARY_DOMAIN_GUID_PRESENT;
559 44 : break;
560 : }
561 :
562 48 : info->basic.role = role;
563 48 : info->basic.flags = flags;
564 48 : info->basic.domain = domain;
565 48 : info->basic.dns_domain = dns_domain;
566 48 : info->basic.forest = forest;
567 48 : info->basic.domain_guid = domain_guid;
568 :
569 48 : r->out.info = info;
570 48 : return WERR_OK;
571 : }
572 15 : case DS_ROLE_UPGRADE_STATUS:
573 : {
574 15 : info->upgrade.upgrading = DS_ROLE_NOT_UPGRADING;
575 15 : info->upgrade.previous_role = DS_ROLE_PREVIOUS_UNKNOWN;
576 :
577 15 : r->out.info = info;
578 15 : return WERR_OK;
579 : }
580 15 : case DS_ROLE_OP_STATUS:
581 : {
582 15 : info->opstatus.status = DS_ROLE_OP_IDLE;
583 :
584 15 : r->out.info = info;
585 15 : 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 457 : static NTSTATUS dcesrv_lsa_info_AccountDomain(struct lsa_policy_state *state, TALLOC_CTX *mem_ctx,
596 : struct lsa_DomainInfo *info)
597 : {
598 457 : info->name.string = state->domain_name;
599 457 : info->sid = state->domain_sid;
600 :
601 457 : return NT_STATUS_OK;
602 : }
603 :
604 : /*
605 : fill in the DNS domain info
606 : */
607 568 : static NTSTATUS dcesrv_lsa_info_DNS(struct lsa_policy_state *state, TALLOC_CTX *mem_ctx,
608 : struct lsa_DnsDomainInfo *info)
609 : {
610 568 : info->name.string = state->domain_name;
611 568 : info->sid = state->domain_sid;
612 568 : info->dns_domain.string = state->domain_dns;
613 568 : info->dns_forest.string = state->forest_dns;
614 568 : info->domain_guid = state->domain_guid;
615 :
616 568 : return NT_STATUS_OK;
617 : }
618 :
619 : /*
620 : lsa_QueryInfoPolicy2
621 : */
622 1133 : static NTSTATUS dcesrv_lsa_QueryInfoPolicy2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
623 : struct lsa_QueryInfoPolicy2 *r)
624 : {
625 : struct lsa_policy_state *state;
626 : struct dcesrv_handle *h;
627 : union lsa_PolicyInformation *info;
628 :
629 1133 : *r->out.info = NULL;
630 :
631 1133 : DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
632 :
633 1133 : state = h->data;
634 :
635 1133 : info = talloc_zero(mem_ctx, union lsa_PolicyInformation);
636 1133 : if (!info) {
637 0 : return NT_STATUS_NO_MEMORY;
638 : }
639 1133 : *r->out.info = info;
640 :
641 1133 : switch (r->in.level) {
642 12 : case LSA_POLICY_INFO_AUDIT_LOG:
643 : /* we don't need to fill in any of this */
644 12 : ZERO_STRUCT(info->audit_log);
645 12 : return NT_STATUS_OK;
646 12 : case LSA_POLICY_INFO_AUDIT_EVENTS:
647 : /* we don't need to fill in any of this */
648 12 : ZERO_STRUCT(info->audit_events);
649 12 : return NT_STATUS_OK;
650 12 : case LSA_POLICY_INFO_PD:
651 : /* we don't need to fill in any of this */
652 12 : ZERO_STRUCT(info->pd);
653 12 : return NT_STATUS_OK;
654 :
655 293 : case LSA_POLICY_INFO_DOMAIN:
656 293 : return dcesrv_lsa_info_AccountDomain(state, mem_ctx, &info->domain);
657 152 : case LSA_POLICY_INFO_ACCOUNT_DOMAIN:
658 152 : return dcesrv_lsa_info_AccountDomain(state, mem_ctx, &info->account_domain);
659 12 : case LSA_POLICY_INFO_L_ACCOUNT_DOMAIN:
660 12 : return dcesrv_lsa_info_AccountDomain(state, mem_ctx, &info->l_account_domain);
661 :
662 12 : case LSA_POLICY_INFO_ROLE:
663 12 : info->role.role = LSA_ROLE_PRIMARY;
664 12 : return NT_STATUS_OK;
665 :
666 568 : case LSA_POLICY_INFO_DNS:
667 : case LSA_POLICY_INFO_DNS_INT:
668 568 : return dcesrv_lsa_info_DNS(state, mem_ctx, &info->dns);
669 :
670 12 : case LSA_POLICY_INFO_REPLICA:
671 12 : ZERO_STRUCT(info->replica);
672 12 : return NT_STATUS_OK;
673 :
674 12 : case LSA_POLICY_INFO_QUOTA:
675 12 : ZERO_STRUCT(info->quota);
676 12 : return NT_STATUS_OK;
677 :
678 36 : 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 36 : *r->out.info = NULL;
683 36 : 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 505 : static NTSTATUS dcesrv_lsa_QueryInfoPolicy(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
694 : struct lsa_QueryInfoPolicy *r)
695 : {
696 : struct lsa_QueryInfoPolicy2 r2;
697 : NTSTATUS status;
698 :
699 505 : ZERO_STRUCT(r2);
700 :
701 505 : r2.in.handle = r->in.handle;
702 505 : r2.in.level = r->in.level;
703 505 : r2.out.info = r->out.info;
704 :
705 505 : status = dcesrv_lsa_QueryInfoPolicy2(dce_call, mem_ctx, &r2);
706 :
707 505 : 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 : struct lsa_account_state *astate;
754 :
755 : struct lsa_policy_state *state;
756 : 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 : struct dcesrv_handle *h;
815 : struct lsa_policy_state *state;
816 : int ret;
817 : struct ldb_message **res;
818 18 : const char * const attrs[] = { "objectSid", NULL};
819 : 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 196 : 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 61 : 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 61 : DATA_BLOB session_key = data_blob(NULL, 0);
872 : enum ndr_err_code ndr_err;
873 : NTSTATUS nt_status;
874 61 : gnutls_cipher_hd_t cipher_hnd = NULL;
875 : gnutls_datum_t _session_key;
876 : int rc;
877 51 : struct auth_session_info *session_info =
878 10 : dcesrv_call_session_info(dce_call);
879 61 : struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
880 : bool encrypted;
881 :
882 51 : encrypted =
883 10 : dcerpc_is_transport_encrypted(session_info);
884 61 : 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 61 : nt_status = dcesrv_transport_session_key(dce_call, &session_key);
892 61 : if (!NT_STATUS_IS_OK(nt_status)) {
893 0 : return nt_status;
894 : }
895 :
896 61 : _session_key = (gnutls_datum_t) {
897 61 : .data = session_key.data,
898 61 : .size = session_key.length,
899 : };
900 :
901 10 : GNUTLS_FIPS140_SET_LAX_MODE();
902 61 : rc = gnutls_cipher_init(&cipher_hnd,
903 : GNUTLS_CIPHER_ARCFOUR_128,
904 : &_session_key,
905 : NULL);
906 61 : 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 112 : rc = gnutls_cipher_decrypt(cipher_hnd,
913 61 : auth_blob->data,
914 : auth_blob->length);
915 61 : gnutls_cipher_deinit(cipher_hnd);
916 10 : GNUTLS_FIPS140_SET_STRICT_MODE();
917 61 : if (rc < 0) {
918 0 : nt_status = gnutls_error_to_ntstatus(rc, NT_STATUS_CRYPTO_SYSTEM_INVALID);
919 0 : goto out;
920 : }
921 :
922 61 : ndr_err = ndr_pull_struct_blob(auth_blob, mem_ctx,
923 : auth_struct,
924 : (ndr_pull_flags_fn_t)ndr_pull_trustDomainPasswords);
925 61 : if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
926 0 : return NT_STATUS_INVALID_PARAMETER;
927 : }
928 :
929 61 : nt_status = NT_STATUS_OK;
930 61 : out:
931 61 : return nt_status;
932 : }
933 :
934 116 : 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 : enum ndr_err_code ndr_err;
940 :
941 116 : if (iopw->current.count != iopw->count) {
942 0 : return NT_STATUS_INVALID_PARAMETER;
943 : }
944 :
945 116 : if (iopw->previous.count > iopw->current.count) {
946 0 : return NT_STATUS_INVALID_PARAMETER;
947 : }
948 :
949 116 : if (iopw->previous.count == 0) {
950 : /*
951 : * If the previous credentials are not present
952 : * we need to make a copy.
953 : */
954 44 : iopw->previous = iopw->current;
955 : }
956 :
957 116 : 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 116 : ndr_err = ndr_push_struct_blob(trustauth_blob, mem_ctx,
987 : iopw,
988 : (ndr_push_flags_fn_t)ndr_push_trustAuthInOutBlob);
989 116 : if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
990 0 : return NT_STATUS_INVALID_PARAMETER;
991 : }
992 :
993 116 : return NT_STATUS_OK;
994 : }
995 :
996 70 : 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 : struct ldb_request *req;
1004 : struct ldb_message *msg;
1005 : struct ldb_dn *dn;
1006 : uint32_t i;
1007 : int ret;
1008 :
1009 70 : dn = ldb_dn_copy(mem_ctx, base_dn);
1010 70 : if (!dn) {
1011 0 : return NT_STATUS_NO_MEMORY;
1012 : }
1013 70 : if (!ldb_dn_add_child_fmt(dn, "cn=%s$,cn=users", netbios_name)) {
1014 0 : return NT_STATUS_NO_MEMORY;
1015 : }
1016 :
1017 70 : msg = ldb_msg_new(mem_ctx);
1018 70 : if (!msg) {
1019 0 : return NT_STATUS_NO_MEMORY;
1020 : }
1021 70 : msg->dn = dn;
1022 :
1023 70 : ret = ldb_msg_add_string(msg, "objectClass", "user");
1024 70 : if (ret != LDB_SUCCESS) {
1025 0 : return NT_STATUS_NO_MEMORY;
1026 : }
1027 :
1028 70 : ret = ldb_msg_add_fmt(msg, "samAccountName", "%s$", netbios_name);
1029 70 : if (ret != LDB_SUCCESS) {
1030 0 : return NT_STATUS_NO_MEMORY;
1031 : }
1032 :
1033 70 : ret = samdb_msg_add_uint(sam_ldb, msg, msg, "userAccountControl",
1034 : UF_INTERDOMAIN_TRUST_ACCOUNT);
1035 70 : if (ret != LDB_SUCCESS) {
1036 0 : return NT_STATUS_NO_MEMORY;
1037 : }
1038 :
1039 116 : for (i = 0; i < in->count; i++) {
1040 : const char *attribute;
1041 : struct ldb_val v;
1042 46 : 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 46 : case TRUST_AUTH_TYPE_CLEAR:
1049 46 : attribute = "clearTextPassword";
1050 46 : v.data = in->current.array[i].AuthInfo.clear.password;
1051 46 : v.length = in->current.array[i].AuthInfo.clear.size;
1052 46 : break;
1053 0 : default:
1054 0 : continue;
1055 : }
1056 :
1057 46 : ret = ldb_msg_add_value(msg, attribute, &v, NULL);
1058 46 : if (ret != LDB_SUCCESS) {
1059 0 : return NT_STATUS_NO_MEMORY;
1060 : }
1061 : }
1062 :
1063 : /* create the trusted_domain user account */
1064 70 : ret = ldb_build_add_req(&req, sam_ldb, mem_ctx, msg, NULL, NULL,
1065 : ldb_op_default_callback, NULL);
1066 70 : if (ret != LDB_SUCCESS) {
1067 0 : return NT_STATUS_NO_MEMORY;
1068 : }
1069 :
1070 70 : ret = ldb_request_add_control(req, DSDB_CONTROL_PERMIT_INTERDOMAIN_TRUST_UAC_OID,
1071 : false, NULL);
1072 70 : if (ret != LDB_SUCCESS) {
1073 0 : return NT_STATUS_NO_MEMORY;
1074 : }
1075 :
1076 70 : ret = dsdb_autotransaction_request(sam_ldb, req);
1077 70 : 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 70 : if (user_dn) {
1093 70 : *user_dn = dn;
1094 : }
1095 70 : return NT_STATUS_OK;
1096 : }
1097 :
1098 : /*
1099 : lsa_CreateTrustedDomainEx2
1100 : */
1101 133 : 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 : struct dcesrv_handle *policy_handle;
1108 : struct lsa_policy_state *policy_state;
1109 : struct lsa_trusted_domain_state *trusted_domain_state;
1110 : struct dcesrv_handle *handle;
1111 : struct ldb_message **msgs, *msg;
1112 133 : const char *attrs[] = {
1113 : NULL
1114 : };
1115 : const char *netbios_name;
1116 : const char *dns_name;
1117 : DATA_BLOB trustAuthIncoming, trustAuthOutgoing, auth_blob;
1118 : struct trustDomainPasswords auth_struct;
1119 : int ret;
1120 : NTSTATUS nt_status;
1121 : struct ldb_context *sam_ldb;
1122 133 : struct server_id *server_ids = NULL;
1123 133 : uint32_t num_server_ids = 0;
1124 : NTSTATUS status;
1125 : bool ok;
1126 133 : char *dns_encoded = NULL;
1127 133 : char *netbios_encoded = NULL;
1128 133 : char *sid_encoded = NULL;
1129 123 : struct imessaging_context *imsg_ctx =
1130 133 : dcesrv_imessaging_context(dce_call->conn);
1131 :
1132 133 : DCESRV_PULL_HANDLE(policy_handle, r->in.policy_handle, LSA_HANDLE_POLICY);
1133 133 : ZERO_STRUCTP(r->out.trustdom_handle);
1134 :
1135 133 : policy_state = policy_handle->data;
1136 133 : sam_ldb = policy_state->sam_ldb;
1137 :
1138 133 : netbios_name = r->in.info->netbios_name.string;
1139 133 : if (!netbios_name) {
1140 0 : return NT_STATUS_INVALID_PARAMETER;
1141 : }
1142 :
1143 133 : dns_name = r->in.info->domain_name.string;
1144 133 : if (dns_name == NULL) {
1145 0 : return NT_STATUS_INVALID_PARAMETER;
1146 : }
1147 :
1148 133 : 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 133 : ok = dom_sid_is_valid_account_domain(r->in.info->sid);
1158 133 : if (!ok) {
1159 0 : return NT_STATUS_INVALID_PARAMETER;
1160 : }
1161 :
1162 133 : dns_encoded = ldb_binary_encode_string(mem_ctx, dns_name);
1163 133 : if (dns_encoded == NULL) {
1164 0 : return NT_STATUS_NO_MEMORY;
1165 : }
1166 133 : netbios_encoded = ldb_binary_encode_string(mem_ctx, netbios_name);
1167 133 : if (netbios_encoded == NULL) {
1168 0 : return NT_STATUS_NO_MEMORY;
1169 : }
1170 133 : sid_encoded = ldap_encode_ndr_dom_sid(mem_ctx, r->in.info->sid);
1171 133 : if (sid_encoded == NULL) {
1172 0 : return NT_STATUS_NO_MEMORY;
1173 : }
1174 :
1175 133 : trusted_domain_state = talloc_zero(mem_ctx, struct lsa_trusted_domain_state);
1176 133 : if (!trusted_domain_state) {
1177 0 : return NT_STATUS_NO_MEMORY;
1178 : }
1179 133 : trusted_domain_state->policy = policy_state;
1180 :
1181 133 : if (strcasecmp(netbios_name, "BUILTIN") == 0
1182 133 : || (strcasecmp(dns_name, "BUILTIN") == 0)
1183 133 : || (dom_sid_in_domain(policy_state->builtin_sid, r->in.info->sid))) {
1184 0 : return NT_STATUS_INVALID_PARAMETER;
1185 : }
1186 :
1187 133 : if (strcasecmp(netbios_name, policy_state->domain_name) == 0
1188 133 : || strcasecmp(netbios_name, policy_state->domain_dns) == 0
1189 133 : || strcasecmp(dns_name, policy_state->domain_dns) == 0
1190 133 : || strcasecmp(dns_name, policy_state->domain_name) == 0
1191 133 : || (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 133 : 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 97 : } else if (op == NDR_LSA_CREATETRUSTEDDOMAINEX2) {
1201 61 : auth_blob = data_blob_const(r->in.auth_info_internal->auth_blob.data,
1202 61 : r->in.auth_info_internal->auth_blob.size);
1203 61 : nt_status = get_trustdom_auth_blob(dce_call, mem_ctx,
1204 : &auth_blob, &auth_struct);
1205 61 : 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 133 : if (auth_struct.incoming.count) {
1223 58 : nt_status = get_trustauth_inout_blob(dce_call, mem_ctx,
1224 : &auth_struct.incoming,
1225 : &trustAuthIncoming);
1226 58 : 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 133 : if (auth_struct.outgoing.count) {
1234 58 : nt_status = get_trustauth_inout_blob(dce_call, mem_ctx,
1235 : &auth_struct.outgoing,
1236 : &trustAuthOutgoing);
1237 58 : 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 133 : ret = ldb_transaction_start(sam_ldb);
1245 133 : if (ret != LDB_SUCCESS) {
1246 0 : return NT_STATUS_INTERNAL_DB_CORRUPTION;
1247 : }
1248 :
1249 : /* search for the trusted_domain record */
1250 133 : 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 133 : if (ret > 0) {
1260 0 : ldb_transaction_cancel(sam_ldb);
1261 0 : return NT_STATUS_OBJECT_NAME_COLLISION;
1262 : }
1263 133 : if (ret < 0) {
1264 0 : ldb_transaction_cancel(sam_ldb);
1265 0 : return NT_STATUS_INTERNAL_DB_CORRUPTION;
1266 : }
1267 :
1268 133 : msg = ldb_msg_new(mem_ctx);
1269 133 : if (msg == NULL) {
1270 0 : return NT_STATUS_NO_MEMORY;
1271 : }
1272 :
1273 133 : msg->dn = ldb_dn_copy(mem_ctx, policy_state->system_dn);
1274 133 : 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 133 : ret = ldb_msg_add_string(msg, "objectClass", "trustedDomain");
1280 133 : if (ret != LDB_SUCCESS) {
1281 0 : ldb_transaction_cancel(sam_ldb);
1282 0 : return NT_STATUS_NO_MEMORY;;
1283 : }
1284 :
1285 133 : ret = ldb_msg_add_string(msg, "flatname", netbios_name);
1286 133 : if (ret != LDB_SUCCESS) {
1287 0 : ldb_transaction_cancel(sam_ldb);
1288 0 : return NT_STATUS_NO_MEMORY;
1289 : }
1290 :
1291 133 : ret = ldb_msg_add_string(msg, "trustPartner", dns_name);
1292 133 : if (ret != LDB_SUCCESS) {
1293 0 : ldb_transaction_cancel(sam_ldb);
1294 0 : return NT_STATUS_NO_MEMORY;;
1295 : }
1296 :
1297 133 : ret = samdb_msg_add_dom_sid(sam_ldb, mem_ctx, msg, "securityIdentifier",
1298 133 : r->in.info->sid);
1299 133 : if (ret != LDB_SUCCESS) {
1300 0 : ldb_transaction_cancel(sam_ldb);
1301 0 : return NT_STATUS_NO_MEMORY;;
1302 : }
1303 :
1304 133 : ret = samdb_msg_add_int(sam_ldb, mem_ctx, msg, "trustType", r->in.info->trust_type);
1305 133 : if (ret != LDB_SUCCESS) {
1306 0 : ldb_transaction_cancel(sam_ldb);
1307 0 : return NT_STATUS_NO_MEMORY;;
1308 : }
1309 :
1310 133 : ret = samdb_msg_add_int(sam_ldb, mem_ctx, msg, "trustAttributes", r->in.info->trust_attributes);
1311 133 : if (ret != LDB_SUCCESS) {
1312 0 : ldb_transaction_cancel(sam_ldb);
1313 0 : return NT_STATUS_NO_MEMORY;;
1314 : }
1315 :
1316 133 : ret = samdb_msg_add_int(sam_ldb, mem_ctx, msg, "trustDirection", r->in.info->trust_direction);
1317 133 : if (ret != LDB_SUCCESS) {
1318 0 : ldb_transaction_cancel(sam_ldb);
1319 0 : return NT_STATUS_NO_MEMORY;;
1320 : }
1321 :
1322 133 : if (trustAuthIncoming.data) {
1323 58 : ret = ldb_msg_add_value(msg, "trustAuthIncoming", &trustAuthIncoming, NULL);
1324 58 : if (ret != LDB_SUCCESS) {
1325 0 : ldb_transaction_cancel(sam_ldb);
1326 0 : return NT_STATUS_NO_MEMORY;
1327 : }
1328 : }
1329 133 : if (trustAuthOutgoing.data) {
1330 58 : ret = ldb_msg_add_value(msg, "trustAuthOutgoing", &trustAuthOutgoing, NULL);
1331 58 : if (ret != LDB_SUCCESS) {
1332 0 : ldb_transaction_cancel(sam_ldb);
1333 0 : return NT_STATUS_NO_MEMORY;
1334 : }
1335 : }
1336 :
1337 133 : trusted_domain_state->trusted_domain_dn = talloc_reference(trusted_domain_state, msg->dn);
1338 :
1339 : /* create the trusted_domain */
1340 133 : ret = ldb_add(sam_ldb, msg);
1341 133 : switch (ret) {
1342 133 : case LDB_SUCCESS:
1343 133 : 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 133 : if (r->in.info->trust_direction & LSA_TRUST_DIRECTION_INBOUND) {
1365 : struct ldb_dn *user_dn;
1366 : /* Inbound trusts must also create a cn=users object to match */
1367 70 : 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 70 : 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 : trusted_domain_state->trusted_domain_user_dn
1379 70 : = talloc_steal(trusted_domain_state, user_dn);
1380 : }
1381 :
1382 133 : ret = ldb_transaction_commit(sam_ldb);
1383 133 : 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 133 : status = irpc_servers_byname(imsg_ctx,
1391 : mem_ctx,
1392 : "winbind_server",
1393 : &num_server_ids,
1394 : &server_ids);
1395 133 : if (NT_STATUS_IS_OK(status) && num_server_ids >= 1) {
1396 133 : imessaging_send(imsg_ctx,
1397 : server_ids[0],
1398 : MSG_WINBIND_RELOAD_TRUSTED_DOMAINS,
1399 : NULL);
1400 : }
1401 133 : TALLOC_FREE(server_ids);
1402 :
1403 133 : handle = dcesrv_handle_create(dce_call, LSA_HANDLE_TRUSTED_DOMAIN);
1404 133 : if (!handle) {
1405 0 : return NT_STATUS_NO_MEMORY;
1406 : }
1407 :
1408 133 : handle->data = talloc_steal(handle, trusted_domain_state);
1409 :
1410 133 : trusted_domain_state->access_mask = r->in.access_mask;
1411 133 : trusted_domain_state->policy = talloc_reference(trusted_domain_state, policy_state);
1412 :
1413 133 : *r->out.trustdom_handle = handle->wire_handle;
1414 :
1415 133 : return NT_STATUS_OK;
1416 : }
1417 :
1418 : /*
1419 : lsa_CreateTrustedDomainEx2
1420 : */
1421 61 : static NTSTATUS dcesrv_lsa_CreateTrustedDomainEx2(struct dcesrv_call_state *dce_call,
1422 : TALLOC_CTX *mem_ctx,
1423 : struct lsa_CreateTrustedDomainEx2 *r)
1424 : {
1425 61 : 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 : 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 : 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 3421 : 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 : struct lsa_trusted_domain_state *trusted_domain_state;
1478 : struct dcesrv_handle *handle;
1479 : struct ldb_message **msgs;
1480 3421 : const char *attrs[] = {
1481 : "trustDirection",
1482 : "flatname",
1483 : NULL
1484 : };
1485 : uint32_t direction;
1486 : int ret;
1487 :
1488 : /* TODO: perform access checks */
1489 :
1490 : /* search for the trusted_domain record */
1491 3421 : ret = gendb_search(policy_state->sam_ldb, tmp_mem,
1492 : policy_state->system_dn,
1493 : &msgs, attrs, "%s", filter);
1494 3421 : if (ret == 0) {
1495 51 : return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1496 : }
1497 :
1498 3370 : 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 3370 : trusted_domain_state = talloc_zero(tmp_mem,
1506 : struct lsa_trusted_domain_state);
1507 3370 : if (!trusted_domain_state) {
1508 0 : return NT_STATUS_NO_MEMORY;
1509 : }
1510 3370 : trusted_domain_state->policy = policy_state;
1511 :
1512 3370 : trusted_domain_state->trusted_domain_dn =
1513 3370 : talloc_steal(trusted_domain_state, msgs[0]->dn);
1514 :
1515 3370 : direction = ldb_msg_find_attr_as_int(msgs[0], "trustDirection", 0);
1516 3370 : if (direction & LSA_TRUST_DIRECTION_INBOUND) {
1517 1611 : const char *flatname = ldb_msg_find_attr_as_string(msgs[0],
1518 : "flatname", NULL);
1519 :
1520 : /* search for the trusted_domain account */
1521 1611 : 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 1611 : if (ret == 1) {
1530 1611 : trusted_domain_state->trusted_domain_user_dn =
1531 1611 : talloc_steal(trusted_domain_state, msgs[0]->dn);
1532 : }
1533 : }
1534 :
1535 3370 : handle = dcesrv_handle_create(dce_call, LSA_HANDLE_TRUSTED_DOMAIN);
1536 3370 : if (!handle) {
1537 0 : return NT_STATUS_NO_MEMORY;
1538 : }
1539 :
1540 3370 : handle->data = talloc_steal(handle, trusted_domain_state);
1541 :
1542 3370 : trusted_domain_state->access_mask = access_mask;
1543 3370 : trusted_domain_state->policy = talloc_reference(trusted_domain_state,
1544 : policy_state);
1545 :
1546 3370 : *_handle = handle;
1547 :
1548 3370 : return NT_STATUS_OK;
1549 : }
1550 :
1551 : /*
1552 : lsa_OpenTrustedDomain
1553 : */
1554 1624 : static NTSTATUS dcesrv_lsa_OpenTrustedDomain(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1555 : struct lsa_OpenTrustedDomain *r)
1556 : {
1557 : struct dcesrv_handle *policy_handle;
1558 : struct lsa_policy_state *policy_state;
1559 : struct dcesrv_handle *handle;
1560 : const char *sid_string;
1561 : char *filter;
1562 : NTSTATUS status;
1563 :
1564 1624 : DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
1565 1624 : ZERO_STRUCTP(r->out.trustdom_handle);
1566 1624 : policy_state = policy_handle->data;
1567 :
1568 1624 : sid_string = dom_sid_string(mem_ctx, r->in.sid);
1569 1624 : if (!sid_string) {
1570 0 : return NT_STATUS_NO_MEMORY;
1571 : }
1572 :
1573 1624 : filter = talloc_asprintf(mem_ctx,
1574 : "(&(securityIdentifier=%s)"
1575 : "(objectclass=trustedDomain))",
1576 : sid_string);
1577 1624 : if (filter == NULL) {
1578 0 : return NT_STATUS_NO_MEMORY;
1579 : }
1580 :
1581 1624 : status = dcesrv_lsa_OpenTrustedDomain_common(dce_call, mem_ctx,
1582 : policy_state,
1583 : filter,
1584 : r->in.access_mask,
1585 : &handle);
1586 1624 : if (!NT_STATUS_IS_OK(status)) {
1587 1 : return status;
1588 : }
1589 :
1590 1623 : *r->out.trustdom_handle = handle->wire_handle;
1591 :
1592 1623 : return NT_STATUS_OK;
1593 : }
1594 :
1595 :
1596 : /*
1597 : lsa_OpenTrustedDomainByName
1598 : */
1599 1797 : static NTSTATUS dcesrv_lsa_OpenTrustedDomainByName(struct dcesrv_call_state *dce_call,
1600 : TALLOC_CTX *mem_ctx,
1601 : struct lsa_OpenTrustedDomainByName *r)
1602 : {
1603 : struct dcesrv_handle *policy_handle;
1604 : struct lsa_policy_state *policy_state;
1605 : struct dcesrv_handle *handle;
1606 : char *td_name;
1607 : char *filter;
1608 : NTSTATUS status;
1609 :
1610 1797 : DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
1611 1797 : ZERO_STRUCTP(r->out.trustdom_handle);
1612 1797 : policy_state = policy_handle->data;
1613 :
1614 1797 : if (!r->in.name.string) {
1615 0 : return NT_STATUS_INVALID_PARAMETER;
1616 : }
1617 :
1618 : /* search for the trusted_domain record */
1619 1797 : td_name = ldb_binary_encode_string(mem_ctx, r->in.name.string);
1620 1797 : if (td_name == NULL) {
1621 0 : return NT_STATUS_NO_MEMORY;
1622 : }
1623 :
1624 1797 : filter = talloc_asprintf(mem_ctx,
1625 : "(&(|(flatname=%s)(cn=%s)(trustPartner=%s))"
1626 : "(objectclass=trustedDomain))",
1627 : td_name, td_name, td_name);
1628 1797 : if (filter == NULL) {
1629 0 : return NT_STATUS_NO_MEMORY;
1630 : }
1631 :
1632 1797 : status = dcesrv_lsa_OpenTrustedDomain_common(dce_call, mem_ctx,
1633 : policy_state,
1634 : filter,
1635 : r->in.access_mask,
1636 : &handle);
1637 1797 : if (!NT_STATUS_IS_OK(status)) {
1638 50 : 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 : char *filter;
1677 : 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 : 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 : const struct ldb_val *orig_val;
1736 43 : uint32_t orig_uint = 0;
1737 43 : unsigned int flags = 0;
1738 : 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 : struct ldb_message **msgs;
1784 : struct ldb_message *msg;
1785 : uint32_t uac;
1786 : uint32_t i;
1787 : 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 : const char *attribute;
1838 : 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 : DATA_BLOB trustAuthIncoming, trustAuthOutgoing, auth_blob;
1894 : struct trustDomainPasswords auth_struct;
1895 40 : struct trustAuthInOutBlob *current_passwords = NULL;
1896 : NTSTATUS nt_status;
1897 : struct ldb_message **msgs;
1898 : 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 : int ret;
1906 : 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 : uint32_t origattrs;
2049 : uint32_t changed_attrs;
2050 : uint32_t origdir;
2051 : 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 12 : if ((origdir & LSA_TRUST_DIRECTION_INBOUND) &&
2074 6 : !(info_ex->trust_direction & LSA_TRUST_DIRECTION_INBOUND)) {
2075 0 : del_incoming = true;
2076 : }
2077 12 : 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 : 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 incidate 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 : struct dcesrv_handle *h;
2242 : struct lsa_trusted_domain_state *td_state;
2243 : struct ldb_message **msgs;
2244 : 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 111 : static NTSTATUS dcesrv_lsa_DeleteTrustedDomain(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2272 : struct lsa_DeleteTrustedDomain *r)
2273 : {
2274 : NTSTATUS status;
2275 111 : struct lsa_OpenTrustedDomain opn = {{0},{0}};
2276 : struct lsa_DeleteObject del;
2277 : struct dcesrv_handle *h;
2278 :
2279 111 : opn.in.handle = r->in.handle;
2280 111 : opn.in.sid = r->in.dom_sid;
2281 111 : opn.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2282 111 : opn.out.trustdom_handle = talloc(mem_ctx, struct policy_handle);
2283 111 : if (!opn.out.trustdom_handle) {
2284 0 : return NT_STATUS_NO_MEMORY;
2285 : }
2286 111 : status = dcesrv_lsa_OpenTrustedDomain(dce_call, mem_ctx, &opn);
2287 111 : if (!NT_STATUS_IS_OK(status)) {
2288 0 : return status;
2289 : }
2290 :
2291 111 : DCESRV_PULL_HANDLE(h, opn.out.trustdom_handle, DCESRV_HANDLE_ANY);
2292 111 : talloc_steal(mem_ctx, h);
2293 :
2294 111 : del.in.handle = opn.out.trustdom_handle;
2295 111 : del.out.handle = opn.out.trustdom_handle;
2296 111 : status = dcesrv_lsa_DeleteObject(dce_call, mem_ctx, &del);
2297 111 : if (!NT_STATUS_IS_OK(status)) {
2298 0 : return status;
2299 : }
2300 111 : 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 : info_ex->domain_name.string
2308 2041 : = ldb_msg_find_attr_as_string(msg, "trustPartner", NULL);
2309 : info_ex->netbios_name.string
2310 2041 : = ldb_msg_find_attr_as_string(msg, "flatname", NULL);
2311 : info_ex->sid
2312 2041 : = samdb_result_dom_sid(mem_ctx, msg, "securityIdentifier");
2313 : info_ex->trust_direction
2314 2041 : = ldb_msg_find_attr_as_int(msg, "trustDirection", 0);
2315 : info_ex->trust_type
2316 2041 : = ldb_msg_find_attr_as_int(msg, "trustType", 0);
2317 : 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 : struct dcesrv_handle *h;
2330 : struct lsa_trusted_domain_state *trusted_domain_state;
2331 : struct ldb_message *msg;
2332 : int ret;
2333 : 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 : 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 : 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 727 : 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 : 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 : 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 : NTSTATUS status;
2421 1405 : struct lsa_OpenTrustedDomain opn = {{0},{0}};
2422 : struct lsa_QueryTrustedDomainInfo query;
2423 : 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 : struct dcesrv_handle *policy_handle;
2460 : struct lsa_policy_state *policy_state;
2461 : struct ldb_message **msgs;
2462 : 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 36 : 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 1689 : static NTSTATUS dcesrv_lsa_QueryTrustedDomainInfoByName(struct dcesrv_call_state *dce_call,
2489 : TALLOC_CTX *mem_ctx,
2490 : struct lsa_QueryTrustedDomainInfoByName *r)
2491 : {
2492 : NTSTATUS status;
2493 1689 : struct lsa_OpenTrustedDomainByName opn = {{0},{0}};
2494 : struct lsa_QueryTrustedDomainInfo query;
2495 : struct dcesrv_handle *h;
2496 :
2497 1689 : opn.in.handle = r->in.handle;
2498 1689 : opn.in.name = *r->in.trusted_domain;
2499 1689 : opn.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2500 1689 : opn.out.trustdom_handle = talloc(mem_ctx, struct policy_handle);
2501 1689 : if (!opn.out.trustdom_handle) {
2502 0 : return NT_STATUS_NO_MEMORY;
2503 : }
2504 1689 : status = dcesrv_lsa_OpenTrustedDomainByName(dce_call, mem_ctx, &opn);
2505 1689 : if (!NT_STATUS_IS_OK(status)) {
2506 50 : 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 : * implmented 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 1108 : static int compare_DomainInfo(struct lsa_DomainInfo *e1, struct lsa_DomainInfo *e2)
2542 : {
2543 1108 : return strcasecmp_m(e1->name.string, e2->name.string);
2544 : }
2545 :
2546 : /*
2547 : lsa_EnumTrustDom
2548 : */
2549 51 : static NTSTATUS dcesrv_lsa_EnumTrustDom(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2550 : struct lsa_EnumTrustDom *r)
2551 : {
2552 : struct dcesrv_handle *policy_handle;
2553 : struct lsa_DomainInfo *entries;
2554 : struct lsa_policy_state *policy_state;
2555 : struct ldb_message **domains;
2556 51 : const char *attrs[] = {
2557 : "flatname",
2558 : "securityIdentifier",
2559 : NULL
2560 : };
2561 :
2562 :
2563 : int count, i;
2564 :
2565 51 : *r->out.resume_handle = 0;
2566 :
2567 51 : r->out.domains->domains = NULL;
2568 51 : r->out.domains->count = 0;
2569 :
2570 51 : DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
2571 :
2572 51 : 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 51 : count = gendb_search(policy_state->sam_ldb, mem_ctx, policy_state->system_dn, &domains, attrs,
2577 : "objectclass=trustedDomain");
2578 51 : if (count < 0) {
2579 0 : return NT_STATUS_INTERNAL_DB_CORRUPTION;
2580 : }
2581 :
2582 : /* convert to lsa_TrustInformation format */
2583 51 : entries = talloc_array(mem_ctx, struct lsa_DomainInfo, count);
2584 51 : if (!entries) {
2585 0 : return NT_STATUS_NO_MEMORY;
2586 : }
2587 483 : 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 51 : TYPESAFE_QSORT(entries, count, compare_DomainInfo);
2594 :
2595 51 : if (*r->in.resume_handle >= count) {
2596 15 : *r->out.resume_handle = -1;
2597 :
2598 15 : 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 1108 : static int compare_TrustDomainInfoInfoEx(struct lsa_TrustDomainInfoInfoEx *e1, struct lsa_TrustDomainInfoInfoEx *e2)
2630 : {
2631 1108 : 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 : struct dcesrv_handle *policy_handle;
2641 : struct lsa_TrustDomainInfoInfoEx *entries;
2642 : struct lsa_policy_state *policy_state;
2643 : 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 : NTSTATUS nt_status;
2654 :
2655 : 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 : struct dcesrv_handle *h, *ah;
2721 : struct lsa_policy_state *state;
2722 : 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 : struct dcesrv_handle *h;
2782 : struct lsa_account_state *astate;
2783 : int ret;
2784 : unsigned int i, j;
2785 : struct ldb_message **res;
2786 18 : const char * const attrs[] = { "privilege", NULL};
2787 : struct ldb_message_element *el;
2788 : const char *sidstr;
2789 : 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 64 : static NTSTATUS dcesrv_lsa_EnumAccountRights(struct dcesrv_call_state *dce_call,
2852 : TALLOC_CTX *mem_ctx,
2853 : struct lsa_EnumAccountRights *r)
2854 : {
2855 : struct dcesrv_handle *h;
2856 : struct lsa_policy_state *state;
2857 : int ret;
2858 : unsigned int i;
2859 : struct ldb_message **res;
2860 64 : const char * const attrs[] = { "privilege", NULL};
2861 : const char *sidstr;
2862 : struct ldb_message_element *el;
2863 :
2864 64 : DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
2865 :
2866 64 : state = h->data;
2867 :
2868 64 : sidstr = ldap_encode_ndr_dom_sid(mem_ctx, r->in.sid);
2869 64 : if (sidstr == NULL) {
2870 0 : return NT_STATUS_NO_MEMORY;
2871 : }
2872 :
2873 64 : ret = gendb_search(state->pdb, mem_ctx, NULL, &res, attrs,
2874 : "(&(objectSid=%s)(privilege=*))", sidstr);
2875 64 : if (ret == 0) {
2876 15 : return NT_STATUS_OBJECT_NAME_NOT_FOUND;
2877 : }
2878 49 : if (ret != 1) {
2879 0 : DEBUG(3, ("searching for account rights for SID: %s failed: %s",
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 49 : el = ldb_msg_find_element(res[0], "privilege");
2886 49 : if (el == NULL || el->num_values == 0) {
2887 0 : return NT_STATUS_OBJECT_NAME_NOT_FOUND;
2888 : }
2889 :
2890 49 : r->out.rights->count = el->num_values;
2891 49 : r->out.rights->names = talloc_array(r->out.rights,
2892 : struct lsa_StringLarge, r->out.rights->count);
2893 49 : if (r->out.rights->names == NULL) {
2894 0 : return NT_STATUS_NO_MEMORY;
2895 : }
2896 :
2897 299 : for (i=0;i<el->num_values;i++) {
2898 250 : r->out.rights->names[i].string = (const char *)el->values[i].data;
2899 : }
2900 :
2901 49 : return NT_STATUS_OK;
2902 : }
2903 :
2904 :
2905 :
2906 : /*
2907 : helper for lsa_AddAccountRights and lsa_RemoveAccountRights
2908 : */
2909 42 : 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 42 : struct auth_session_info *session_info =
2917 0 : dcesrv_call_session_info(dce_call);
2918 : const char *sidstr, *sidndrstr;
2919 : struct ldb_message *msg;
2920 : struct ldb_message_element *el;
2921 : int ret;
2922 : uint32_t i;
2923 : struct lsa_EnumAccountRights r2;
2924 : char *dnstr;
2925 :
2926 42 : 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 42 : msg = ldb_msg_new(mem_ctx);
2933 42 : if (msg == NULL) {
2934 0 : return NT_STATUS_NO_MEMORY;
2935 : }
2936 :
2937 42 : sidndrstr = ldap_encode_ndr_dom_sid(msg, sid);
2938 42 : if (sidndrstr == NULL) {
2939 0 : TALLOC_FREE(msg);
2940 0 : return NT_STATUS_NO_MEMORY;
2941 : }
2942 :
2943 42 : sidstr = dom_sid_string(msg, sid);
2944 42 : if (sidstr == NULL) {
2945 0 : TALLOC_FREE(msg);
2946 0 : return NT_STATUS_NO_MEMORY;
2947 : }
2948 :
2949 42 : dnstr = talloc_asprintf(msg, "sid=%s", sidstr);
2950 42 : if (dnstr == NULL) {
2951 0 : TALLOC_FREE(msg);
2952 0 : return NT_STATUS_NO_MEMORY;
2953 : }
2954 :
2955 42 : msg->dn = ldb_dn_new(msg, state->pdb, dnstr);
2956 42 : if (msg->dn == NULL) {
2957 0 : TALLOC_FREE(msg);
2958 0 : return NT_STATUS_NO_MEMORY;
2959 : }
2960 :
2961 42 : if (LDB_FLAG_MOD_TYPE(ldb_flag) == LDB_FLAG_MOD_ADD) {
2962 : NTSTATUS status;
2963 :
2964 23 : r2.in.handle = &state->handle->wire_handle;
2965 23 : r2.in.sid = sid;
2966 23 : r2.out.rights = talloc(mem_ctx, struct lsa_RightSet);
2967 :
2968 23 : status = dcesrv_lsa_EnumAccountRights(dce_call, mem_ctx, &r2);
2969 23 : if (!NT_STATUS_IS_OK(status)) {
2970 4 : ZERO_STRUCTP(r2.out.rights);
2971 : }
2972 : }
2973 :
2974 88 : for (i=0;i<rights->count;i++) {
2975 : bool ok;
2976 :
2977 46 : ok = dcesrc_lsa_valid_AccountRight(rights->names[i].string);
2978 46 : if (!ok) {
2979 0 : talloc_free(msg);
2980 0 : return NT_STATUS_NO_SUCH_PRIVILEGE;
2981 : }
2982 :
2983 46 : if (LDB_FLAG_MOD_TYPE(ldb_flag) == LDB_FLAG_MOD_ADD) {
2984 : uint32_t j;
2985 129 : 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 23 : if (j != r2.out.rights->count) continue;
2992 : }
2993 :
2994 46 : ret = ldb_msg_add_string(msg, "privilege", rights->names[i].string);
2995 46 : if (ret != LDB_SUCCESS) {
2996 0 : talloc_free(msg);
2997 0 : return NT_STATUS_NO_MEMORY;
2998 : }
2999 : }
3000 :
3001 42 : el = ldb_msg_find_element(msg, "privilege");
3002 42 : if (!el) {
3003 0 : talloc_free(msg);
3004 0 : return NT_STATUS_OK;
3005 : }
3006 :
3007 42 : el->flags = ldb_flag;
3008 :
3009 42 : ret = ldb_modify(state->pdb, msg);
3010 42 : if (ret == LDB_ERR_NO_SUCH_OBJECT) {
3011 4 : 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 4 : ldb_msg_add_string(msg, "comment", "added via LSA");
3016 4 : ret = ldb_add(state->pdb, msg);
3017 : }
3018 42 : 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",
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 42 : talloc_free(msg);
3031 42 : 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 : struct lsa_RightSet rights;
3041 : struct dcesrv_handle *h;
3042 : struct lsa_account_state *astate;
3043 : 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 : struct lsa_RightSet *rights;
3078 : struct dcesrv_handle *h;
3079 : struct lsa_account_state *astate;
3080 : 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 : struct lsa_EnumAccountRights r2;
3091 : 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 : struct dcesrv_handle *h;
3160 : struct lsa_account_state *astate;
3161 : int ret;
3162 : unsigned int i;
3163 : struct ldb_message **res;
3164 26 : const char * const attrs[] = { "privilege", NULL};
3165 : struct ldb_message_element *el;
3166 : 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 1655 : static NTSTATUS dcesrv_lsa_CreateSecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3218 : struct lsa_CreateSecret *r)
3219 : {
3220 983 : struct auth_session_info *session_info =
3221 672 : dcesrv_call_session_info(dce_call);
3222 : struct dcesrv_handle *policy_handle;
3223 : struct lsa_policy_state *policy_state;
3224 : struct lsa_secret_state *secret_state;
3225 : struct dcesrv_handle *handle;
3226 : struct ldb_message **msgs, *msg;
3227 1655 : const char *attrs[] = {
3228 : NULL
3229 : };
3230 :
3231 : const char *name;
3232 :
3233 : int ret;
3234 :
3235 1655 : DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
3236 1655 : ZERO_STRUCTP(r->out.sec_handle);
3237 :
3238 1655 : switch (security_session_user_level(session_info, NULL))
3239 : {
3240 1655 : case SECURITY_SYSTEM:
3241 : case SECURITY_ADMINISTRATOR:
3242 1655 : break;
3243 0 : default:
3244 : /* Users and annonymous are not allowed create secrets */
3245 0 : return NT_STATUS_ACCESS_DENIED;
3246 : }
3247 :
3248 1655 : policy_state = policy_handle->data;
3249 :
3250 1655 : if (!r->in.name.string) {
3251 0 : return NT_STATUS_INVALID_PARAMETER;
3252 : }
3253 :
3254 1655 : secret_state = talloc(mem_ctx, struct lsa_secret_state);
3255 1655 : NT_STATUS_HAVE_NO_MEMORY(secret_state);
3256 1655 : secret_state->policy = policy_state;
3257 :
3258 1655 : msg = ldb_msg_new(mem_ctx);
3259 1655 : if (msg == NULL) {
3260 0 : return NT_STATUS_NO_MEMORY;
3261 : }
3262 :
3263 1655 : if (strncmp("G$", r->in.name.string, 2) == 0) {
3264 : const char *name2;
3265 :
3266 11 : secret_state->global = true;
3267 :
3268 11 : name = &r->in.name.string[2];
3269 11 : if (strlen(name) == 0) {
3270 0 : return NT_STATUS_INVALID_PARAMETER;
3271 : }
3272 :
3273 11 : name2 = talloc_asprintf(mem_ctx, "%s Secret",
3274 : ldb_binary_encode_string(mem_ctx, name));
3275 11 : 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 11 : secret_state->sam_ldb =
3288 11 : dcesrv_samdb_connect_as_system(secret_state, dce_call);
3289 11 : NT_STATUS_HAVE_NO_MEMORY(secret_state->sam_ldb);
3290 :
3291 : /* search for the secret record */
3292 11 : ret = gendb_search(secret_state->sam_ldb,
3293 : mem_ctx, policy_state->system_dn, &msgs, attrs,
3294 : "(&(cn=%s)(objectclass=secret))",
3295 : name2);
3296 11 : if (ret > 0) {
3297 5 : return NT_STATUS_OBJECT_NAME_COLLISION;
3298 : }
3299 :
3300 6 : 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 6 : msg->dn = ldb_dn_copy(mem_ctx, policy_state->system_dn);
3307 6 : NT_STATUS_HAVE_NO_MEMORY(msg->dn);
3308 6 : if (!ldb_dn_add_child_fmt(msg->dn, "cn=%s", name2)) {
3309 0 : return NT_STATUS_NO_MEMORY;
3310 : }
3311 :
3312 6 : ret = ldb_msg_add_string(msg, "cn", name2);
3313 6 : if (ret != LDB_SUCCESS) return NT_STATUS_NO_MEMORY;
3314 : } else {
3315 1644 : secret_state->global = false;
3316 :
3317 1644 : name = r->in.name.string;
3318 1644 : if (strlen(name) == 0) {
3319 0 : return NT_STATUS_INVALID_PARAMETER;
3320 : }
3321 :
3322 2316 : secret_state->sam_ldb = secrets_db_connect(secret_state,
3323 1644 : dce_call->conn->dce_ctx->lp_ctx);
3324 1644 : NT_STATUS_HAVE_NO_MEMORY(secret_state->sam_ldb);
3325 :
3326 : /* search for the secret record */
3327 1644 : 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 1644 : if (ret > 0) {
3333 6 : return NT_STATUS_OBJECT_NAME_COLLISION;
3334 : }
3335 :
3336 1638 : 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 1638 : msg->dn = ldb_dn_new_fmt(mem_ctx, secret_state->sam_ldb,
3343 : "cn=%s,cn=LSA Secrets", name);
3344 1638 : NT_STATUS_HAVE_NO_MEMORY(msg->dn);
3345 1638 : ret = ldb_msg_add_string(msg, "cn", name);
3346 1638 : if (ret != LDB_SUCCESS) return NT_STATUS_NO_MEMORY;
3347 : }
3348 :
3349 1644 : ret = ldb_msg_add_string(msg, "objectClass", "secret");
3350 1644 : if (ret != LDB_SUCCESS) return NT_STATUS_NO_MEMORY;
3351 :
3352 1644 : secret_state->secret_dn = talloc_reference(secret_state, msg->dn);
3353 1644 : NT_STATUS_HAVE_NO_MEMORY(secret_state->secret_dn);
3354 :
3355 : /* create the secret */
3356 1644 : ret = ldb_add(secret_state->sam_ldb, msg);
3357 1644 : 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 1644 : handle = dcesrv_handle_create(dce_call, LSA_HANDLE_SECRET);
3365 1644 : NT_STATUS_HAVE_NO_MEMORY(handle);
3366 :
3367 1644 : handle->data = talloc_steal(handle, secret_state);
3368 :
3369 1644 : secret_state->access_mask = r->in.access_mask;
3370 1644 : secret_state->policy = talloc_reference(secret_state, policy_state);
3371 1644 : NT_STATUS_HAVE_NO_MEMORY(secret_state->policy);
3372 :
3373 1644 : *r->out.sec_handle = handle->wire_handle;
3374 :
3375 1644 : return NT_STATUS_OK;
3376 : }
3377 :
3378 :
3379 : /*
3380 : lsa_OpenSecret
3381 : */
3382 27 : static NTSTATUS dcesrv_lsa_OpenSecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3383 : struct lsa_OpenSecret *r)
3384 : {
3385 27 : struct auth_session_info *session_info =
3386 0 : dcesrv_call_session_info(dce_call);
3387 : struct dcesrv_handle *policy_handle;
3388 : struct lsa_policy_state *policy_state;
3389 : struct lsa_secret_state *secret_state;
3390 : struct dcesrv_handle *handle;
3391 : struct ldb_message **msgs;
3392 27 : const char *attrs[] = {
3393 : NULL
3394 : };
3395 : const char *name;
3396 : int ret;
3397 :
3398 27 : DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
3399 27 : ZERO_STRUCTP(r->out.sec_handle);
3400 27 : policy_state = policy_handle->data;
3401 :
3402 27 : if (!r->in.name.string) {
3403 0 : return NT_STATUS_INVALID_PARAMETER;
3404 : }
3405 :
3406 27 : switch (security_session_user_level(session_info, NULL))
3407 : {
3408 27 : case SECURITY_SYSTEM:
3409 : case SECURITY_ADMINISTRATOR:
3410 27 : break;
3411 0 : default:
3412 : /* Users and annonymous are not allowed to access secrets */
3413 0 : return NT_STATUS_ACCESS_DENIED;
3414 : }
3415 :
3416 27 : secret_state = talloc(mem_ctx, struct lsa_secret_state);
3417 27 : if (!secret_state) {
3418 0 : return NT_STATUS_NO_MEMORY;
3419 : }
3420 27 : secret_state->policy = policy_state;
3421 :
3422 27 : if (strncmp("G$", r->in.name.string, 2) == 0) {
3423 16 : 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 16 : secret_state->sam_ldb =
3435 16 : dcesrv_samdb_connect_as_system(secret_state, dce_call);
3436 16 : NT_STATUS_HAVE_NO_MEMORY(secret_state->sam_ldb);
3437 16 : secret_state->global = true;
3438 :
3439 16 : if (strlen(name) < 1) {
3440 0 : return NT_STATUS_INVALID_PARAMETER;
3441 : }
3442 :
3443 : /* search for the secret record */
3444 16 : 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 16 : if (ret == 0) {
3449 5 : return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3450 : }
3451 :
3452 11 : 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 11 : secret_state->global = false;
3459 11 : secret_state->sam_ldb = secrets_db_connect(secret_state,
3460 11 : dce_call->conn->dce_ctx->lp_ctx);
3461 11 : NT_STATUS_HAVE_NO_MEMORY(secret_state->sam_ldb);
3462 :
3463 11 : name = r->in.name.string;
3464 11 : if (strlen(name) < 1) {
3465 0 : return NT_STATUS_INVALID_PARAMETER;
3466 : }
3467 :
3468 : /* search for the secret record */
3469 11 : 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 11 : if (ret == 0) {
3475 5 : return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3476 : }
3477 :
3478 6 : 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 17 : secret_state->secret_dn = talloc_reference(secret_state, msgs[0]->dn);
3486 :
3487 17 : handle = dcesrv_handle_create(dce_call, LSA_HANDLE_SECRET);
3488 17 : if (!handle) {
3489 0 : return NT_STATUS_NO_MEMORY;
3490 : }
3491 :
3492 17 : handle->data = talloc_steal(handle, secret_state);
3493 :
3494 17 : secret_state->access_mask = r->in.access_mask;
3495 17 : secret_state->policy = talloc_reference(secret_state, policy_state);
3496 :
3497 17 : *r->out.sec_handle = handle->wire_handle;
3498 :
3499 17 : return NT_STATUS_OK;
3500 : }
3501 :
3502 :
3503 : /*
3504 : lsa_SetSecret
3505 : */
3506 2344 : static NTSTATUS dcesrv_lsa_SetSecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3507 : struct lsa_SetSecret *r)
3508 : {
3509 :
3510 : struct dcesrv_handle *h;
3511 : struct lsa_secret_state *secret_state;
3512 : struct ldb_message *msg;
3513 : DATA_BLOB session_key;
3514 : DATA_BLOB crypt_secret, secret;
3515 : struct ldb_val val;
3516 : int ret;
3517 2344 : NTSTATUS status = NT_STATUS_OK;
3518 :
3519 2344 : struct timeval now = timeval_current();
3520 2344 : NTTIME nt_now = timeval_to_nttime(&now);
3521 :
3522 2344 : DCESRV_PULL_HANDLE(h, r->in.sec_handle, LSA_HANDLE_SECRET);
3523 :
3524 2344 : secret_state = h->data;
3525 :
3526 2344 : msg = ldb_msg_new(mem_ctx);
3527 2344 : if (msg == NULL) {
3528 0 : return NT_STATUS_NO_MEMORY;
3529 : }
3530 :
3531 2344 : msg->dn = talloc_reference(mem_ctx, secret_state->secret_dn);
3532 2344 : if (!msg->dn) {
3533 0 : return NT_STATUS_NO_MEMORY;
3534 : }
3535 2344 : status = dcesrv_transport_session_key(dce_call, &session_key);
3536 2344 : if (!NT_STATUS_IS_OK(status)) {
3537 0 : return status;
3538 : }
3539 :
3540 2344 : if (r->in.old_val) {
3541 : /* Decrypt */
3542 10 : crypt_secret.data = r->in.old_val->data;
3543 10 : crypt_secret.length = r->in.old_val->size;
3544 :
3545 10 : status = sess_decrypt_blob(mem_ctx, &crypt_secret, &session_key, &secret);
3546 10 : if (!NT_STATUS_IS_OK(status)) {
3547 0 : return status;
3548 : }
3549 :
3550 10 : val.data = secret.data;
3551 10 : val.length = secret.length;
3552 :
3553 : /* set value */
3554 10 : 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 10 : 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 : const struct ldb_val *old_val;
3568 : NTTIME last_set_time;
3569 : struct ldb_message **res;
3570 2334 : const char *attrs[] = {
3571 : "currentValue",
3572 : "lastSetTime",
3573 : NULL
3574 : };
3575 :
3576 : /* search for the secret record */
3577 2334 : ret = gendb_search_dn(secret_state->sam_ldb,mem_ctx,
3578 : secret_state->secret_dn, &res, attrs);
3579 2334 : if (ret == 0) {
3580 0 : return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3581 : }
3582 :
3583 2334 : 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 2334 : old_val = ldb_msg_find_ldb_val(res[0], "currentValue");
3590 2334 : last_set_time = ldb_msg_find_attr_as_uint64(res[0], "lastSetTime", 0);
3591 :
3592 2334 : if (old_val) {
3593 : /* set old value */
3594 1172 : if (ldb_msg_add_value(msg, "priorValue",
3595 : old_val, NULL) != LDB_SUCCESS) {
3596 0 : return NT_STATUS_NO_MEMORY;
3597 : }
3598 : } else {
3599 1162 : 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 2334 : if (ldb_msg_find_ldb_val(res[0], "lastSetTime")) {
3607 1172 : 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 1162 : 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 2344 : if (r->in.new_val) {
3620 : /* Decrypt */
3621 2334 : crypt_secret.data = r->in.new_val->data;
3622 2334 : crypt_secret.length = r->in.new_val->size;
3623 :
3624 2334 : status = sess_decrypt_blob(mem_ctx, &crypt_secret, &session_key, &secret);
3625 2334 : if (!NT_STATUS_IS_OK(status)) {
3626 1162 : return status;
3627 : }
3628 :
3629 1172 : val.data = secret.data;
3630 1172 : val.length = secret.length;
3631 :
3632 : /* set value */
3633 1172 : 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 1172 : 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 10 : 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 10 : 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 1182 : ret = dsdb_replace(secret_state->sam_ldb, msg, 0);
3656 1182 : if (ret != LDB_SUCCESS) {
3657 0 : return dsdb_ldb_err_to_ntstatus(ret);
3658 : }
3659 :
3660 1182 : return NT_STATUS_OK;
3661 : }
3662 :
3663 :
3664 : /*
3665 : lsa_QuerySecret
3666 : */
3667 1188 : static NTSTATUS dcesrv_lsa_QuerySecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3668 : struct lsa_QuerySecret *r)
3669 : {
3670 708 : struct auth_session_info *session_info =
3671 480 : dcesrv_call_session_info(dce_call);
3672 : struct dcesrv_handle *h;
3673 : struct lsa_secret_state *secret_state;
3674 : struct ldb_message *msg;
3675 : DATA_BLOB session_key;
3676 : DATA_BLOB crypt_secret, secret;
3677 : int ret;
3678 : struct ldb_message **res;
3679 1188 : const char *attrs[] = {
3680 : "currentValue",
3681 : "priorValue",
3682 : "lastSetTime",
3683 : "priorSetTime",
3684 : NULL
3685 : };
3686 :
3687 : NTSTATUS nt_status;
3688 :
3689 1188 : DCESRV_PULL_HANDLE(h, r->in.sec_handle, LSA_HANDLE_SECRET);
3690 :
3691 : /* Ensure user is permitted to read this... */
3692 1188 : switch (security_session_user_level(session_info, NULL))
3693 : {
3694 1188 : case SECURITY_SYSTEM:
3695 : case SECURITY_ADMINISTRATOR:
3696 1188 : break;
3697 0 : default:
3698 : /* Users and annonymous are not allowed to read secrets */
3699 0 : return NT_STATUS_ACCESS_DENIED;
3700 : }
3701 :
3702 1188 : secret_state = h->data;
3703 :
3704 : /* pull all the user attributes */
3705 1188 : ret = gendb_search_dn(secret_state->sam_ldb, mem_ctx,
3706 : secret_state->secret_dn, &res, attrs);
3707 1188 : if (ret != 1) {
3708 0 : return NT_STATUS_INTERNAL_DB_CORRUPTION;
3709 : }
3710 1188 : msg = res[0];
3711 :
3712 1188 : nt_status = dcesrv_transport_session_key(dce_call, &session_key);
3713 1188 : if (!NT_STATUS_IS_OK(nt_status)) {
3714 0 : return nt_status;
3715 : }
3716 :
3717 1188 : if (r->in.old_val) {
3718 : const struct ldb_val *prior_val;
3719 20 : r->out.old_val = talloc_zero(mem_ctx, struct lsa_DATA_BUF_PTR);
3720 20 : if (!r->out.old_val) {
3721 0 : return NT_STATUS_NO_MEMORY;
3722 : }
3723 20 : prior_val = ldb_msg_find_ldb_val(msg, "priorValue");
3724 :
3725 20 : if (prior_val && prior_val->length) {
3726 20 : secret.data = prior_val->data;
3727 20 : secret.length = prior_val->length;
3728 :
3729 : /* Encrypt */
3730 20 : crypt_secret = sess_encrypt_blob(mem_ctx, &secret, &session_key);
3731 20 : if (!crypt_secret.length) {
3732 0 : return NT_STATUS_NO_MEMORY;
3733 : }
3734 20 : r->out.old_val->buf = talloc(mem_ctx, struct lsa_DATA_BUF);
3735 20 : if (!r->out.old_val->buf) {
3736 0 : return NT_STATUS_NO_MEMORY;
3737 : }
3738 20 : r->out.old_val->buf->size = crypt_secret.length;
3739 20 : r->out.old_val->buf->length = crypt_secret.length;
3740 20 : r->out.old_val->buf->data = crypt_secret.data;
3741 : }
3742 : }
3743 :
3744 1188 : if (r->in.old_mtime) {
3745 20 : r->out.old_mtime = talloc(mem_ctx, NTTIME);
3746 20 : if (!r->out.old_mtime) {
3747 0 : return NT_STATUS_NO_MEMORY;
3748 : }
3749 20 : *r->out.old_mtime = ldb_msg_find_attr_as_uint64(msg, "priorSetTime", 0);
3750 : }
3751 :
3752 1188 : if (r->in.new_val) {
3753 : const struct ldb_val *new_val;
3754 1188 : r->out.new_val = talloc_zero(mem_ctx, struct lsa_DATA_BUF_PTR);
3755 1188 : if (!r->out.new_val) {
3756 0 : return NT_STATUS_NO_MEMORY;
3757 : }
3758 :
3759 1188 : new_val = ldb_msg_find_ldb_val(msg, "currentValue");
3760 :
3761 1188 : if (new_val && new_val->length) {
3762 1178 : secret.data = new_val->data;
3763 1178 : secret.length = new_val->length;
3764 :
3765 : /* Encrypt */
3766 1178 : crypt_secret = sess_encrypt_blob(mem_ctx, &secret, &session_key);
3767 1178 : if (!crypt_secret.length) {
3768 0 : return NT_STATUS_NO_MEMORY;
3769 : }
3770 1178 : r->out.new_val->buf = talloc(mem_ctx, struct lsa_DATA_BUF);
3771 1178 : if (!r->out.new_val->buf) {
3772 0 : return NT_STATUS_NO_MEMORY;
3773 : }
3774 1178 : r->out.new_val->buf->length = crypt_secret.length;
3775 1178 : r->out.new_val->buf->size = crypt_secret.length;
3776 1178 : r->out.new_val->buf->data = crypt_secret.data;
3777 : }
3778 : }
3779 :
3780 1188 : if (r->in.new_mtime) {
3781 1182 : r->out.new_mtime = talloc(mem_ctx, NTTIME);
3782 1182 : if (!r->out.new_mtime) {
3783 0 : return NT_STATUS_NO_MEMORY;
3784 : }
3785 1182 : *r->out.new_mtime = ldb_msg_find_attr_as_uint64(msg, "lastSetTime", 0);
3786 : }
3787 :
3788 1188 : return NT_STATUS_OK;
3789 : }
3790 :
3791 :
3792 : /*
3793 : lsa_LookupPrivValue
3794 : */
3795 75 : static NTSTATUS dcesrv_lsa_LookupPrivValue(struct dcesrv_call_state *dce_call,
3796 : TALLOC_CTX *mem_ctx,
3797 : struct lsa_LookupPrivValue *r)
3798 : {
3799 : struct dcesrv_handle *h;
3800 : int id;
3801 :
3802 75 : DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3803 :
3804 75 : id = sec_privilege_id(r->in.name->string);
3805 75 : if (id == SEC_PRIV_INVALID) {
3806 0 : return NT_STATUS_NO_SUCH_PRIVILEGE;
3807 : }
3808 :
3809 75 : r->out.luid->low = id;
3810 75 : r->out.luid->high = 0;
3811 :
3812 75 : 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 : struct dcesrv_handle *h;
3824 : struct lsa_StringLarge *name;
3825 : 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 : struct dcesrv_handle *h;
3859 75 : struct lsa_StringLarge *disp_name = NULL;
3860 : 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 : struct dcesrv_handle *h;
3894 : struct lsa_policy_state *state;
3895 : int ret, i;
3896 : struct ldb_message **res;
3897 75 : const char * const attrs[] = { "objectSid", NULL};
3898 : const char *privname;
3899 : 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 96 : 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 8 : static NTSTATUS dcesrv_lsa_AddAccountRights(struct dcesrv_call_state *dce_call,
3944 : TALLOC_CTX *mem_ctx,
3945 : struct lsa_AddAccountRights *r)
3946 : {
3947 : struct dcesrv_handle *h;
3948 : struct lsa_policy_state *state;
3949 :
3950 8 : DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3951 :
3952 8 : state = h->data;
3953 :
3954 8 : return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, state,
3955 : LDB_FLAG_MOD_ADD,
3956 8 : 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 : struct dcesrv_handle *h;
3968 : 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 274 : static NTSTATUS dcesrv_lsa_GetUserName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4004 : struct lsa_GetUserName *r)
4005 : {
4006 258 : enum dcerpc_transport_t transport =
4007 274 : dcerpc_binding_get_transport(dce_call->conn->endpoint->ep_description);
4008 258 : struct auth_session_info *session_info =
4009 16 : dcesrv_call_session_info(dce_call);
4010 274 : NTSTATUS status = NT_STATUS_OK;
4011 : const char *account_name;
4012 : const char *authority_name;
4013 : struct lsa_String *_account_name;
4014 274 : struct lsa_String *_authority_name = NULL;
4015 :
4016 274 : if (transport != NCACN_NP && transport != NCALRPC) {
4017 3 : DCESRV_FAULT(DCERPC_FAULT_ACCESS_DENIED);
4018 : }
4019 :
4020 : /* this is what w2k3 does */
4021 271 : r->out.account_name = r->in.account_name;
4022 271 : r->out.authority_name = r->in.authority_name;
4023 :
4024 271 : if (r->in.account_name
4025 271 : && *r->in.account_name
4026 : /* && *(*r->in.account_name)->string */
4027 : ) {
4028 0 : return NT_STATUS_INVALID_PARAMETER;
4029 : }
4030 :
4031 271 : if (r->in.authority_name
4032 253 : && *r->in.authority_name
4033 : /* && *(*r->in.authority_name)->string */
4034 : ) {
4035 0 : return NT_STATUS_INVALID_PARAMETER;
4036 : }
4037 :
4038 271 : account_name = talloc_reference(mem_ctx, session_info->info->account_name);
4039 271 : authority_name = talloc_reference(mem_ctx, session_info->info->domain_name);
4040 :
4041 271 : _account_name = talloc(mem_ctx, struct lsa_String);
4042 271 : NT_STATUS_HAVE_NO_MEMORY(_account_name);
4043 271 : _account_name->string = account_name;
4044 :
4045 271 : if (r->in.authority_name) {
4046 253 : _authority_name = talloc(mem_ctx, struct lsa_String);
4047 253 : NT_STATUS_HAVE_NO_MEMORY(_authority_name);
4048 253 : _authority_name->string = authority_name;
4049 : }
4050 :
4051 271 : *r->out.account_name = _account_name;
4052 271 : if (r->out.authority_name) {
4053 253 : *r->out.authority_name = _authority_name;
4054 : }
4055 :
4056 271 : 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 6 : 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 : time_t svc_tkt_lifetime;
4076 : time_t usr_tkt_lifetime;
4077 : time_t renewal_lifetime;
4078 :
4079 : /* Our KDC always re-validates the client */
4080 6 : k->authentication_options = LSA_POLICY_KERBEROS_VALIDATE_CLIENT;
4081 :
4082 6 : lpcfg_default_kdc_policy(mem_ctx, lp_ctx, &svc_tkt_lifetime,
4083 : &usr_tkt_lifetime, &renewal_lifetime);
4084 :
4085 6 : unix_to_nt_time(&k->service_tkt_lifetime, svc_tkt_lifetime);
4086 6 : unix_to_nt_time(&k->user_tkt_lifetime, usr_tkt_lifetime);
4087 6 : 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 6 : if (smb_krb5_context) {
4094 6 : unix_to_nt_time(&k->clock_skew,
4095 : krb5_get_max_time_skew(smb_krb5_context->krb5_context));
4096 : }
4097 : #endif
4098 6 : k->reserved = 0;
4099 6 : }
4100 : /*
4101 : lsa_QueryDomainInformationPolicy
4102 : */
4103 12 : static NTSTATUS dcesrv_lsa_QueryDomainInformationPolicy(struct dcesrv_call_state *dce_call,
4104 : TALLOC_CTX *mem_ctx,
4105 : struct lsa_QueryDomainInformationPolicy *r)
4106 : {
4107 : union lsa_DomainInformationPolicy *info;
4108 :
4109 12 : info = talloc_zero(r->out.info, union lsa_DomainInformationPolicy);
4110 12 : if (!info) {
4111 0 : return NT_STATUS_NO_MEMORY;
4112 : }
4113 :
4114 12 : switch (r->in.level) {
4115 6 : case LSA_DOMAIN_INFO_POLICY_EFS:
4116 6 : talloc_free(info);
4117 6 : *r->out.info = NULL;
4118 6 : return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4119 6 : case LSA_DOMAIN_INFO_POLICY_KERBEROS:
4120 : {
4121 6 : struct lsa_DomainInfoKerberos *k = &info->kerberos_info;
4122 : struct smb_krb5_context *smb_krb5_context;
4123 6 : int ret = smb_krb5_init_context(mem_ctx,
4124 6 : dce_call->conn->dce_ctx->lp_ctx,
4125 : &smb_krb5_context);
4126 6 : if (ret != 0) {
4127 0 : talloc_free(info);
4128 0 : *r->out.info = NULL;
4129 0 : return NT_STATUS_INTERNAL_ERROR;
4130 : }
4131 6 : kdc_get_policy(mem_ctx, dce_call->conn->dce_ctx->lp_ctx,
4132 : smb_krb5_context,
4133 : k);
4134 6 : talloc_free(smb_krb5_context);
4135 6 : *r->out.info = info;
4136 6 : 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 : 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 246 : 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 : struct dcesrv_handle *h;
4376 : 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 : 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 : NTSTATUS status;
4402 : enum ndr_err_code ndr_err;
4403 : int ret;
4404 87 : bool in_transaction = false;
4405 45 : 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 132 : 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 54 : NTSTATUS dcerpc_server_lsa_init(TALLOC_CTX *ctx)
4835 : {
4836 : NTSTATUS ret;
4837 :
4838 54 : ret = dcerpc_server_dssetup_init(ctx);
4839 54 : if (!NT_STATUS_IS_OK(ret)) {
4840 0 : return ret;
4841 : }
4842 54 : ret = dcerpc_server_lsarpc_init(ctx);
4843 54 : if (!NT_STATUS_IS_OK(ret)) {
4844 0 : return ret;
4845 : }
4846 54 : return ret;
4847 : }
|