2 Unix SMB/CIFS implementation.
3 Samba utility functions
4 Copyright (C) Ralph Boehme 2024
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program. If not, see <http://www.gnu.org/licenses/>.
21 #include "lib/util/strv.h"
22 #include "libcli/security/security.h"
23 #include "source3/lib/substitute.h"
24 #include "passdb/lookup_sid.h"
28 * No prefix means direct username
29 * @name means netgroup first, then unix group
30 * &name means netgroup
31 * +name means unix group
32 * + and & may be combined
35 static bool do_group_checks(const char **name
, const char **pattern
)
37 if ((*name
)[0] == '@') {
43 if (((*name
)[0] == '+') && ((*name
)[1] == '&')) {
49 if ((*name
)[0] == '+') {
55 if (((*name
)[0] == '&') && ((*name
)[1] == '+')) {
61 if ((*name
)[0] == '&') {
70 bool token_contains_name(TALLOC_CTX
*mem_ctx
,
73 const char *sharename
,
74 const struct security_token
*token
,
80 enum lsa_SidType type
;
85 if (username
!= NULL
) {
86 size_t domain_len
= domain
!= NULL
? strlen(domain
) : 0;
88 /* Check if username starts with domain name */
90 const char *sep
= lp_winbind_separator();
91 int cmp
= strncasecmp_m(username
, domain
, domain_len
);
92 if (cmp
== 0 && sep
[0] == username
[domain_len
]) {
93 /* Move after the winbind separator */
99 name
= talloc_sub_basic(mem_ctx
,
100 username
+ domain_len
,
104 if (sharename
!= NULL
) {
105 name
= talloc_string_sub(mem_ctx
, name
, "%S", sharename
);
112 if ( string_to_sid( &sid
, name
) ) {
113 DEBUG(5,("token_contains_name: Checking for SID [%s] in token\n", name
));
114 *match
= nt_token_check_sid( &sid
, token
);
118 if (!do_group_checks(&name
, &prefix
)) {
119 status
= lookup_name_smbconf_ex(mem_ctx
,
126 if (!NT_STATUS_IS_OK(status
)) {
127 DBG_ERR("lookup_name '%s' failed %s\n",
128 name
, nt_errstr(status
));
131 if (type
!= SID_NAME_USER
) {
132 DBG_WARNING("%s is a %s, expected a user\n",
133 name
, sid_type_lookup(type
));
136 *match
= nt_token_check_sid(&sid
, token
);
140 for (/* initialized above */ ; *prefix
!= '\0'; prefix
++) {
141 if (*prefix
== '+') {
142 status
= lookup_name_smbconf_ex(
145 LOOKUP_NAME_ALL
|LOOKUP_NAME_GROUP
,
150 if (!NT_STATUS_IS_OK(status
)) {
151 DBG_ERR("lookup_name '%s' failed %s\n",
152 name
, nt_errstr(status
));
155 if ((type
!= SID_NAME_DOM_GRP
) &&
156 (type
!= SID_NAME_ALIAS
) &&
157 (type
!= SID_NAME_WKN_GRP
)) {
158 DBG_WARNING("%s is a %s, expected a group\n",
159 name
, sid_type_lookup(type
));
162 if (nt_token_check_sid(&sid
, token
)) {
168 if (*prefix
== '&') {
170 if (user_in_netgroup(mem_ctx
, username
, name
)) {
177 smb_panic("got invalid prefix from do_groups_check");
182 static size_t namearray_len(const struct name_compare_entry
*array
)
186 while (array
[i
].name
!= NULL
) {
193 /*******************************************************************
194 Strip a '/' separated list into an array of
195 name_compare_entry structures suitable for
196 passing to is_in_path(). We do this for
197 speed so we can pre-parse all the names in the list
198 and don't do it for each call to is_in_path().
199 We also check if the entry contains a wildcard to
200 remove a potentially expensive call to mask_match
202 ********************************************************************/
204 bool append_to_namearray(TALLOC_CTX
*mem_ctx
,
205 const char *namelist_in
,
206 struct name_compare_entry
**_name_array
)
208 struct name_compare_entry
*name_array
= *_name_array
;
210 char *namelist
= NULL
;
211 const char *p
= NULL
;
213 if ((namelist_in
== NULL
) || (namelist_in
[0] == '\0')) {
217 if (name_array
== NULL
) {
218 name_array
= talloc_zero(mem_ctx
, struct name_compare_entry
);
219 if (name_array
== NULL
) {
223 len
= namearray_len(name_array
);
225 namelist
= path_to_strv(name_array
, namelist_in
);
226 if (namelist
== NULL
) {
227 DBG_ERR("path_to_strv failed\n");
231 while ((p
= strv_next(namelist
, p
)) != NULL
) {
232 struct name_compare_entry
*tmp
= NULL
;
235 /* cope with multiple (useless) /s) */
239 tmp
= talloc_realloc(mem_ctx
,
241 struct name_compare_entry
,
248 name_array
[len
] = (struct name_compare_entry
){
250 .is_wild
= ms_has_wild(p
),
252 name_array
[len
+ 1] = (struct name_compare_entry
){};
256 *_name_array
= name_array
;
260 bool set_namearray(TALLOC_CTX
*mem_ctx
,
261 const char *namelist_in
,
262 struct name_compare_entry
**_name_array
)
268 ret
= append_to_namearray(mem_ctx
, namelist_in
, _name_array
);