Line data Source code
1 : /*
2 : * Unix SMB/CIFS implementation.
3 : * Utils for caching sid2name and name2sid
4 : * Copyright (C) Volker Lendecke 2017
5 : *
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.
10 : *
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.
15 : *
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/>.
18 : */
19 :
20 : #include "replace.h"
21 : #include "namemap_cache.h"
22 : #include "source3/lib/gencache.h"
23 : #include "lib/util/debug.h"
24 : #include "lib/util/strv.h"
25 : #include "lib/util/util.h"
26 : #include "lib/util/talloc_stack.h"
27 : #include "lib/util/charset/charset.h"
28 : #include "libcli/security/dom_sid.h"
29 : #include "lib/util/smb_strtox.h"
30 :
31 0 : bool namemap_cache_set_sid2name(const struct dom_sid *sid,
32 : const char *domain, const char *name,
33 : enum lsa_SidType type, time_t timeout)
34 : {
35 : char typebuf[16];
36 : struct dom_sid_buf sidbuf;
37 : char keybuf[sizeof(sidbuf.buf)+10];
38 0 : char *val = NULL;
39 : DATA_BLOB data;
40 : int ret;
41 0 : bool ok = false;
42 :
43 0 : if ((sid == NULL) || is_null_sid(sid)) {
44 0 : return true;
45 : }
46 0 : if (domain == NULL) {
47 0 : domain = "";
48 : }
49 0 : if (name == NULL) {
50 0 : name = "";
51 : }
52 0 : if (type == SID_NAME_UNKNOWN) {
53 0 : domain = "";
54 0 : name = "";
55 : }
56 :
57 0 : snprintf(typebuf, sizeof(typebuf), "%d", (int)type);
58 :
59 0 : ret = strv_add(talloc_tos(), &val, domain);
60 0 : if (ret != 0) {
61 0 : DBG_DEBUG("strv_add failed: %s\n", strerror(ret));
62 0 : goto fail;
63 : }
64 0 : ret = strv_add(NULL, &val, name);
65 0 : if (ret != 0) {
66 0 : DBG_DEBUG("strv_add failed: %s\n", strerror(ret));
67 0 : goto fail;
68 : }
69 0 : ret = strv_add(NULL, &val, typebuf);
70 0 : if (ret != 0) {
71 0 : DBG_DEBUG("strv_add failed: %s\n", strerror(ret));
72 0 : goto fail;
73 : }
74 :
75 0 : dom_sid_str_buf(sid, &sidbuf);
76 0 : snprintf(keybuf, sizeof(keybuf), "SID2NAME/%s", sidbuf.buf);
77 :
78 0 : data = data_blob_const(val, talloc_get_size(val));
79 :
80 0 : ok = gencache_set_data_blob(keybuf, data, timeout);
81 0 : if (!ok) {
82 0 : DBG_DEBUG("gencache_set_data_blob failed\n");
83 : }
84 0 : fail:
85 0 : TALLOC_FREE(val);
86 0 : return ok;
87 : }
88 :
89 : struct namemap_cache_find_sid_state {
90 : void (*fn)(const char *domain,
91 : const char *name,
92 : enum lsa_SidType type,
93 : bool expired,
94 : void *private_data);
95 : void *private_data;
96 : bool ok;
97 : };
98 :
99 0 : static void namemap_cache_find_sid_parser(
100 : const struct gencache_timeout *timeout,
101 : DATA_BLOB blob,
102 : void *private_data)
103 : {
104 0 : struct namemap_cache_find_sid_state *state = private_data;
105 0 : const char *strv = (const char *)blob.data;
106 0 : size_t strv_len = blob.length;
107 : const char *domain;
108 : const char *name;
109 : const char *typebuf;
110 0 : int error = 0;
111 : unsigned long type;
112 :
113 0 : state->ok = false;
114 :
115 0 : domain = strv_len_next(strv, strv_len, NULL);
116 0 : if (domain == NULL) {
117 0 : return;
118 : }
119 0 : name = strv_len_next(strv, strv_len, domain);
120 0 : if (name == NULL) {
121 0 : return;
122 : }
123 0 : typebuf = strv_len_next(strv, strv_len, name);
124 0 : if (typebuf == NULL) {
125 0 : return;
126 : }
127 :
128 0 : type = smb_strtoul(typebuf, NULL, 10, &error, SMB_STR_FULL_STR_CONV);
129 0 : if (error != 0) {
130 0 : return;
131 : }
132 :
133 0 : state->fn(domain,
134 : name,
135 : (enum lsa_SidType)type,
136 0 : gencache_timeout_expired(timeout),
137 : state->private_data);
138 :
139 0 : state->ok = true;
140 : }
141 :
142 0 : bool namemap_cache_find_sid(const struct dom_sid *sid,
143 : void (*fn)(const char *domain,
144 : const char *name,
145 : enum lsa_SidType type,
146 : bool expired,
147 : void *private_data),
148 : void *private_data)
149 : {
150 0 : struct namemap_cache_find_sid_state state = {
151 : .fn = fn, .private_data = private_data
152 : };
153 : struct dom_sid_buf sidbuf;
154 : char keybuf[sizeof(sidbuf.buf)+10];
155 : bool ok;
156 :
157 0 : dom_sid_str_buf(sid, &sidbuf);
158 0 : snprintf(keybuf, sizeof(keybuf), "SID2NAME/%s", sidbuf.buf);
159 :
160 0 : ok = gencache_parse(keybuf, namemap_cache_find_sid_parser, &state);
161 0 : if (!ok) {
162 0 : DBG_DEBUG("gencache_parse(%s) failed\n", keybuf);
163 0 : return false;
164 : }
165 :
166 0 : if (!state.ok) {
167 0 : DBG_DEBUG("Could not parse %s, deleting\n", keybuf);
168 0 : gencache_del(keybuf);
169 0 : return false;
170 : }
171 :
172 0 : return true;
173 : }
174 :
175 615 : bool namemap_cache_set_name2sid(const char *domain, const char *name,
176 : const struct dom_sid *sid,
177 : enum lsa_SidType type,
178 : time_t timeout)
179 : {
180 : char typebuf[16];
181 615 : struct dom_sid_buf sidbuf = {{0}};
182 : char *key;
183 : char *key_upper;
184 615 : char *val = NULL;
185 : DATA_BLOB data;
186 : int ret;
187 615 : bool ok = false;
188 :
189 615 : if (domain == NULL) {
190 0 : domain = "";
191 : }
192 615 : if (name == NULL) {
193 0 : name = "";
194 : }
195 615 : if (type != SID_NAME_UNKNOWN) {
196 615 : dom_sid_str_buf(sid, &sidbuf);
197 : }
198 :
199 615 : snprintf(typebuf, sizeof(typebuf), "%d", (int)type);
200 :
201 615 : key = talloc_asprintf(talloc_tos(), "NAME2SID/%s\\%s", domain, name);
202 615 : if (key == NULL) {
203 0 : DBG_DEBUG("talloc_asprintf failed\n");
204 0 : goto fail;
205 : }
206 615 : key_upper = strupper_talloc(key, key);
207 615 : if (key_upper == NULL) {
208 0 : DBG_DEBUG("strupper_talloc failed\n");
209 0 : goto fail;
210 : }
211 :
212 615 : ret = strv_add(key, &val, sidbuf.buf);
213 615 : if (ret != 0) {
214 0 : DBG_DEBUG("strv_add failed: %s\n", strerror(ret));
215 0 : goto fail;
216 : }
217 615 : ret = strv_add(NULL, &val, typebuf);
218 615 : if (ret != 0) {
219 0 : DBG_DEBUG("strv_add failed: %s\n", strerror(ret));
220 0 : goto fail;
221 : }
222 :
223 615 : data = data_blob_const(val, talloc_get_size(val));
224 :
225 615 : ok = gencache_set_data_blob(key_upper, data, timeout);
226 615 : if (!ok) {
227 0 : DBG_DEBUG("gencache_set_data_blob failed\n");
228 : }
229 923 : fail:
230 615 : TALLOC_FREE(key);
231 615 : return ok;
232 : }
233 :
234 : struct namemap_cache_find_name_state {
235 : void (*fn)(const struct dom_sid *sid,
236 : enum lsa_SidType type,
237 : bool expired,
238 : void *private_data);
239 : void *private_data;
240 : bool ok;
241 : };
242 :
243 0 : static void namemap_cache_find_name_parser(
244 : const struct gencache_timeout *timeout,
245 : DATA_BLOB blob,
246 : void *private_data)
247 : {
248 0 : struct namemap_cache_find_name_state *state = private_data;
249 0 : const char *strv = (const char *)blob.data;
250 0 : size_t strv_len = blob.length;
251 : const char *sidbuf;
252 : const char *sid_endptr;
253 : const char *typebuf;
254 0 : int error = 0;
255 : struct dom_sid sid;
256 : unsigned long type;
257 : bool ok;
258 :
259 0 : state->ok = false;
260 :
261 0 : sidbuf = strv_len_next(strv, strv_len, NULL);
262 0 : if (sidbuf == NULL) {
263 0 : return;
264 : }
265 0 : typebuf = strv_len_next(strv, strv_len, sidbuf);
266 0 : if (typebuf == NULL) {
267 0 : return;
268 : }
269 :
270 0 : ok = dom_sid_parse_endp(sidbuf, &sid, &sid_endptr);
271 0 : if (!ok) {
272 0 : return;
273 : }
274 0 : if (*sid_endptr != '\0') {
275 0 : return;
276 : }
277 :
278 0 : type = smb_strtoul(typebuf, NULL, 10, &error, SMB_STR_FULL_STR_CONV);
279 0 : if (error != 0) {
280 0 : return;
281 : }
282 :
283 0 : state->fn(&sid,
284 : (enum lsa_SidType)type,
285 0 : gencache_timeout_expired(timeout),
286 : state->private_data);
287 :
288 0 : state->ok = true;
289 : }
290 :
291 0 : bool namemap_cache_find_name(const char *domain,
292 : const char *name,
293 : void (*fn)(const struct dom_sid *sid,
294 : enum lsa_SidType type,
295 : bool expired,
296 : void *private_data),
297 : void *private_data)
298 : {
299 0 : struct namemap_cache_find_name_state state = {
300 : .fn = fn, .private_data = private_data
301 : };
302 : char *key;
303 : char *key_upper;
304 0 : bool ret = false;
305 : bool ok;
306 :
307 0 : key = talloc_asprintf(talloc_tos(), "NAME2SID/%s\\%s", domain, name);
308 0 : if (key == NULL) {
309 0 : DBG_DEBUG("talloc_asprintf failed\n");
310 0 : return false;
311 : }
312 0 : key_upper = strupper_talloc(key, key);
313 0 : if (key_upper == NULL) {
314 0 : DBG_DEBUG("strupper_talloc failed\n");
315 0 : goto fail;
316 : }
317 :
318 0 : ok = gencache_parse(key_upper, namemap_cache_find_name_parser, &state);
319 0 : if (!ok) {
320 0 : DBG_DEBUG("gencache_parse(%s) failed\n", key_upper);
321 0 : goto fail;
322 : }
323 :
324 0 : if (!state.ok) {
325 0 : DBG_DEBUG("Could not parse %s, deleting\n", key_upper);
326 0 : goto fail;
327 : }
328 :
329 0 : ret = true;
330 0 : fail:
331 0 : TALLOC_FREE(key);
332 0 : return ret;
333 : }
|