winbindd_cache.c
来自「samba-3.0.22.tar.gz 编译smb服务器的源码」· C语言 代码 · 共 1,621 行 · 第 1/3 页
C
1,621 行
/* null strings are marked as len 0xFFFF */ centry_put_uint8(centry, 0xFF); return; } len = strlen(s); /* can't handle more than 254 char strings. Truncating is probably best */ if (len > 254) { DEBUG(10,("centry_put_string: truncating len (%d) to: 254\n", len)); len = 254; } centry_put_uint8(centry, len); centry_expand(centry, len); memcpy(centry->data + centry->ofs, s, len); centry->ofs += len;}static void centry_put_sid(struct cache_entry *centry, const DOM_SID *sid) { fstring sid_string; centry_put_string(centry, sid_to_string(sid_string, sid));}/* start a centry for output. When finished, call centry_end()*/struct cache_entry *centry_start(struct winbindd_domain *domain, NTSTATUS status){ struct cache_entry *centry; if (!wcache->tdb) return NULL; centry = SMB_XMALLOC_P(struct cache_entry); centry->len = 8192; /* reasonable default */ centry->data = SMB_XMALLOC_ARRAY(uint8, centry->len); centry->ofs = 0; centry->sequence_number = domain->sequence_number; centry_put_uint32(centry, NT_STATUS_V(status)); centry_put_uint32(centry, centry->sequence_number); return centry;}/* finish a centry and write it to the tdb*/static void centry_end(struct cache_entry *centry, const char *format, ...) PRINTF_ATTRIBUTE(2,3);static void centry_end(struct cache_entry *centry, const char *format, ...){ va_list ap; char *kstr; TDB_DATA key, data; va_start(ap, format); smb_xvasprintf(&kstr, format, ap); va_end(ap); key.dptr = kstr; key.dsize = strlen(kstr); data.dptr = (char *)centry->data; data.dsize = centry->ofs; tdb_store(wcache->tdb, key, data, TDB_REPLACE); free(kstr);}static void wcache_save_name_to_sid(struct winbindd_domain *domain, NTSTATUS status, const char *domain_name, const char *name, const DOM_SID *sid, enum SID_NAME_USE type){ struct cache_entry *centry; fstring uname; centry = centry_start(domain, status); if (!centry) return; centry_put_uint32(centry, type); centry_put_sid(centry, sid); fstrcpy(uname, name); strupper_m(uname); centry_end(centry, "NS/%s/%s", domain_name, uname); DEBUG(10,("wcache_save_name_to_sid: %s -> %s\n", uname, sid_string_static(sid))); centry_free(centry);}static void wcache_save_sid_to_name(struct winbindd_domain *domain, NTSTATUS status, const DOM_SID *sid, const char *domain_name, const char *name, enum SID_NAME_USE type){ struct cache_entry *centry; fstring sid_string; centry = centry_start(domain, status); if (!centry) return; if (NT_STATUS_IS_OK(status)) { centry_put_uint32(centry, type); centry_put_string(centry, domain_name); centry_put_string(centry, name); } centry_end(centry, "SN/%s", sid_to_string(sid_string, sid)); DEBUG(10,("wcache_save_sid_to_name: %s -> %s\n", sid_string, name)); centry_free(centry);}static void wcache_save_user(struct winbindd_domain *domain, NTSTATUS status, WINBIND_USERINFO *info){ struct cache_entry *centry; fstring sid_string; centry = centry_start(domain, status); if (!centry) return; centry_put_string(centry, info->acct_name); centry_put_string(centry, info->full_name); centry_put_string(centry, info->homedir); centry_put_string(centry, info->shell); centry_put_sid(centry, &info->user_sid); centry_put_sid(centry, &info->group_sid); centry_end(centry, "U/%s", sid_to_string(sid_string, &info->user_sid)); DEBUG(10,("wcache_save_user: %s (acct_name %s)\n", sid_string, info->acct_name)); centry_free(centry);}/* Query display info. This is the basic user list fn */static NTSTATUS query_user_list(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, uint32 *num_entries, WINBIND_USERINFO **info){ struct winbind_cache *cache = get_cache(domain); struct cache_entry *centry = NULL; NTSTATUS status; unsigned int i, retry; if (!cache->tdb) goto do_query; centry = wcache_fetch(cache, domain, "UL/%s", domain->name); if (!centry) goto do_query; *num_entries = centry_uint32(centry); if (*num_entries == 0) goto do_cached; (*info) = TALLOC_ARRAY(mem_ctx, WINBIND_USERINFO, *num_entries); if (! (*info)) smb_panic("query_user_list out of memory"); for (i=0; i<(*num_entries); i++) { (*info)[i].acct_name = centry_string(centry, mem_ctx); (*info)[i].full_name = centry_string(centry, mem_ctx); (*info)[i].homedir = centry_string(centry, mem_ctx); (*info)[i].shell = centry_string(centry, mem_ctx); centry_sid(centry, &(*info)[i].user_sid); centry_sid(centry, &(*info)[i].group_sid); }do_cached: status = centry->status; DEBUG(10,("query_user_list: [Cached] - cached list for domain %s status %s\n", domain->name, get_friendly_nt_error_msg(status) )); centry_free(centry); return status;do_query: *num_entries = 0; *info = NULL; /* Return status value returned by seq number check */ if (!NT_STATUS_IS_OK(domain->last_status)) return domain->last_status; /* Put the query_user_list() in a retry loop. There appears to be * some bug either with Windows 2000 or Samba's handling of large * rpc replies. This manifests itself as sudden disconnection * at a random point in the enumeration of a large (60k) user list. * The retry loop simply tries the operation again. )-: It's not * pretty but an acceptable workaround until we work out what the * real problem is. */ retry = 0; do { DEBUG(10,("query_user_list: [Cached] - doing backend query for list for domain %s\n", domain->name )); status = domain->backend->query_user_list(domain, mem_ctx, num_entries, info); if (!NT_STATUS_IS_OK(status)) DEBUG(3, ("query_user_list: returned 0x%08x, " "retrying\n", NT_STATUS_V(status))); if (NT_STATUS_EQUAL(status, NT_STATUS_UNSUCCESSFUL)) { DEBUG(3, ("query_user_list: flushing " "connection cache\n")); invalidate_cm_connection(&domain->conn); } } while (NT_STATUS_V(status) == NT_STATUS_V(NT_STATUS_UNSUCCESSFUL) && (retry++ < 5)); /* and save it */ refresh_sequence_number(domain, False); centry = centry_start(domain, status); if (!centry) goto skip_save; centry_put_uint32(centry, *num_entries); for (i=0; i<(*num_entries); i++) { centry_put_string(centry, (*info)[i].acct_name); centry_put_string(centry, (*info)[i].full_name); centry_put_string(centry, (*info)[i].homedir); centry_put_string(centry, (*info)[i].shell); centry_put_sid(centry, &(*info)[i].user_sid); centry_put_sid(centry, &(*info)[i].group_sid); if (domain->backend->consistent) { /* when the backend is consistent we can pre-prime some mappings */ wcache_save_name_to_sid(domain, NT_STATUS_OK, domain->name, (*info)[i].acct_name, &(*info)[i].user_sid, SID_NAME_USER); wcache_save_sid_to_name(domain, NT_STATUS_OK, &(*info)[i].user_sid, domain->name, (*info)[i].acct_name, SID_NAME_USER); wcache_save_user(domain, NT_STATUS_OK, &(*info)[i]); } } centry_end(centry, "UL/%s", domain->name); centry_free(centry);skip_save: return status;}/* list all domain groups */static NTSTATUS enum_dom_groups(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, uint32 *num_entries, struct acct_info **info){ struct winbind_cache *cache = get_cache(domain); struct cache_entry *centry = NULL; NTSTATUS status; unsigned int i; if (!cache->tdb) goto do_query; centry = wcache_fetch(cache, domain, "GL/%s/domain", domain->name); if (!centry) goto do_query; *num_entries = centry_uint32(centry); if (*num_entries == 0) goto do_cached; (*info) = TALLOC_ARRAY(mem_ctx, struct acct_info, *num_entries); if (! (*info)) smb_panic("enum_dom_groups out of memory"); for (i=0; i<(*num_entries); i++) { fstrcpy((*info)[i].acct_name, centry_string(centry, mem_ctx)); fstrcpy((*info)[i].acct_desc, centry_string(centry, mem_ctx)); (*info)[i].rid = centry_uint32(centry); }do_cached: status = centry->status; DEBUG(10,("enum_dom_groups: [Cached] - cached list for domain %s status %s\n", domain->name, get_friendly_nt_error_msg(status) )); centry_free(centry); return status;do_query: *num_entries = 0; *info = NULL; /* Return status value returned by seq number check */ if (!NT_STATUS_IS_OK(domain->last_status)) return domain->last_status; DEBUG(10,("enum_dom_groups: [Cached] - doing backend query for list for domain %s\n", domain->name )); status = domain->backend->enum_dom_groups(domain, mem_ctx, num_entries, info); /* and save it */ refresh_sequence_number(domain, False); centry = centry_start(domain, status); if (!centry) goto skip_save; centry_put_uint32(centry, *num_entries); for (i=0; i<(*num_entries); i++) { centry_put_string(centry, (*info)[i].acct_name); centry_put_string(centry, (*info)[i].acct_desc); centry_put_uint32(centry, (*info)[i].rid); } centry_end(centry, "GL/%s/domain", domain->name); centry_free(centry);skip_save: return status;}/* list all domain groups */static NTSTATUS enum_local_groups(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, uint32 *num_entries, struct acct_info **info){ struct winbind_cache *cache = get_cache(domain); struct cache_entry *centry = NULL; NTSTATUS status; unsigned int i; if (!cache->tdb) goto do_query; centry = wcache_fetch(cache, domain, "GL/%s/local", domain->name); if (!centry) goto do_query; *num_entries = centry_uint32(centry); if (*num_entries == 0) goto do_cached; (*info) = TALLOC_ARRAY(mem_ctx, struct acct_info, *num_entries); if (! (*info)) smb_panic("enum_dom_groups out of memory"); for (i=0; i<(*num_entries); i++) { fstrcpy((*info)[i].acct_name, centry_string(centry, mem_ctx)); fstrcpy((*info)[i].acct_desc, centry_string(centry, mem_ctx)); (*info)[i].rid = centry_uint32(centry); }do_cached: /* If we are returning cached data and the domain controller is down then we don't know whether the data is up to date or not. Return NT_STATUS_MORE_PROCESSING_REQUIRED to indicate this. */ if (wcache_server_down(domain)) { DEBUG(10, ("enum_local_groups: returning cached user list and server was down\n")); status = NT_STATUS_MORE_PROCESSING_REQUIRED; } else status = centry->status; DEBUG(10,("enum_local_groups: [Cached] - cached list for domain %s status %s\n", domain->name, get_friendly_nt_error_msg(status) )); centry_free(centry); return status;do_query: *num_entries = 0; *info = NULL; /* Return status value returned by seq number check */ if (!NT_STATUS_IS_OK(domain->last_status)) return domain->last_status; DEBUG(10,("enum_local_groups: [Cached] - doing backend query for list for domain %s\n", domain->name )); status = domain->backend->enum_local_groups(domain, mem_ctx, num_entries, info); /* and save it */ refresh_sequence_number(domain, False); centry = centry_start(domain, status); if (!centry) goto skip_save; centry_put_uint32(centry, *num_entries); for (i=0; i<(*num_entries); i++) { centry_put_string(centry, (*info)[i].acct_name); centry_put_string(centry, (*info)[i].acct_desc); centry_put_uint32(centry, (*info)[i].rid); } centry_end(centry, "GL/%s/local", domain->name); centry_free(centry);skip_save: return status;}/* convert a single name to a sid in a domain */static NTSTATUS name_to_sid(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, const char *domain_name, const char *name, DOM_SID *sid, enum SID_NAME_USE *type){ struct winbind_cache *cache = get_cache(domain); struct cache_entry *centry = NULL; NTSTATUS status; fstring uname; if (!cache->tdb) goto do_query; fstrcpy(uname, name); strupper_m(uname); centry = wcache_fetch(cache, domain, "NS/%s/%s", domain_name, uname); if (!centry) goto do_query; *type = (enum SID_NAME_USE)centry_uint32(centry); centry_sid(centry, sid); status = centry->status; DEBUG(10,("name_to_sid: [Cached] - cached name for domain %s status %s\n", domain->name, get_friendly_nt_error_msg(status) )); centry_free(centry); return status;do_query: ZERO_STRUCTP(sid); /* If the seq number check indicated that there is a problem * with this DC, then return that status... except for * access_denied. This is special because the dc may be in * "restrict anonymous = 1" mode, in which case it will deny * most unauthenticated operations, but *will* allow the LSA * name-to-sid that we try as a fallback. */ if (!(NT_STATUS_IS_OK(domain->last_status) || NT_STATUS_EQUAL(domain->last_status, NT_STATUS_ACCESS_DENIED))) return domain->last_status; DEBUG(10,("name_to_sid: [Cached] - doing backend query for name for domain %s\n", domain->name )); status = domain->backend->name_to_sid(domain, mem_ctx, domain_name, name, sid, type); /* and save it */ wcache_save_name_to_sid(domain, status, domain_name, name, sid, *type); if (NT_STATUS_IS_OK(status)) { strupper_m(CONST_DISCARD(char *,domain_name)); strlower_m(CONST_DISCARD(char *,name)); wcache_save_sid_to_name(domain, status, sid, domain_name, name, *type); } return status;}/* convert a sid to a user or group name. The sid is guaranteed to be in the domain given */static NTSTATUS sid_to_name(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, const DOM_SID *sid, char **domain_name, char **name, enum SID_NAME_USE *type){ struct winbind_cache *cache = get_cache(domain); struct cache_entry *centry = NULL; NTSTATUS status; fstring sid_string; if (!cache->tdb) goto do_query; centry = wcache_fetch(cache, domain, "SN/%s", sid_to_string(sid_string, sid)); if (!centry) goto do_query; if (NT_STATUS_IS_OK(centry->status)) { *type = (enum SID_NAME_USE)centry_uint32(centry); *domain_name = centry_string(centry, mem_ctx); *name = centry_string(centry, mem_ctx); } status = centry->status; DEBUG(10,("sid_to_name: [Cached] - cached name for domain %s status %s\n", domain->name, get_friendly_nt_error_msg(status) )); centry_free(centry); return status;do_query: *name = NULL; *domain_name = NULL; /* If the seq number check indicated that there is a problem * with this DC, then return that status... except for * access_denied. This is special because the dc may be in * "restrict anonymous = 1" mode, in which case it will deny * most unauthenticated operations, but *will* allow the LSA * sid-to-name that we try as a fallback. */ if (!(NT_STATUS_IS_OK(domain->last_status) || NT_STATUS_EQUAL(domain->last_status, NT_STATUS_ACCESS_DENIED))) return domain->last_status; DEBUG(10,("sid_to_name: [Cached] - doing backend query for name for domain %s\n", domain->name )); status = domain->backend->sid_to_name(domain, mem_ctx, sid, domain_name, name, type); /* and save it */ refresh_sequence_number(domain, False); wcache_save_sid_to_name(domain, status, sid, *domain_name, *name, *type); /* We can't save the name to sid mapping here, as with sid history a * later name2sid would give the wrong sid. */ return status;}/* Lookup user information from a rid */static NTSTATUS query_user(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, const DOM_SID *user_sid, WINBIND_USERINFO *info){ struct winbind_cache *cache = get_cache(domain); struct cache_entry *centry = NULL; NTSTATUS status; if (!cache->tdb) goto do_query; centry = wcache_fetch(cache, domain, "U/%s", sid_string_static(user_sid)); /* If we have an access denied cache entry and a cached info3 in the samlogon cache then do a query. This will force the rpc back end
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?