libcli:security: allow spaces after BAD:
[Samba.git] / source3 / libsmb / namecache.c
blobeb59b9eb2e2fbcecb814c2c029488fc0b757e4c0
1 /*
2 Unix SMB/CIFS implementation.
4 NetBIOS name cache module on top of gencache mechanism.
6 Copyright (C) Tim Potter 2002
7 Copyright (C) Rafal Szczesniak 2002
8 Copyright (C) Jeremy Allison 2007
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 3 of the License, or
13 (at your option) any later version.
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program. If not, see <http://www.gnu.org/licenses/>.
24 #include "includes.h"
25 #include "lib/gencache.h"
26 #include "libsmb/namequery.h"
28 #define IPSTR_LIST_SEP ","
29 #define IPSTR_LIST_CHAR ','
31 /**
32 * Allocate and initialise an ipstr list using samba_sockaddr ip addresses
33 * passed as arguments.
35 * @param ctx TALLOC_CTX to use
36 * @param ip_list array of ip addresses to place in the list
37 * @param ip_count number of addresses stored in ip_list
38 * @return pointer to allocated ip string
39 **/
41 static char *ipstr_list_make_sa(TALLOC_CTX *ctx,
42 const struct samba_sockaddr *sa_list,
43 size_t ip_count)
45 char *ipstr_list = NULL;
46 size_t i;
48 /* arguments checking */
49 if (sa_list == NULL) {
50 return NULL;
53 /* process ip addresses given as arguments */
54 for (i = 0; i < ip_count; i++) {
55 char addr_buf[INET6_ADDRSTRLEN];
56 char *new_str = NULL;
58 print_sockaddr(addr_buf,
59 sizeof(addr_buf),
60 &sa_list[i].u.ss);
62 if (sa_list[i].u.ss.ss_family == AF_INET) {
63 /* IPv4 - port no longer used, store 0 */
64 new_str = talloc_asprintf(ctx,
65 "%s:%d",
66 addr_buf,
67 0);
68 } else {
69 /* IPv6 - port no longer used, store 0 */
70 new_str = talloc_asprintf(ctx,
71 "[%s]:%d",
72 addr_buf,
73 0);
75 if (new_str == NULL) {
76 TALLOC_FREE(ipstr_list);
77 return NULL;
80 if (ipstr_list == NULL) {
81 /* First ip address. */
82 ipstr_list = new_str;
83 } else {
85 * Append the separator "," and then the new
86 * ip address to the existing list.
88 * The efficiency here is horrible, but
89 * ip_count should be small enough we can
90 * live with it.
92 char *tmp = talloc_asprintf(ctx,
93 "%s%s%s",
94 ipstr_list,
95 IPSTR_LIST_SEP,
96 new_str);
97 if (tmp == NULL) {
98 TALLOC_FREE(new_str);
99 TALLOC_FREE(ipstr_list);
100 return NULL;
102 TALLOC_FREE(new_str);
103 TALLOC_FREE(ipstr_list);
104 ipstr_list = tmp;
108 return ipstr_list;
112 * Parse given ip string list into array of ip addresses
113 * (as ip_service structures)
114 * e.g. [IPv6]:port,192.168.1.100:389,192.168.1.78, ...
116 * @param ipstr ip string list to be parsed
117 * @param ip_list pointer to array of ip addresses which is
118 * talloced by this function and must be freed by caller
119 * @return number of successfully parsed addresses
122 static int ipstr_list_parse(TALLOC_CTX *ctx,
123 const char *ipstr_list,
124 struct samba_sockaddr **sa_list_out)
126 TALLOC_CTX *frame = talloc_stackframe();
127 struct samba_sockaddr *sa_list = NULL;
128 char *token_str = NULL;
129 size_t count;
130 size_t array_size;
132 *sa_list_out = NULL;
134 array_size = count_chars(ipstr_list, IPSTR_LIST_CHAR) + 1;
135 sa_list = talloc_zero_array(frame,
136 struct samba_sockaddr,
137 array_size);
138 if (sa_list == NULL) {
139 TALLOC_FREE(frame);
140 return 0;
143 count = 0;
144 while (next_token_talloc(frame,
145 &ipstr_list,
146 &token_str,
147 IPSTR_LIST_SEP)) {
148 bool ok;
149 char *s = token_str;
150 char *p = strrchr(token_str, ':');
151 struct sockaddr_storage ss;
153 /* Ensure we don't overrun. */
154 if (count >= array_size) {
155 break;
158 if (p) {
159 *p = 0;
160 /* We now ignore the port. */
163 /* convert single token to ip address */
164 if (token_str[0] == '[') {
165 /* IPv6 address. */
166 s++;
167 p = strchr(token_str, ']');
168 if (!p) {
169 continue;
171 *p = '\0';
173 ok = interpret_string_addr(&ss, s, AI_NUMERICHOST);
174 if (!ok) {
175 continue;
177 ok = sockaddr_storage_to_samba_sockaddr(&sa_list[count],
178 &ss);
179 if (!ok) {
180 continue;
182 count++;
184 if (count > 0) {
185 *sa_list_out = talloc_move(ctx, &sa_list);
187 TALLOC_FREE(frame);
188 return count;
191 #define NBTKEY_FMT "NBT/%s#%02X"
194 * Generates a key for netbios name lookups on basis of
195 * netbios name and type.
196 * The caller must free returned key string when finished.
198 * @param name netbios name string (case insensitive)
199 * @param name_type netbios type of the name being looked up
201 * @return string consisted of uppercased name and appended
202 * type number
205 static char *namecache_key(TALLOC_CTX *ctx,
206 const char *name,
207 int name_type)
209 return talloc_asprintf_strupper_m(ctx,
210 NBTKEY_FMT,
211 name,
212 name_type);
216 * Store a name(s) in the name cache - samba_sockaddr version.
218 * @param name netbios names array
219 * @param name_type integer netbios name type
220 * @param num_names number of names being stored
221 * @param ip_list array of in_addr structures containing
222 * ip addresses being stored
225 bool namecache_store(const char *name,
226 int name_type,
227 size_t num_names,
228 struct samba_sockaddr *sa_list)
230 time_t expiry;
231 char *key = NULL;
232 char *value_string = NULL;
233 size_t i;
234 bool ret = false;
235 TALLOC_CTX *frame = talloc_stackframe();
237 if (name_type > 255) {
238 /* Don't store non-real name types. */
239 goto out;
242 if ( DEBUGLEVEL >= 5 ) {
243 char *addr = NULL;
245 DBG_INFO("storing %zu address%s for %s#%02x: ",
246 num_names, num_names == 1 ? "": "es", name, name_type);
248 for (i = 0; i < num_names; i++) {
249 addr = print_canonical_sockaddr(frame,
250 &sa_list[i].u.ss);
251 if (!addr) {
252 continue;
254 DEBUGADD(5, ("%s%s", addr,
255 (i == (num_names - 1) ? "" : ",")));
258 DEBUGADD(5, ("\n"));
261 key = namecache_key(frame, name, name_type);
262 if (!key) {
263 goto out;
266 expiry = time(NULL) + lp_name_cache_timeout();
269 * Generate string representation of ip addresses list
271 value_string = ipstr_list_make_sa(frame, sa_list, num_names);
272 if (value_string == NULL) {
273 goto out;
276 /* set the entry */
277 ret = gencache_set(key, value_string, expiry);
279 out:
281 TALLOC_FREE(key);
282 TALLOC_FREE(value_string);
283 TALLOC_FREE(frame);
284 return ret;
288 * Look up a name in the cache.
290 * @param name netbios name to look up for
291 * @param name_type netbios name type of @param name
292 * @param ip_list talloced list of IP addresses if found in the cache,
293 * NULL otherwise
294 * @param num_names number of entries found
296 * @return true upon successful fetch or
297 * false if name isn't found in the cache or has expired
300 bool namecache_fetch(TALLOC_CTX *ctx,
301 const char *name,
302 int name_type,
303 struct samba_sockaddr **sa_list,
304 size_t *num_names)
306 char *key, *value;
307 time_t timeout;
309 if (name_type > 255) {
310 return false; /* Don't fetch non-real name types. */
313 *num_names = 0;
316 * Use gencache interface - lookup the key
318 key = namecache_key(talloc_tos(), name, name_type);
319 if (!key) {
320 return false;
323 if (!gencache_get(key, talloc_tos(), &value, &timeout)) {
324 DBG_INFO("no entry for %s#%02X found.\n", name, name_type);
325 TALLOC_FREE(key);
326 return false;
329 DBG_INFO("name %s#%02X found.\n", name, name_type);
332 * Split up the stored value into the list of IP addresses
334 *num_names = ipstr_list_parse(ctx, value, sa_list);
336 TALLOC_FREE(key);
337 TALLOC_FREE(value);
339 return *num_names > 0; /* true only if some ip has been fetched */
343 * Remove a namecache entry. Needed for site support.
347 bool namecache_delete(const char *name, int name_type)
349 bool ret;
350 char *key;
352 if (name_type > 255) {
353 return false; /* Don't fetch non-real name types. */
356 key = namecache_key(talloc_tos(), name, name_type);
357 if (!key) {
358 return false;
360 ret = gencache_del(key);
361 TALLOC_FREE(key);
362 return ret;
366 * Delete single namecache entry. Look at the
367 * gencache_iterate definition.
371 static void flush_netbios_name(const char *key,
372 const char *value,
373 time_t timeout,
374 void *dptr)
376 gencache_del(key);
377 DBG_INFO("Deleting entry %s\n", key);
381 * Flush all names from the name cache.
382 * It's done by gencache_iterate()
384 * @return true upon successful deletion or
385 * false in case of an error
388 void namecache_flush(void)
391 * iterate through each NBT cache's entry and flush it
392 * by flush_netbios_name function
394 gencache_iterate(flush_netbios_name, NULL, "NBT/*");
395 DBG_INFO("Namecache flushed\n");
398 /* Construct a name status record key. */
400 static char *namecache_status_record_key(TALLOC_CTX *ctx,
401 const char *name,
402 int name_type1,
403 int name_type2,
404 const struct sockaddr_storage *keyip)
406 char addr[INET6_ADDRSTRLEN];
408 print_sockaddr(addr, sizeof(addr), keyip);
409 return talloc_asprintf_strupper_m(ctx,
410 "NBT/%s#%02X.%02X.%s",
411 name,
412 name_type1,
413 name_type2,
414 addr);
417 /* Store a name status record. */
419 bool namecache_status_store(const char *keyname, int keyname_type,
420 int name_type, const struct sockaddr_storage *keyip,
421 const char *srvname)
423 char *key;
424 time_t expiry;
425 bool ret;
427 key = namecache_status_record_key(talloc_tos(),
428 keyname,
429 keyname_type,
430 name_type,
431 keyip);
432 if (!key)
433 return false;
435 expiry = time(NULL) + lp_name_cache_timeout();
436 ret = gencache_set(key, srvname, expiry);
438 if (ret) {
439 DBG_INFO("entry %s -> %s\n", key, srvname);
440 } else {
441 DBG_INFO("entry %s store failed.\n", key);
444 TALLOC_FREE(key);
445 return ret;
448 /* Fetch a name status record. */
450 bool namecache_status_fetch(const char *keyname,
451 int keyname_type,
452 int name_type,
453 const struct sockaddr_storage *keyip,
454 char *srvname_out)
456 char *key = NULL;
457 char *value = NULL;
458 time_t timeout;
460 key = namecache_status_record_key(talloc_tos(),
461 keyname,
462 keyname_type,
463 name_type,
464 keyip);
465 if (!key)
466 return false;
468 if (!gencache_get(key, talloc_tos(), &value, &timeout)) {
469 DBG_INFO("no entry for %s found.\n", key);
470 TALLOC_FREE(key);
471 return false;
472 } else {
473 DBG_INFO("key %s -> %s\n", key, value);
476 strlcpy(srvname_out, value, 16);
477 TALLOC_FREE(key);
478 TALLOC_FREE(value);
479 return true;