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 3 : 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 3 : char typebuf[16];
36 3 : struct dom_sid_buf sidbuf;
37 3 : char keybuf[sizeof(sidbuf.buf)+10];
38 3 : char *val = NULL;
39 3 : DATA_BLOB data;
40 3 : int ret;
41 3 : bool ok = false;
42 :
43 3 : if ((sid == NULL) || is_null_sid(sid)) {
44 0 : return true;
45 : }
46 3 : if (domain == NULL) {
47 0 : domain = "";
48 : }
49 3 : if (name == NULL) {
50 0 : name = "";
51 : }
52 3 : if (type == SID_NAME_UNKNOWN) {
53 0 : domain = "";
54 0 : name = "";
55 : }
56 :
57 3 : snprintf(typebuf, sizeof(typebuf), "%d", (int)type);
58 :
59 3 : ret = strv_add(talloc_tos(), &val, domain);
60 3 : if (ret != 0) {
61 0 : DBG_DEBUG("strv_add failed: %s\n", strerror(ret));
62 0 : goto fail;
63 : }
64 3 : ret = strv_add(NULL, &val, name);
65 3 : if (ret != 0) {
66 0 : DBG_DEBUG("strv_add failed: %s\n", strerror(ret));
67 0 : goto fail;
68 : }
69 3 : ret = strv_add(NULL, &val, typebuf);
70 3 : if (ret != 0) {
71 0 : DBG_DEBUG("strv_add failed: %s\n", strerror(ret));
72 0 : goto fail;
73 : }
74 :
75 3 : dom_sid_str_buf(sid, &sidbuf);
76 3 : snprintf(keybuf, sizeof(keybuf), "SID2NAME/%s", sidbuf.buf);
77 :
78 3 : data = data_blob_const(val, talloc_get_size(val));
79 :
80 3 : ok = gencache_set_data_blob(keybuf, data, timeout);
81 3 : if (!ok) {
82 0 : DBG_DEBUG("gencache_set_data_blob failed\n");
83 : }
84 3 : fail:
85 3 : 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 4 : static void namemap_cache_find_sid_parser(
100 : const struct gencache_timeout *timeout,
101 : DATA_BLOB blob,
102 : void *private_data)
103 : {
104 4 : struct namemap_cache_find_sid_state *state = private_data;
105 4 : const char *strv = (const char *)blob.data;
106 4 : size_t strv_len = blob.length;
107 4 : const char *domain;
108 4 : const char *name;
109 4 : const char *typebuf;
110 4 : int error = 0;
111 4 : unsigned long type;
112 :
113 4 : state->ok = false;
114 :
115 4 : domain = strv_len_next(strv, strv_len, NULL);
116 4 : if (domain == NULL) {
117 1 : return;
118 : }
119 4 : name = strv_len_next(strv, strv_len, domain);
120 4 : if (name == NULL) {
121 0 : return;
122 : }
123 3 : typebuf = strv_len_next(strv, strv_len, name);
124 3 : if (typebuf == NULL) {
125 0 : return;
126 : }
127 :
128 3 : type = smb_strtoul(typebuf, NULL, 10, &error, SMB_STR_FULL_STR_CONV);
129 3 : if (error != 0) {
130 0 : return;
131 : }
132 :
133 3 : state->fn(domain,
134 : name,
135 : (enum lsa_SidType)type,
136 3 : gencache_timeout_expired(timeout),
137 : state->private_data);
138 :
139 3 : state->ok = true;
140 : }
141 :
142 4 : 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 4 : struct namemap_cache_find_sid_state state = {
151 : .fn = fn, .private_data = private_data
152 : };
153 4 : struct dom_sid_buf sidbuf;
154 4 : char keybuf[sizeof(sidbuf.buf)+10];
155 4 : bool ok;
156 :
157 4 : dom_sid_str_buf(sid, &sidbuf);
158 4 : snprintf(keybuf, sizeof(keybuf), "SID2NAME/%s", sidbuf.buf);
159 :
160 4 : ok = gencache_parse(keybuf, namemap_cache_find_sid_parser, &state);
161 4 : if (!ok) {
162 0 : DBG_DEBUG("gencache_parse(%s) failed\n", keybuf);
163 0 : return false;
164 : }
165 :
166 4 : if (!state.ok) {
167 1 : DBG_DEBUG("Could not parse %s, deleting\n", keybuf);
168 1 : gencache_del(keybuf);
169 1 : return false;
170 : }
171 :
172 0 : return true;
173 : }
174 :
175 871 : 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 3 : char typebuf[16];
181 871 : struct dom_sid_buf sidbuf = {{0}};
182 3 : char *key;
183 3 : char *key_upper;
184 871 : char *val = NULL;
185 3 : DATA_BLOB data;
186 3 : int ret;
187 871 : bool ok = false;
188 :
189 871 : if (domain == NULL) {
190 0 : domain = "";
191 : }
192 871 : if (name == NULL) {
193 0 : name = "";
194 : }
195 871 : if (type != SID_NAME_UNKNOWN) {
196 871 : dom_sid_str_buf(sid, &sidbuf);
197 : }
198 :
199 871 : snprintf(typebuf, sizeof(typebuf), "%d", (int)type);
200 :
201 871 : key = talloc_asprintf(talloc_tos(), "NAME2SID/%s\\%s", domain, name);
202 871 : if (key == NULL) {
203 0 : DBG_DEBUG("talloc_asprintf failed\n");
204 0 : goto fail;
205 : }
206 871 : key_upper = strupper_talloc(key, key);
207 871 : if (key_upper == NULL) {
208 0 : DBG_DEBUG("strupper_talloc failed\n");
209 0 : goto fail;
210 : }
211 :
212 871 : ret = strv_add(key, &val, sidbuf.buf);
213 871 : if (ret != 0) {
214 0 : DBG_DEBUG("strv_add failed: %s\n", strerror(ret));
215 0 : goto fail;
216 : }
217 871 : ret = strv_add(NULL, &val, typebuf);
218 871 : if (ret != 0) {
219 0 : DBG_DEBUG("strv_add failed: %s\n", strerror(ret));
220 0 : goto fail;
221 : }
222 :
223 871 : data = data_blob_const(val, talloc_get_size(val));
224 :
225 871 : ok = gencache_set_data_blob(key_upper, data, timeout);
226 871 : if (!ok) {
227 0 : DBG_DEBUG("gencache_set_data_blob failed\n");
228 : }
229 871 : fail:
230 871 : TALLOC_FREE(key);
231 871 : 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 3 : static void namemap_cache_find_name_parser(
244 : const struct gencache_timeout *timeout,
245 : DATA_BLOB blob,
246 : void *private_data)
247 : {
248 3 : struct namemap_cache_find_name_state *state = private_data;
249 3 : const char *strv = (const char *)blob.data;
250 3 : size_t strv_len = blob.length;
251 3 : const char *sidbuf;
252 3 : const char *sid_endptr;
253 3 : const char *typebuf;
254 3 : int error = 0;
255 3 : struct dom_sid sid;
256 3 : unsigned long type;
257 3 : bool ok;
258 :
259 3 : state->ok = false;
260 :
261 3 : sidbuf = strv_len_next(strv, strv_len, NULL);
262 3 : if (sidbuf == NULL) {
263 0 : return;
264 : }
265 3 : typebuf = strv_len_next(strv, strv_len, sidbuf);
266 3 : if (typebuf == NULL) {
267 0 : return;
268 : }
269 :
270 3 : ok = dom_sid_parse_endp(sidbuf, &sid, &sid_endptr);
271 3 : if (!ok) {
272 0 : return;
273 : }
274 3 : if (*sid_endptr != '\0') {
275 0 : return;
276 : }
277 :
278 3 : type = smb_strtoul(typebuf, NULL, 10, &error, SMB_STR_FULL_STR_CONV);
279 3 : if (error != 0) {
280 0 : return;
281 : }
282 :
283 3 : state->fn(&sid,
284 : (enum lsa_SidType)type,
285 3 : gencache_timeout_expired(timeout),
286 : state->private_data);
287 :
288 3 : state->ok = true;
289 : }
290 :
291 4 : 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 4 : struct namemap_cache_find_name_state state = {
300 : .fn = fn, .private_data = private_data
301 : };
302 4 : char *key;
303 4 : char *key_upper;
304 4 : bool ret = false;
305 4 : bool ok;
306 :
307 4 : key = talloc_asprintf(talloc_tos(), "NAME2SID/%s\\%s", domain, name);
308 4 : if (key == NULL) {
309 0 : DBG_DEBUG("talloc_asprintf failed\n");
310 0 : return false;
311 : }
312 4 : key_upper = strupper_talloc(key, key);
313 4 : if (key_upper == NULL) {
314 0 : DBG_DEBUG("strupper_talloc failed\n");
315 0 : goto fail;
316 : }
317 :
318 4 : ok = gencache_parse(key_upper, namemap_cache_find_name_parser, &state);
319 4 : if (!ok) {
320 1 : DBG_DEBUG("gencache_parse(%s) failed\n", key_upper);
321 1 : goto fail;
322 : }
323 :
324 3 : 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 4 : fail:
331 4 : TALLOC_FREE(key);
332 4 : return ret;
333 : }
|