winbindd_util.c
来自「samba-3.0.22.tar.gz 编译smb服务器的源码」· C语言 代码 · 共 1,210 行 · 第 1/2 页
C
1,210 行
/* Unix SMB/CIFS implementation. Winbind daemon for ntdom nss module Copyright (C) Tim Potter 2000-2001 Copyright (C) 2001 by Martin Pool <mbp@samba.org> This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.*/#include "includes.h"#include "winbindd.h"#undef DBGC_CLASS#define DBGC_CLASS DBGC_WINBIND/** * @file winbindd_util.c * * Winbind daemon for NT domain authentication nss module. **//** * Used to clobber name fields that have an undefined value. * * Correct code should never look at a field that has this value. **/static const fstring name_deadbeef = "<deadbeef>";/* The list of trusted domains. Note that the list can be deleted and recreated using the init_domain_list() function so pointers to individual winbindd_domain structures cannot be made. Keep a copy of the domain name instead. */static struct winbindd_domain *_domain_list;/** When was the last scan of trusted domains done? 0 == not ever*/static time_t last_trustdom_scan;struct winbindd_domain *domain_list(void){ /* Initialise list */ if (!_domain_list) init_domain_list(); return _domain_list;}/* Free all entries in the trusted domain list */void free_domain_list(void){ struct winbindd_domain *domain = _domain_list; while(domain) { struct winbindd_domain *next = domain->next; DLIST_REMOVE(_domain_list, domain); SAFE_FREE(domain); domain = next; }}static BOOL is_internal_domain(const DOM_SID *sid){ if (sid == NULL) return False; return (sid_check_is_domain(sid) || sid_check_is_builtin(sid));}static BOOL is_in_internal_domain(const DOM_SID *sid){ if (sid == NULL) return False; return (sid_check_is_in_our_domain(sid) || sid_check_is_in_builtin(sid));}/* Add a trusted domain to our list of domains */static struct winbindd_domain *add_trusted_domain(const char *domain_name, const char *alt_name, struct winbindd_methods *methods, const DOM_SID *sid){ struct winbindd_domain *domain; const char *alternative_name = NULL; /* ignore alt_name if we are not in an AD domain */ if ( (lp_security() == SEC_ADS) && alt_name && *alt_name) { alternative_name = alt_name; } /* We can't call domain_list() as this function is called from init_domain_list() and we'll get stuck in a loop. */ for (domain = _domain_list; domain; domain = domain->next) { if (strequal(domain_name, domain->name) || strequal(domain_name, domain->alt_name)) { return domain; } if (alternative_name && *alternative_name) { if (strequal(alternative_name, domain->name) || strequal(alternative_name, domain->alt_name)) { return domain; } } if (sid) { if (is_null_sid(sid)) { } else if (sid_equal(sid, &domain->sid)) { return domain; } } } /* Create new domain entry */ if ((domain = SMB_MALLOC_P(struct winbindd_domain)) == NULL) return NULL; /* Fill in fields */ ZERO_STRUCTP(domain); /* prioritise the short name */ if (strchr_m(domain_name, '.') && alternative_name && *alternative_name) { fstrcpy(domain->name, alternative_name); fstrcpy(domain->alt_name, domain_name); } else { fstrcpy(domain->name, domain_name); if (alternative_name) { fstrcpy(domain->alt_name, alternative_name); } } domain->methods = methods; domain->backend = NULL; domain->internal = is_internal_domain(sid); domain->sequence_number = DOM_SEQUENCE_NONE; domain->last_seq_check = 0; domain->initialized = False; if (sid) { sid_copy(&domain->sid, sid); } /* Link to domain list */ DLIST_ADD(_domain_list, domain); DEBUG(2,("Added domain %s %s %s\n", domain->name, domain->alt_name, &domain->sid?sid_string_static(&domain->sid):"")); return domain;}/******************************************************************** rescan our domains looking for new trusted domains********************************************************************/struct trustdom_state { TALLOC_CTX *mem_ctx; struct winbindd_response *response;};static void trustdom_recv(void *private_data, BOOL success);static void add_trusted_domains( struct winbindd_domain *domain ){ TALLOC_CTX *mem_ctx; struct winbindd_request *request; struct winbindd_response *response; struct trustdom_state *state; mem_ctx = talloc_init("add_trusted_domains"); if (mem_ctx == NULL) { DEBUG(0, ("talloc_init failed\n")); return; } request = TALLOC_ZERO_P(mem_ctx, struct winbindd_request); response = TALLOC_P(mem_ctx, struct winbindd_response); state = TALLOC_P(mem_ctx, struct trustdom_state); if ((request == NULL) || (response == NULL) || (state == NULL)) { DEBUG(0, ("talloc failed\n")); talloc_destroy(mem_ctx); return; } state->mem_ctx = mem_ctx; state->response = response; request->length = sizeof(*request); request->cmd = WINBINDD_LIST_TRUSTDOM; async_domain_request(mem_ctx, domain, request, response, trustdom_recv, state);}static void trustdom_recv(void *private_data, BOOL success){ extern struct winbindd_methods cache_methods; struct trustdom_state *state = talloc_get_type_abort(private_data, struct trustdom_state); struct winbindd_response *response = state->response; char *p; if ((!success) || (response->result != WINBINDD_OK)) { DEBUG(1, ("Could not receive trustdoms\n")); talloc_destroy(state->mem_ctx); return; } p = response->extra_data; while ((p != NULL) && (*p != '\0')) { char *q, *sidstr, *alt_name; DOM_SID sid; alt_name = strchr(p, '\\'); if (alt_name == NULL) { DEBUG(0, ("Got invalid trustdom response\n")); break; } *alt_name = '\0'; alt_name += 1; sidstr = strchr(alt_name, '\\'); if (sidstr == NULL) { DEBUG(0, ("Got invalid trustdom response\n")); break; } *sidstr = '\0'; sidstr += 1; q = strchr(sidstr, '\n'); if (q != NULL) *q = '\0'; if (!string_to_sid(&sid, sidstr)) { DEBUG(0, ("Got invalid trustdom response\n")); break; } if (find_domain_from_name_noinit(p) == NULL) { struct winbindd_domain *domain; char *alternate_name = NULL; /* use the real alt_name if we have one, else pass in NULL */ if ( !strequal( alt_name, "(null)" ) ) alternate_name = alt_name; domain = add_trusted_domain(p, alternate_name, &cache_methods, &sid); setup_domain_child(domain, &domain->child, NULL); } p=q; if (p != NULL) p += 1; } SAFE_FREE(response->extra_data); talloc_destroy(state->mem_ctx);}/******************************************************************** Periodically we need to refresh the trusted domain cache for smbd ********************************************************************/void rescan_trusted_domains( void ){ time_t now = time(NULL); /* see if the time has come... */ if ((now >= last_trustdom_scan) && ((now-last_trustdom_scan) < WINBINDD_RESCAN_FREQ) ) return; /* this will only add new domains we didn't already know about */ add_trusted_domains( find_our_domain() ); last_trustdom_scan = now; return; }struct init_child_state { TALLOC_CTX *mem_ctx; struct winbindd_domain *domain; struct winbindd_request *request; struct winbindd_response *response; void (*continuation)(void *private_data, BOOL success); void *private_data;};static void init_child_recv(void *private_data, BOOL success);static void init_child_getdc_recv(void *private_data, BOOL success);enum winbindd_result init_child_connection(struct winbindd_domain *domain, void (*continuation)(void *private_data, BOOL success), void *private_data){ TALLOC_CTX *mem_ctx; struct winbindd_request *request; struct winbindd_response *response; struct init_child_state *state; mem_ctx = talloc_init("init_child_connection"); if (mem_ctx == NULL) { DEBUG(0, ("talloc_init failed\n")); return WINBINDD_ERROR; } request = TALLOC_ZERO_P(mem_ctx, struct winbindd_request); response = TALLOC_P(mem_ctx, struct winbindd_response); state = TALLOC_P(mem_ctx, struct init_child_state); if ((request == NULL) || (response == NULL) || (state == NULL)) { DEBUG(0, ("talloc failed\n")); continuation(private_data, False); return WINBINDD_ERROR; } request->length = sizeof(*request); state->mem_ctx = mem_ctx; state->domain = domain; state->request = request; state->response = response; state->continuation = continuation; state->private_data = private_data; if (domain->primary) { /* The primary domain has to find the DC name itself */ request->cmd = WINBINDD_INIT_CONNECTION; fstrcpy(request->domain_name, domain->name); request->data.init_conn.is_primary = True; fstrcpy(request->data.init_conn.dcname, ""); async_request(mem_ctx, &domain->child, request, response, init_child_recv, state); return WINBINDD_PENDING; } /* This is *not* the primary domain, let's ask our DC about a DC * name */ request->cmd = WINBINDD_GETDCNAME; fstrcpy(request->domain_name, domain->name); async_domain_request(mem_ctx, find_our_domain(), request, response, init_child_getdc_recv, state); return WINBINDD_PENDING;}static void init_child_getdc_recv(void *private_data, BOOL success){ struct init_child_state *state = talloc_get_type_abort(private_data, struct init_child_state); const char *dcname = ""; DEBUG(10, ("Received getdcname response\n")); if (success && (state->response->result == WINBINDD_OK)) { dcname = state->response->data.dc_name; } state->request->cmd = WINBINDD_INIT_CONNECTION; fstrcpy(state->request->domain_name, state->domain->name); state->request->data.init_conn.is_primary = False; fstrcpy(state->request->data.init_conn.dcname, dcname); async_request(state->mem_ctx, &state->domain->child, state->request, state->response, init_child_recv, state);}static void init_child_recv(void *private_data, BOOL success){ struct init_child_state *state = talloc_get_type_abort(private_data, struct init_child_state); DEBUG(5, ("Received child initialization response for domain %s\n", state->domain->name)); if ((!success) || (state->response->result != WINBINDD_OK)) { DEBUG(3, ("Could not init child\n")); state->continuation(state->private_data, False); talloc_destroy(state->mem_ctx); return; } fstrcpy(state->domain->name, state->response->data.domain_info.name); fstrcpy(state->domain->alt_name, state->response->data.domain_info.alt_name); string_to_sid(&state->domain->sid, state->response->data.domain_info.sid); state->domain->native_mode = state->response->data.domain_info.native_mode; state->domain->active_directory = state->response->data.domain_info.active_directory; state->domain->sequence_number = state->response->data.domain_info.sequence_number; state->domain->initialized = 1; if (state->continuation != NULL) state->continuation(state->private_data, True); talloc_destroy(state->mem_ctx);}enum winbindd_result winbindd_dual_init_connection(struct winbindd_domain *domain, struct winbindd_cli_state *state){ struct in_addr ipaddr; /* Ensure null termination */ state->request.domain_name [sizeof(state->request.domain_name)-1]='\0'; state->request.data.init_conn.dcname [sizeof(state->request.data.init_conn.dcname)-1]='\0'; if (strlen(state->request.data.init_conn.dcname) > 0) { fstrcpy(domain->dcname, state->request.data.init_conn.dcname); } if (strlen(domain->dcname) > 0) { if (!resolve_name(domain->dcname, &ipaddr, 0x20)) { DEBUG(2, ("Could not resolve DC name %s for domain %s\n", domain->dcname, domain->name)); return WINBINDD_ERROR; } domain->dcaddr.sin_family = PF_INET; putip((char *)&(domain->dcaddr.sin_addr), (char *)&ipaddr); domain->dcaddr.sin_port = 0; } set_dc_type_and_flags(domain); if (!domain->initialized) { DEBUG(1, ("Could not initialize domain %s\n", state->request.domain_name)); return WINBINDD_ERROR; } fstrcpy(state->response.data.domain_info.name, domain->name); fstrcpy(state->response.data.domain_info.alt_name, domain->alt_name); fstrcpy(state->response.data.domain_info.sid, sid_string_static(&domain->sid)); state->response.data.domain_info.native_mode = domain->native_mode; state->response.data.domain_info.active_directory = domain->active_directory; state->response.data.domain_info.primary = domain->primary; state->response.data.domain_info.sequence_number = domain->sequence_number; return WINBINDD_OK;}/* Look up global info for the winbind daemon */void init_domain_list(void){ extern struct winbindd_methods cache_methods; extern struct winbindd_methods passdb_methods; struct winbindd_domain *domain; /* Free existing list */ free_domain_list(); /* Add ourselves as the first entry. */ if (IS_DC) { domain = add_trusted_domain(get_global_sam_name(), NULL, &passdb_methods, get_global_sam_sid()); } else { DOM_SID our_sid; if (!secrets_fetch_domain_sid(lp_workgroup(), &our_sid)) { smb_panic("Could not fetch our SID - did we join?\n"); } domain = add_trusted_domain( lp_workgroup(), lp_realm(), &cache_methods, &our_sid); } domain->primary = True; setup_domain_child(domain, &domain->child, NULL); /* Add our local SAM domains */ domain = add_trusted_domain("BUILTIN", NULL, &passdb_methods, &global_sid_Builtin); setup_domain_child(domain, &domain->child, NULL); if (!IS_DC) { domain = add_trusted_domain(get_global_sam_name(), NULL, &passdb_methods, get_global_sam_sid()); setup_domain_child(domain, &domain->child, NULL); }}/** * Given a domain name, return the struct winbindd domain info for it * * @note Do *not* pass lp_workgroup() to this function. domain_list * may modify it's value, and free that pointer. Instead, our local * domain may be found by calling find_our_domain(). * directly. * * * @return The domain structure for the named domain, if it is working. */struct winbindd_domain *find_domain_from_name_noinit(const char *domain_name){ struct winbindd_domain *domain; /* Search through list */ for (domain = domain_list(); domain != NULL; domain = domain->next) { if (strequal(domain_name, domain->name) || (domain->alt_name[0] && strequal(domain_name, domain->alt_name))) { return domain; } } /* Not found */ return NULL;}struct winbindd_domain *find_domain_from_name(const char *domain_name){ struct winbindd_domain *domain; domain = find_domain_from_name_noinit(domain_name); if (domain == NULL) return NULL; if (!domain->initialized) set_dc_type_and_flags(domain); return domain;}/* Given a domain sid, return the struct winbindd domain info for it */struct winbindd_domain *find_domain_from_sid_noinit(const DOM_SID *sid){ struct winbindd_domain *domain; /* Search through list */ for (domain = domain_list(); domain != NULL; domain = domain->next) { if (sid_compare_domain(sid, &domain->sid) == 0) return domain; } /* Not found */ return NULL;}/* Given a domain sid, return the struct winbindd domain info for it */
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?