static bool delete_sid_cache(const struct dom_sid* psid) { DATA_BLOB sid = data_blob_const(psid, ndr_size_dom_sid(psid, 0)); DATA_BLOB id; if (memcache_lookup(NULL, SID_GID_CACHE, sid, &id)) { DEBUG(3, ("Delete mapping %s <-> GID %d from memcache\n", sid_string_dbg(psid), *(int*)id.data)); memcache_delete(NULL, SID_GID_CACHE, sid); memcache_delete(NULL, GID_SID_CACHE, id); } else if (memcache_lookup(NULL, SID_UID_CACHE, sid, &id)) { DEBUG(3, ("Delete mapping %s <-> UID %d from memcache\n", sid_string_dbg(psid), *(int*)id.data)); memcache_delete(NULL, SID_UID_CACHE, sid); memcache_delete(NULL, UID_SID_CACHE, id); } else { DEBUG(3, ("SID %s is not memcached!\n", sid_string_dbg(psid))); return false; } return true; }
static bool delete_gid_cache(gid_t pgid) { DATA_BLOB gid = data_blob_const(&pgid, sizeof(pgid)); DATA_BLOB sid; if (!memcache_lookup(NULL, GID_SID_CACHE, gid, &sid)) { DEBUG(3, ("GID %d is not memcached!\n", (int)pgid)); return false; } DEBUG(3, ("Delete mapping GID %d <-> %s from memcache\n", (int)pgid, sid_string_dbg((struct dom_sid*)sid.data))); memcache_delete(NULL, SID_GID_CACHE, sid); memcache_delete(NULL, GID_SID_CACHE, gid); return true; }
/* lookup an entry in the prefix cache. Return NULL if not found. */ static char *cache_lookup(TALLOC_CTX *mem_ctx, unsigned int hash) { DATA_BLOB value; if (!memcache_lookup(smbd_memcache(), MANGLE_HASH2_CACHE, data_blob_const(&hash, sizeof(hash)), &value)) { return NULL; } SMB_ASSERT((value.length > 0) && (value.data[value.length-1] == '\0')); return talloc_strdup(mem_ctx, (char *)value.data); }
/* 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; }
bool stat_cache_lookup(connection_struct *conn, bool posix_paths, char **pp_name, char **pp_dirpath, char **pp_start, SMB_STRUCT_STAT *pst) { char *chk_name; size_t namelen; bool sizechanged = False; unsigned int num_components = 0; char *translated_path; size_t translated_path_length; DATA_BLOB data_val; char *name; TALLOC_CTX *ctx = talloc_tos(); struct smb_filename smb_fname; int ret; *pp_dirpath = NULL; *pp_start = *pp_name; if (!lp_stat_cache()) { return False; } name = *pp_name; namelen = strlen(name); DO_PROFILE_INC(statcache_lookups); /* * Don't lookup trivial valid directory entries. */ if ((*name == '\0') || ISDOT(name) || ISDOTDOT(name)) { return False; } if (conn->case_sensitive) { chk_name = talloc_strdup(ctx,name); if (!chk_name) { DEBUG(0, ("stat_cache_lookup: strdup failed!\n")); return False; } } else { chk_name = talloc_strdup_upper(ctx,name); if (!chk_name) { DEBUG(0, ("stat_cache_lookup: talloc_strdup_upper failed!\n")); return False; } /* * In some language encodings the length changes * if we uppercase. We need to treat this differently * below. */ if (strlen(chk_name) != namelen) { sizechanged = True; } } while (1) { char *sp; data_val = data_blob_null; if (memcache_lookup( smbd_memcache(), STAT_CACHE, data_blob_const(chk_name, strlen(chk_name)), &data_val)) { break; } DEBUG(10,("stat_cache_lookup: lookup failed for name [%s]\n", chk_name )); /* * Didn't find it - remove last component for next try. */ if (!(sp = strrchr_m(chk_name, '/'))) { /* * We reached the end of the name - no match. */ DO_PROFILE_INC(statcache_misses); TALLOC_FREE(chk_name); return False; } *sp = '\0'; /* * Count the number of times we have done this, we'll * need it when reconstructing the string. */ if (sizechanged) { num_components++; } if ((*chk_name == '\0') || ISDOT(chk_name) || ISDOTDOT(chk_name)) { DO_PROFILE_INC(statcache_misses); TALLOC_FREE(chk_name); return False; } } translated_path = talloc_strdup(ctx,(char *)data_val.data); if (!translated_path) { smb_panic("talloc failed"); } translated_path_length = data_val.length - 1; DEBUG(10,("stat_cache_lookup: lookup succeeded for name [%s] " "-> [%s]\n", chk_name, translated_path )); DO_PROFILE_INC(statcache_hits); ZERO_STRUCT(smb_fname); smb_fname.base_name = translated_path; if (posix_paths) { ret = SMB_VFS_LSTAT(conn, &smb_fname); } else { ret = SMB_VFS_STAT(conn, &smb_fname); } if (ret != 0) { /* Discard this entry - it doesn't exist in the filesystem. */ memcache_delete(smbd_memcache(), STAT_CACHE, data_blob_const(chk_name, strlen(chk_name))); TALLOC_FREE(chk_name); TALLOC_FREE(translated_path); return False; } *pst = smb_fname.st; if (!sizechanged) { memcpy(*pp_name, translated_path, MIN(namelen, translated_path_length)); } else { if (num_components == 0) { name = talloc_strndup(ctx, translated_path, translated_path_length); } else { char *sp; sp = strnrchr_m(name, '/', num_components); if (sp) { name = talloc_asprintf(ctx,"%.*s%s", (int)translated_path_length, translated_path, sp); } else { name = talloc_strndup(ctx, translated_path, translated_path_length); } } if (name == NULL) { /* * TODO: Get us out of here with a real error message */ smb_panic("talloc failed"); } TALLOC_FREE(*pp_name); *pp_name = name; } /* set pointer for 'where to start' on fixing the rest of the name */ *pp_start = &name[translated_path_length]; if (**pp_start == '/') { ++*pp_start; } *pp_dirpath = translated_path; TALLOC_FREE(chk_name); return (namelen == translated_path_length); }