CVE-2020-25718 s4-rpc_server: Put RODC reveal/never reveal logic into a single helper...
[Samba.git] / source4 / rpc_server / common / sid_helper.c
blobeaeab236fc0111d41ef6c67db685d012df387e7f
1 /*
2 Unix SMB/CIFS implementation.
4 common sid helper functions
6 Copyright (C) Catalyst.NET Ltd 2017
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>.
22 #include "includes.h"
23 #include "rpc_server/dcerpc_server.h"
24 #include "librpc/gen_ndr/ndr_security.h"
25 #include "source4/dsdb/samdb/samdb.h"
26 #include "rpc_server/common/sid_helper.h"
27 #include "libcli/security/security.h"
30 see if any SIDs in list1 are in list2
32 bool sid_list_match(uint32_t num_sids1,
33 const struct dom_sid *list1,
34 uint32_t num_sids2,
35 const struct dom_sid *list2)
37 unsigned int i, j;
38 /* do we ever have enough SIDs here to worry about O(n^2) ? */
39 for (i=0; i < num_sids1; i++) {
40 for (j=0; j < num_sids2; j++) {
41 if (dom_sid_equal(&list1[i], &list2[j])) {
42 return true;
46 return false;
50 * Return an array of SIDs from a ldb_message given an attribute name assumes
51 * the SIDs are in NDR form (with additional sids applied on the end).
53 WERROR samdb_result_sid_array_ndr(struct ldb_context *sam_ctx,
54 struct ldb_message *msg,
55 TALLOC_CTX *mem_ctx,
56 const char *attr,
57 uint32_t *num_sids,
58 struct dom_sid **sids,
59 const struct dom_sid *additional_sids,
60 unsigned int num_additional)
62 struct ldb_message_element *el;
63 unsigned int i, j;
65 el = ldb_msg_find_element(msg, attr);
66 if (!el) {
67 *sids = NULL;
68 return WERR_OK;
71 /* Make array long enough for NULL and additional SID */
72 (*sids) = talloc_array(mem_ctx, struct dom_sid,
73 el->num_values + num_additional);
74 W_ERROR_HAVE_NO_MEMORY(*sids);
76 for (i=0; i<el->num_values; i++) {
77 enum ndr_err_code ndr_err;
79 ndr_err = ndr_pull_struct_blob_all_noalloc(&el->values[i], &(*sids)[i],
80 (ndr_pull_flags_fn_t)ndr_pull_dom_sid);
81 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
82 return WERR_INTERNAL_DB_CORRUPTION;
86 for (j = 0; j < num_additional; j++) {
87 (*sids)[i++] = additional_sids[j];
90 *num_sids = i;
92 return WERR_OK;
96 return an array of SIDs from a ldb_message given an attribute name
97 assumes the SIDs are in extended DN format
99 WERROR samdb_result_sid_array_dn(struct ldb_context *sam_ctx,
100 struct ldb_message *msg,
101 TALLOC_CTX *mem_ctx,
102 const char *attr,
103 uint32_t *num_sids,
104 struct dom_sid **sids)
106 struct ldb_message_element *el;
107 unsigned int i;
109 el = ldb_msg_find_element(msg, attr);
110 if (!el) {
111 *sids = NULL;
112 return WERR_OK;
115 (*sids) = talloc_array(mem_ctx, struct dom_sid, el->num_values + 1);
116 W_ERROR_HAVE_NO_MEMORY(*sids);
118 for (i=0; i<el->num_values; i++) {
119 struct ldb_dn *dn = ldb_dn_from_ldb_val(mem_ctx, sam_ctx, &el->values[i]);
120 NTSTATUS status;
121 struct dom_sid sid = { 0, };
123 status = dsdb_get_extended_dn_sid(dn, &sid, "SID");
124 if (!NT_STATUS_IS_OK(status)) {
125 return WERR_INTERNAL_DB_CORRUPTION;
127 (*sids)[i] = sid;
129 *num_sids = i;
131 return WERR_OK;
134 WERROR samdb_confirm_rodc_allowed_to_repl_to_sid_list(struct ldb_context *sam_ctx,
135 struct ldb_message *rodc_msg,
136 uint32_t num_token_sids,
137 struct dom_sid *token_sids)
139 uint32_t num_never_reveal_sids, num_reveal_sids;
140 struct dom_sid *never_reveal_sids, *reveal_sids;
141 TALLOC_CTX *frame = talloc_stackframe();
142 WERROR werr = samdb_result_sid_array_dn(sam_ctx, rodc_msg,
143 frame, "msDS-NeverRevealGroup",
144 &num_never_reveal_sids,
145 &never_reveal_sids);
146 if (!W_ERROR_IS_OK(werr)) {
147 TALLOC_FREE(frame);
148 return WERR_DS_DRA_SECRETS_DENIED;
151 werr = samdb_result_sid_array_dn(sam_ctx, rodc_msg,
152 frame, "msDS-RevealOnDemandGroup",
153 &num_reveal_sids,
154 &reveal_sids);
155 if (!W_ERROR_IS_OK(werr)) {
156 TALLOC_FREE(frame);
157 return WERR_DS_DRA_SECRETS_DENIED;
160 if (never_reveal_sids &&
161 sid_list_match(num_token_sids,
162 token_sids,
163 num_never_reveal_sids,
164 never_reveal_sids)) {
165 TALLOC_FREE(frame);
166 return WERR_DS_DRA_SECRETS_DENIED;
169 if (reveal_sids &&
170 sid_list_match(num_token_sids,
171 token_sids,
172 num_reveal_sids,
173 reveal_sids)) {
174 TALLOC_FREE(frame);
175 return WERR_OK;
178 TALLOC_FREE(frame);
179 return WERR_DS_DRA_SECRETS_DENIED;