libnet: Fix Coverity ID 1634803 Dereference after null check
[samba4-gss.git] / source3 / lib / util_namearray.c
blob8d05beb7d31ccc337bd4d94e6732f80e34d2b940
1 /*
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/>.
20 #include "includes.h"
21 #include "lib/util/strv.h"
22 #include "libcli/security/security.h"
23 #include "source3/lib/substitute.h"
24 #include "passdb/lookup_sid.h"
25 #include "auth.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] == '@') {
38 *pattern = "&+";
39 *name += 1;
40 return True;
43 if (((*name)[0] == '+') && ((*name)[1] == '&')) {
44 *pattern = "+&";
45 *name += 2;
46 return True;
49 if ((*name)[0] == '+') {
50 *pattern = "+";
51 *name += 1;
52 return True;
55 if (((*name)[0] == '&') && ((*name)[1] == '+')) {
56 *pattern = "&+";
57 *name += 2;
58 return True;
61 if ((*name)[0] == '&') {
62 *pattern = "&";
63 *name += 1;
64 return True;
67 return False;
70 bool token_contains_name(TALLOC_CTX *mem_ctx,
71 const char *username,
72 const char *domain,
73 const char *sharename,
74 const struct security_token *token,
75 const char *name,
76 bool *match)
78 const char *prefix;
79 struct dom_sid sid;
80 enum lsa_SidType type;
81 NTSTATUS status;
83 *match = false;
85 if (username != NULL) {
86 size_t domain_len = domain != NULL ? strlen(domain) : 0;
88 /* Check if username starts with domain name */
89 if (domain_len > 0) {
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 */
94 domain_len += 1;
95 } else {
96 domain_len = 0;
99 name = talloc_sub_basic(mem_ctx,
100 username + domain_len,
101 domain,
102 name);
104 if (sharename != NULL) {
105 name = talloc_string_sub(mem_ctx, name, "%S", sharename);
108 if (name == NULL) {
109 return false;
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 );
115 return true;
118 if (!do_group_checks(&name, &prefix)) {
119 status = lookup_name_smbconf_ex(mem_ctx,
120 name,
121 LOOKUP_NAME_ALL,
122 NULL,
123 NULL,
124 &sid,
125 &type);
126 if (!NT_STATUS_IS_OK(status)) {
127 DBG_ERR("lookup_name '%s' failed %s\n",
128 name, nt_errstr(status));
129 return false;
131 if (type != SID_NAME_USER) {
132 DBG_WARNING("%s is a %s, expected a user\n",
133 name, sid_type_lookup(type));
134 return true;
136 *match = nt_token_check_sid(&sid, token);
137 return true;
140 for (/* initialized above */ ; *prefix != '\0'; prefix++) {
141 if (*prefix == '+') {
142 status = lookup_name_smbconf_ex(
143 mem_ctx,
144 name,
145 LOOKUP_NAME_ALL|LOOKUP_NAME_GROUP,
146 NULL,
147 NULL,
148 &sid,
149 &type);
150 if (!NT_STATUS_IS_OK(status)) {
151 DBG_ERR("lookup_name '%s' failed %s\n",
152 name, nt_errstr(status));
153 return false;
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));
160 return true;
162 if (nt_token_check_sid(&sid, token)) {
163 *match = true;
164 return True;
166 continue;
168 if (*prefix == '&') {
169 if (username) {
170 if (user_in_netgroup(mem_ctx, username, name)) {
171 *match = true;
172 return True;
175 continue;
177 smb_panic("got invalid prefix from do_groups_check");
179 return true;
182 static size_t namearray_len(const struct name_compare_entry *array)
184 size_t i = 0;
186 while (array[i].name != NULL) {
187 i += 1;
190 return i;
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
201 if possible.
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;
209 size_t len;
210 char *namelist = NULL;
211 const char *p = NULL;
213 if ((namelist_in == NULL) || (namelist_in[0] == '\0')) {
214 return true;
217 if (name_array == NULL) {
218 name_array = talloc_zero(mem_ctx, struct name_compare_entry);
219 if (name_array == NULL) {
220 return false;
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");
228 return false;
231 while ((p = strv_next(namelist, p)) != NULL) {
232 struct name_compare_entry *tmp = NULL;
234 if (*p == '\0') {
235 /* cope with multiple (useless) /s) */
236 continue;
239 tmp = talloc_realloc(mem_ctx,
240 name_array,
241 struct name_compare_entry,
242 len + 2);
243 if (tmp == NULL) {
244 return false;
246 name_array = tmp;
248 name_array[len] = (struct name_compare_entry){
249 .name = p,
250 .is_wild = ms_has_wild(p),
252 name_array[len + 1] = (struct name_compare_entry){};
253 len += 1;
256 *_name_array = name_array;
257 return true;
260 bool set_namearray(TALLOC_CTX *mem_ctx,
261 const char *namelist_in,
262 struct name_compare_entry **_name_array)
264 bool ret;
266 *_name_array = NULL;
268 ret = append_to_namearray(mem_ctx, namelist_in, _name_array);
269 return ret;