/* insert an entry into the prefix cache. The string might not be null terminated */ static void cache_insert(const char *prefix, int length, unsigned int hash) { char *str = SMB_STRNDUP(prefix, length); if (str == NULL) { return; } memcache_add(smbd_memcache(), MANGLE_HASH2_CACHE, data_blob_const(&hash, sizeof(hash)), data_blob_const(str, length+1)); SAFE_FREE(str); }
/* string_match - match string s against token tok */ static bool string_match(const char *tok,const char *s) { size_t tok_len; size_t str_len; const char *cut; /* Return true if a token has the magic value "ALL". Return * true if the token is "FAIL". If the token starts with a "." * (domain name), return true if it matches the last fields of * the string. If the token has the magic value "LOCAL", * return true if the string does not contain a "." * character. If the token ends on a "." (network number), * return true if it matches the first fields of the * string. If the token begins with a "@" (netgroup name), * return true if the string is a (host) member of the * netgroup. Return true if the token fully matches the * string. If the token is a netnumber/netmask pair, return * true if the address is a member of the specified subnet. */ if (tok[0] == '.') { /* domain: match last fields */ if ((str_len = strlen(s)) > (tok_len = strlen(tok)) && strequal(tok, s + str_len - tok_len)) { return true; } } else if (tok[0] == '@') { /* netgroup: look it up */ #ifdef HAVE_NETGROUP DATA_BLOB tmp; char *mydomain = NULL; char *hostname = NULL; bool netgroup_ok = false; if (memcache_lookup( NULL, SINGLETON_CACHE, data_blob_string_const_null("yp_default_domain"), &tmp)) { SMB_ASSERT(tmp.length > 0); mydomain = (tmp.data[0] == '\0') ? NULL : (char *)tmp.data; } else { yp_get_default_domain(&mydomain); memcache_add( NULL, SINGLETON_CACHE, data_blob_string_const_null("yp_default_domain"), data_blob_string_const_null(mydomain?mydomain:"")); } if (!mydomain) { DEBUG(0,("Unable to get default yp domain. " "Try without it.\n")); } if (!(hostname = SMB_STRDUP(s))) { DEBUG(1,("out of memory for strdup!\n")); return false; } netgroup_ok = innetgr(tok + 1, hostname, (char *) 0, mydomain); DEBUG(5,("looking for %s of domain %s in netgroup %s gave %s\n", hostname, mydomain?mydomain:"(ANY)", tok+1, BOOLSTR(netgroup_ok))); SAFE_FREE(hostname); if (netgroup_ok) return true; #else DEBUG(0,("access: netgroup support is not configured\n")); return false; #endif } else if (strequal(tok, "ALL")) { /* all: match any */ return true; } else if (strequal(tok, "FAIL")) { /* fail: match any */ return true; } else if (strequal(tok, "LOCAL")) { /* local: no dots */ if (strchr_m(s, '.') == 0 && !strequal(s, "unknown")) { return true; } } else if (strequal(tok, s)) { /* match host name or address */ return true; } else if (tok[(tok_len = strlen(tok)) - 1] == '.') { /* network */ if (strncmp(tok, s, tok_len) == 0) { return true; } } else if ((cut = strchr_m(tok, '/')) != 0) { /* netnumber/netmask */ if ((isdigit(s[0]) && strchr_m(tok, '.') != NULL) || (tok[0] == '[' && cut > tok && cut[-1] == ']') || ((isxdigit(s[0]) || s[0] == ':') && strchr_m(tok, ':') != NULL)) { /* IPv4/netmask or * [IPv6:addr]/netmask or IPv6:addr/netmask */ return masked_match(tok, cut, s); } } else if (strchr_m(tok, '*') != 0 || strchr_m(tok, '?')) { return unix_wild_match(tok, s); } return false; }
void stat_cache_add( const char *full_orig_name, char *translated_path, bool case_sensitive) { size_t translated_path_length; char *original_path; size_t original_path_length; char saved_char; TALLOC_CTX *ctx = talloc_tos(); if (!lp_stat_cache()) { return; } /* * Don't cache trivial valid directory entries such as . and .. */ if ((*full_orig_name == '\0') || ISDOT(full_orig_name) || ISDOTDOT(full_orig_name)) { return; } /* * If we are in case insentive mode, we don't need to * store names that need no translation - else, it * would be a waste. */ if (case_sensitive && (strcmp(full_orig_name, translated_path) == 0)) { return; } /* * Remove any trailing '/' characters from the * translated path. */ translated_path_length = strlen(translated_path); if(translated_path[translated_path_length-1] == '/') { translated_path_length--; } if(case_sensitive) { original_path = talloc_strdup(ctx,full_orig_name); } else { original_path = talloc_strdup_upper(ctx,full_orig_name); } if (!original_path) { return; } original_path_length = strlen(original_path); if(original_path[original_path_length-1] == '/') { original_path[original_path_length-1] = '\0'; original_path_length--; } if (original_path_length != translated_path_length) { if (original_path_length < translated_path_length) { DEBUG(0, ("OOPS - tried to store stat cache entry " "for weird length paths [%s] %lu and [%s] %lu)!\n", original_path, (unsigned long)original_path_length, translated_path, (unsigned long)translated_path_length)); TALLOC_FREE(original_path); return; } /* we only want to index by the first part of original_path, up to the length of translated_path */ original_path[translated_path_length] = '\0'; original_path_length = translated_path_length; } /* Ensure we're null terminated. */ saved_char = translated_path[translated_path_length]; translated_path[translated_path_length] = '\0'; /* * New entry or replace old entry. */ memcache_add( smbd_memcache(), STAT_CACHE, data_blob_const(original_path, original_path_length), data_blob_const(translated_path, translated_path_length + 1)); DEBUG(5,("stat_cache_add: Added entry (%lx:size %x) %s -> %s\n", (unsigned long)translated_path, (unsigned int)translated_path_length, original_path, translated_path)); translated_path[translated_path_length] = saved_char; TALLOC_FREE(original_path); }