From 482a9ef278567a35d3bcad1c2048ee97d86bfb9c Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Fri, 5 Oct 2001 00:20:06 +0000 Subject: This is the start of a bit of a rewrite of winbindd's connection handling. I've wrapped up all the decisions about managing, making and closing connections into a connection manager in nsswitch/winbindd_cm.c. It's rather incomplete at the moment - only querying basic user info works at the moment (i.e finger -m DOMAIN/user) and everything else is broken. Jeremy, please take a look and I'll start moving across the rest of winbindd to this new system. (This used to be commit c369cf5af787ed9c642778d21f162716fbf0620e) --- source3/nsswitch/winbindd.c | 220 +++++++++++------------ source3/nsswitch/winbindd.h | 22 +-- source3/nsswitch/winbindd_cache.c | 29 ++++ source3/nsswitch/winbindd_cm.c | 245 ++++++++++++++++++++++++++ source3/nsswitch/winbindd_group.c | 19 +- source3/nsswitch/winbindd_pam.c | 20 ++- source3/nsswitch/winbindd_proto.h | 23 ++- source3/nsswitch/winbindd_user.c | 36 ++-- source3/nsswitch/winbindd_util.c | 354 +++++++++++++++----------------------- 9 files changed, 588 insertions(+), 380 deletions(-) create mode 100644 source3/nsswitch/winbindd_cm.c diff --git a/source3/nsswitch/winbindd.c b/source3/nsswitch/winbindd.c index 13b8478257..9bf4935eff 100644 --- a/source3/nsswitch/winbindd.c +++ b/source3/nsswitch/winbindd.c @@ -130,91 +130,92 @@ static void sighup_handler(int signum) static int create_sock(void) { - struct sockaddr_un sunaddr; - struct stat st; - int sock; - mode_t old_umask; - pstring path; - - /* Create the socket directory or reuse the existing one */ - - if (lstat(WINBINDD_SOCKET_DIR, &st) == -1) { - - if (errno == ENOENT) { - - /* Create directory */ - - if (mkdir(WINBINDD_SOCKET_DIR, 0755) == -1) { - DEBUG(0, ("error creating socket directory %s: %s\n", - WINBINDD_SOCKET_DIR, strerror(errno))); - return -1; - } - + struct sockaddr_un sunaddr; + struct stat st; + int sock; + mode_t old_umask; + pstring path; + + /* Create the socket directory or reuse the existing one */ + + if (lstat(WINBINDD_SOCKET_DIR, &st) == -1) { + + if (errno == ENOENT) { + + /* Create directory */ + + if (mkdir(WINBINDD_SOCKET_DIR, 0755) == -1) { + DEBUG(0, ("error creating socket directory " + "%s: %s\n", WINBINDD_SOCKET_DIR, + strerror(errno))); + return -1; + } + + } else { + + DEBUG(0, ("lstat failed on socket directory %s: %s\n", + WINBINDD_SOCKET_DIR, strerror(errno))); + return -1; + } + } else { - - DEBUG(0, ("lstat failed on socket directory %s: %s\n", - WINBINDD_SOCKET_DIR, strerror(errno))); - return -1; + + /* Check ownership and permission on existing directory */ + + if (!S_ISDIR(st.st_mode)) { + DEBUG(0, ("socket directory %s isn't a directory\n", + WINBINDD_SOCKET_DIR)); + return -1; + } + + if ((st.st_uid != sec_initial_uid()) || + ((st.st_mode & 0777) != 0755)) { + DEBUG(0, ("invalid permissions on socket directory " + "%s\n", WINBINDD_SOCKET_DIR)); + return -1; + } } - - } else { - - /* Check ownership and permission on existing directory */ - if (!S_ISDIR(st.st_mode)) { - DEBUG(0, ("socket directory %s isn't a directory\n", - WINBINDD_SOCKET_DIR)); - return -1; + /* Create the socket file */ + + old_umask = umask(0); + + sock = socket(AF_UNIX, SOCK_STREAM, 0); + + if (sock == -1) { + perror("socket"); + return -1; } - if ((st.st_uid != sec_initial_uid()) || - ((st.st_mode & 0777) != 0755)) { - DEBUG(0, ("invalid permissions on socket directory %s\n", - WINBINDD_SOCKET_DIR)); - return -1; + snprintf(path, sizeof(path), "%s/%s", + WINBINDD_SOCKET_DIR, WINBINDD_SOCKET_NAME); + + unlink(path); + memset(&sunaddr, 0, sizeof(sunaddr)); + sunaddr.sun_family = AF_UNIX; + safe_strcpy(sunaddr.sun_path, path, sizeof(sunaddr.sun_path)-1); + + if (bind(sock, (struct sockaddr *)&sunaddr, sizeof(sunaddr)) == -1) { + DEBUG(0, ("bind failed on winbind socket %s: %s\n", + path, + strerror(errno))); + close(sock); + return -1; } - } - - /* Create the socket file */ - - old_umask = umask(0); - - sock = socket(AF_UNIX, SOCK_STREAM, 0); - - if (sock == -1) { - perror("socket"); - return -1; - } - - snprintf(path, sizeof(path), "%s/%s", - WINBINDD_SOCKET_DIR, WINBINDD_SOCKET_NAME); - - unlink(path); - memset(&sunaddr, 0, sizeof(sunaddr)); - sunaddr.sun_family = AF_UNIX; - safe_strcpy(sunaddr.sun_path, path, sizeof(sunaddr.sun_path)-1); - - if (bind(sock, (struct sockaddr *)&sunaddr, sizeof(sunaddr)) == -1) { - DEBUG(0, ("bind failed on winbind socket %s: %s\n", - path, - strerror(errno))); - close(sock); - return -1; - } - - if (listen(sock, 5) == -1) { - DEBUG(0, ("listen failed on winbind socket %s: %s\n", - path, - strerror(errno))); - close(sock); - return -1; - } - - umask(old_umask); - - /* Success! */ - - return sock; + + if (listen(sock, 5) == -1) { + DEBUG(0, ("listen failed on winbind socket %s: %s\n", + path, + strerror(errno))); + close(sock); + return -1; + } + + umask(old_umask); + + /* Success! */ + + return sock; } struct dispatch_table { @@ -228,9 +229,13 @@ static struct dispatch_table dispatch_table[] = { { WINBINDD_GETPWNAM_FROM_USER, winbindd_getpwnam_from_user }, { WINBINDD_GETPWNAM_FROM_UID, winbindd_getpwnam_from_uid }, + +#if 0 + { WINBINDD_SETPWENT, winbindd_setpwent }, { WINBINDD_ENDPWENT, winbindd_endpwent }, { WINBINDD_GETPWENT, winbindd_getpwent }, + { WINBINDD_GETGROUPS, winbindd_getgroups }, /* Group functions */ @@ -269,6 +274,8 @@ static struct dispatch_table dispatch_table[] = { { WINBINDD_CHECK_MACHACC, winbindd_check_machine_acct }, +#endif + /* End of list */ { WINBINDD_NUM_CMDS, NULL } @@ -290,8 +297,6 @@ static void process_request(struct winbindd_cli_state *state) /* Process command */ - if (!server_state.lsa_handle_open) return; - for (table = dispatch_table; table->fn; table++) { if (state->request.cmd == table->cmd) { state->response.result = table->fn(state); @@ -301,9 +306,8 @@ static void process_request(struct winbindd_cli_state *state) /* In case extra data pointer is NULL */ - if (!state->response.extra_data) { + if (!state->response.extra_data) state->response.length = sizeof(struct winbindd_response); - } } /* Process a new connection by adding it to the client connection list */ @@ -319,20 +323,16 @@ static void new_connection(int accept_sock) len = sizeof(sunaddr); if ((sock = accept(accept_sock, (struct sockaddr *)&sunaddr, &len)) - == -1) { - + == -1) return; - } DEBUG(6,("accepted socket %d\n", sock)); /* Create new connection structure */ - if ((state = (struct winbindd_cli_state *) - malloc(sizeof(*state))) == NULL) { - + if ((state = (struct winbindd_cli_state *) + malloc(sizeof(*state))) == NULL) return; - } ZERO_STRUCTP(state); state->sock = sock; @@ -508,10 +508,6 @@ static void process_loop(int accept_sock) lp_talloc_free(); - /* Do any connection establishment that is needed */ - - establish_connections(False); /* Honour timeout */ - /* Initialise fd lists for select() */ FD_ZERO(&r_fds); @@ -544,15 +540,13 @@ static void process_loop(int accept_sock) /* Add fd for reading */ - if (state->read_buf_len != sizeof(state->request)) { + if (state->read_buf_len != sizeof(state->request)) FD_SET(state->sock, &r_fds); - } /* Add fd for writing */ - if (state->write_buf_len) { + if (state->write_buf_len) FD_SET(state->sock, &w_fds); - } state = state->next; } @@ -566,12 +560,6 @@ static void process_loop(int accept_sock) do_flush_caches(); reload_services_file(True); - /* Close and re-open all connections. This will also - refresh the trusted domains list */ - - winbindd_kill_all_connections(); - establish_connections(True); /* Force re-establish */ - do_sighup = False; } @@ -598,9 +586,8 @@ static void process_loop(int accept_sock) if (selret > 0) { - if (FD_ISSET(accept_sock, &r_fds)) { + if (FD_ISSET(accept_sock, &r_fds)) new_connection(accept_sock); - } /* Process activity on client connections */ @@ -625,9 +612,8 @@ static void process_loop(int accept_sock) /* Data available for writing */ - if (FD_ISSET(state->sock, &w_fds)) { + if (FD_ISSET(state->sock, &w_fds)) client_write(state); - } } } } @@ -645,10 +631,13 @@ int main(int argc, char **argv) BOOL interactive = False; int opt, new_debuglevel = -1; + /* Initialise for running in non-root mode */ + sec_init(); /* Set environment variable so we don't recursively call ourselves. This may also be useful interactively. */ + SETENV(WINBINDD_DONT_ENV, "1", 1); /* Initialise samba/rpc client stuff */ @@ -689,9 +678,8 @@ int main(int argc, char **argv) fstrcpy(global_myname, myhostname()); p = strchr(global_myname, '.'); - if (p) { + if (p) *p = 0; - } } TimeInit(); @@ -701,13 +689,11 @@ int main(int argc, char **argv) exit(1); } - if (new_debuglevel != -1) { + if (new_debuglevel != -1) DEBUGLEVEL = new_debuglevel; - } - if (!interactive) { + if (!interactive) become_daemon(); - } load_interfaces(); @@ -717,13 +703,11 @@ int main(int argc, char **argv) /* Winbind daemon initialisation */ - if (!winbindd_param_init()) { + if (!winbindd_param_init()) return 1; - } - if (!winbindd_idmap_init()) { + if (!winbindd_idmap_init()) return 1; - } winbindd_cache_init(); diff --git a/source3/nsswitch/winbindd.h b/source3/nsswitch/winbindd.h index fe25d5ba5e..17282cf131 100644 --- a/source3/nsswitch/winbindd.h +++ b/source3/nsswitch/winbindd.h @@ -68,17 +68,11 @@ struct getpwent_user { /* Server state structure */ struct winbindd_state { - /* Netbios name of PDC */ - fstring controller; - + /* User and group id pool */ + uid_t uid_low, uid_high; /* Range of uids to allocate */ gid_t gid_low, gid_high; /* Range of gids to allocate */ - - /* Cached handle to lsa pipe */ - CLI_POLICY_HND lsa_handle; - BOOL lsa_handle_open; - BOOL pwdb_initialised; }; extern struct winbindd_state server_state; /* Server information */ @@ -90,22 +84,24 @@ struct winbindd_domain { /* Domain information */ fstring name; /* Domain name */ - fstring controller; /* NetBIOS name of DC */ DOM_SID sid; /* SID for this domain */ BOOL got_domain_info; /* Got controller and sid */ /* Cached handles to samr pipe */ - CLI_POLICY_HND sam_handle, sam_dom_handle; - BOOL sam_handle_open, sam_dom_handle_open; - time_t last_check; - struct winbindd_domain *prev, *next; /* Linked list info */ }; extern struct winbindd_domain *domain_list; /* List of domains we know */ +/* Used to glue a policy handle and cli_state together */ + +typedef struct { + struct cli_state *cli; + POLICY_HND pol; +} CLI_POLICY_HND; + #include "winbindd_proto.h" #include "rpc_parse.h" diff --git a/source3/nsswitch/winbindd_cache.c b/source3/nsswitch/winbindd_cache.c index 3fa50abfba..9c0ad5015c 100644 --- a/source3/nsswitch/winbindd_cache.c +++ b/source3/nsswitch/winbindd_cache.c @@ -47,6 +47,35 @@ void winbindd_cache_init(void) } } +/* find the sequence number for a domain */ + +static uint32 domain_sequence_number(char *domain_name) +{ + return DOM_SEQUENCE_NONE; + +#if 0 + struct winbindd_domain *domain; + SAM_UNK_CTR ctr; + + domain = find_domain_from_name(domain_name); + if (!domain) return DOM_SEQUENCE_NONE; + + if (!wb_samr_query_dom_info(&domain->sam_dom_handle, 2, &ctr)) { + + /* If this fails, something bad has gone wrong */ + + DEBUG(2,("domain sequence query failed\n")); + return DOM_SEQUENCE_NONE; + } + + DEBUG(4,("got domain sequence number for %s of %u\n", + domain_name, (unsigned)ctr.info.inf2.seq_num)); + + return ctr.info.inf2.seq_num; +#endif + +} + /* get the domain sequence number, possibly re-fetching */ static uint32 cached_sequence_number(char *domain_name) { diff --git a/source3/nsswitch/winbindd_cm.c b/source3/nsswitch/winbindd_cm.c new file mode 100644 index 0000000000..ec1db826dd --- /dev/null +++ b/source3/nsswitch/winbindd_cm.c @@ -0,0 +1,245 @@ +/* + Unix SMB/Netbios implementation. + Version 3.0 + + Winbind daemon connection manager + + Copyright (C) Tim Potter 2001 + + 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. +*/ + +/* + We need to manage connections to domain controllers without having to + mess up the main winbindd code with other issues. The aim of the + connection manager is to: + + - make connections to domain controllers and cache them + - re-establish connections when networks or servers go down + - centralise the policy on connection timeouts, domain controller + selection etc + - manage re-entrancy for when winbindd becomes able to handle + multiple outstanding rpc requests + + We can also throw away the CLI_POLICY_HND stuff as all this information + will be stored within this module. + + Why not have connection management as part of the rpc layer like tng? + Good question. This code may morph into libsmb/rpc_cache.c or something + like that but at the moment it's simply staying as part of winbind. I + think the TNG architecture of forcing every user of the rpc layer to use + the connection caching system is a bad idea. It should be an optional + method of using the routines. + + The TNG design is quite good but I disagree with some aspects of the + implementation. -tpot + + */ + +/* + TODO: + + - I'm pretty annoyed by all the make_nmb_name() stuff. It should be + moved down into another function. + + - There needs to be a utility function in libsmb/namequery.c that does + get_any_dc_name() + + */ + +#include "winbindd.h" + +/* We store lists of connections here */ + +struct winbindd_cm_conn { + struct winbindd_cm_conn *prev, *next; + fstring domain; + fstring controller; + fstring pipe_name; + struct cli_state cli; + POLICY_HND pol; +}; + +/* Global list of connections. Initially a DLIST but can become a hash + table or whatever later. */ + +struct winbindd_cm_conn *cm_conns = NULL; + +/* Get a domain controller name */ + +BOOL cm_get_dc_name(char *domain, fstring srv_name) +{ + struct in_addr *ip_list, dc_ip; + extern pstring global_myname; + int count, i; + + /* Lookup domain controller name */ + + if (!get_dc_list(False, domain, &ip_list, &count)) + return False; + + /* Firstly choose a PDC/BDC who has the same network address as any + of our interfaces. */ + + for (i = 0; i < count; i++) { + if(!is_local_net(ip_list[i])) + goto got_ip; + } + + i = (sys_random() % count); + + got_ip: + dc_ip = ip_list[i]; + SAFE_FREE(ip_list); + + if (!lookup_pdc_name(global_myname, domain, &dc_ip, srv_name)) + return False; + + return True; +} + +/* Open a new smb pipe connection to a DC on a given domain */ + +static BOOL cm_open_connection(char *domain, char *pipe_name, + struct winbindd_cm_conn *new_conn) +{ + struct nmb_name calling, called; + extern pstring global_myname; + fstring dest_host; + struct in_addr dest_ip; + BOOL result = False; + struct ntuser_creds creds; + + ZERO_STRUCT(new_conn->cli); + + fstrcpy(new_conn->domain, domain); + fstrcpy(new_conn->pipe_name, pipe_name); + + /* Look for a domain controller for this domain */ + + if (!cm_get_dc_name(lp_workgroup(), new_conn->controller)) + goto done; + + /* Initialise SMB connection */ + + if (!cli_initialise(&new_conn->cli)) + goto done; + + if (!resolve_srv_name(new_conn->controller, dest_host, &dest_ip)) + goto done; + + make_nmb_name(&called, dns_to_netbios_name(new_conn->controller), + 0x20); + make_nmb_name(&calling, dns_to_netbios_name(global_myname), 0); + + ZERO_STRUCT(creds); + creds.pwd.null_pwd = 1; + + cli_init_creds(&new_conn->cli, &creds); + + if (!cli_establish_connection(&new_conn->cli, new_conn->controller, + &dest_ip, &calling, &called, "IPC$", + "IPC", False, True)) + goto done; + + if (!cli_nt_session_open (&new_conn->cli, pipe_name)) + goto done; + + result = True; + + done: + if (!result) + cli_shutdown(&new_conn->cli); + + return result; +} + +/* Return a LSA policy handle on a domain */ + +CLI_POLICY_HND *cm_get_lsa_handle(char *domain) +{ + struct winbindd_cm_conn *conn; + uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED; + NTSTATUS result; + static CLI_POLICY_HND hnd; + + /* Look for existing connections */ + + for (conn = cm_conns; conn; conn = conn->next) { + if (strequal(conn->domain, domain) && + strequal(conn->pipe_name, PIPE_LSARPC)) + goto ok; + } + + /* Create a new one */ + + if (!(conn = (struct winbindd_cm_conn *) + malloc(sizeof(struct winbindd_cm_conn)))) + return NULL; + + if (!cm_open_connection(domain, PIPE_LSARPC, conn)) { + DEBUG(3, ("Could not connect to a dc for domain %s\n", + domain)); + return NULL; + } + + result = cli_lsa_open_policy(&conn->cli, conn->cli.mem_ctx, False, + des_access, &conn->pol); + + if (!NT_STATUS_IS_OK(result)) + return NULL; + + /* Add to list */ + + DLIST_ADD(cm_conns, conn); + + ok: + hnd.pol = conn->pol; + hnd.cli = &conn->cli; + + return &hnd; +} + +/* Return a SAM policy handle on a domain */ + +CLI_POLICY_HND *cm_get_sam_handle(char *domain) +{ + DEBUG(0, ("get_sam_handle(): not implemented\n")); + return NULL; +} + +/* Return a SAM domain policy handle on a domain */ + +CLI_POLICY_HND *cm_get_sam_dom_handle(char *domain) +{ + DEBUG(0, ("get_sam_dom_handle(): not implemented\n")); + return NULL; +} + +/* Return a SAM policy handle on a domain user */ + +CLI_POLICY_HND *cm_get_sam_user_handle(char *domain, char *user) +{ + DEBUG(0, ("get_sam_user_handle(): not implemented\n")); + return NULL; +} + +/* Return a SAM policy handle on a domain group */ + +CLI_POLICY_HND *cm_get_sam_group_handle(char *domain, char *group) +{ + DEBUG(0, ("get_sam_group_handle(): not implemented\n")); + return NULL; +} diff --git a/source3/nsswitch/winbindd_group.c b/source3/nsswitch/winbindd_group.c index ab693eff63..40ad100fc5 100644 --- a/source3/nsswitch/winbindd_group.c +++ b/source3/nsswitch/winbindd_group.c @@ -23,6 +23,8 @@ #include "winbindd.h" +#if 0 + /* Fill a grent structure from various other information */ static BOOL fill_grent(struct winbindd_gr *gr, char *gr_name, @@ -496,15 +498,18 @@ static BOOL get_sam_group_entries(struct getent_state *ent) do { struct acct_info *sam_grp_entries = NULL; + CLI_POLICY_HND *hnd; num_entries = 0; - status = wb_samr_enum_dom_groups(&ent->domain->sam_dom_handle, - &ent->grp_query_start_ndx, - 0x8000, /* buffer size? */ - (struct acct_info **) - &sam_grp_entries, - &num_entries); + if (!(hnd = cm_get_sam_dom_handle(ent->domain->name))) + break; + + status = cli_samr_enum_dom_groups( + hnd->cli, hnd->cli->mem_ctx, hnd->pol, + &ent->grp_query_start_ndx, + 0x8000, /* buffer size? */ + (struct acct_info **) &sam_grp_entries, &num_entries); /* Copy entries into return buffer */ @@ -983,3 +988,5 @@ enum winbindd_result winbindd_getgroups(struct winbindd_cli_state *state) return result; } + +#endif diff --git a/source3/nsswitch/winbindd_pam.c b/source3/nsswitch/winbindd_pam.c index 262a9d7a33..406b12c9f6 100644 --- a/source3/nsswitch/winbindd_pam.c +++ b/source3/nsswitch/winbindd_pam.c @@ -55,7 +55,7 @@ static void parse_domain_user(char *domuser, fstring domain, fstring user) enum winbindd_result winbindd_pam_auth(struct winbindd_cli_state *state) { NTSTATUS result; - fstring name_domain, name_user; + fstring name_domain, name_user, auth_dc; int passlen; unsigned char trust_passwd[16]; time_t last_change_time; @@ -127,12 +127,18 @@ enum winbindd_result winbindd_pam_auth(struct winbindd_cli_state *state) return WINBINDD_ERROR; } + if (!cm_get_dc_name(lp_workgroup(), auth_dc)) { + DEBUG(3, ("Could not find dc for workgroup %s\n", + lp_workgroup())); + return WINBINDD_ERROR; + } + /* So domain_client_validate() actually opens a new connection for each authentication performed. This can theoretically be optimised to use an already open IPC$ connection. */ result = domain_client_validate(&user_info, &server_info, - server_state.controller, trust_passwd, + auth_dc, trust_passwd, last_change_time); return NT_STATUS_IS_OK(result) ? WINBINDD_OK : WINBINDD_ERROR; @@ -143,7 +149,7 @@ enum winbindd_result winbindd_pam_auth(struct winbindd_cli_state *state) enum winbindd_result winbindd_pam_auth_crap(struct winbindd_cli_state *state) { NTSTATUS result; - fstring name_domain, name_user; + fstring name_domain, name_user, auth_dc; unsigned char trust_passwd[16]; time_t last_change_time; auth_usersupplied_info user_info; @@ -198,12 +204,18 @@ enum winbindd_result winbindd_pam_auth_crap(struct winbindd_cli_state *state) return WINBINDD_ERROR; } + if (!cm_get_dc_name(lp_workgroup(), auth_dc)) { + DEBUG(3, ("Could not find dc for workgroup %s\n", + lp_workgroup())); + return WINBINDD_ERROR; + } + /* So domain_client_validate() actually opens a new connection for each authentication performed. This can theoretically be optimised to use an already open IPC$ connection. */ result = domain_client_validate(&user_info, &server_info, - server_state.controller, trust_passwd, + auth_dc, trust_passwd, last_change_time); return NT_STATUS_IS_OK(result) ? WINBINDD_OK : WINBINDD_ERROR; diff --git a/source3/nsswitch/winbindd_proto.h b/source3/nsswitch/winbindd_proto.h index 8753d7becb..7b4e36576d 100644 --- a/source3/nsswitch/winbindd_proto.h +++ b/source3/nsswitch/winbindd_proto.h @@ -45,6 +45,15 @@ BOOL winbindd_fetch_gid_cache_entry(char *domain_name, gid_t gid, void winbindd_flush_cache(void); void winbindd_cache_dump_status(void); +/* The following definitions come from nsswitch/winbindd_cm.c */ + +BOOL cm_get_dc_name(char *domain, fstring srv_name); +CLI_POLICY_HND *cm_get_lsa_handle(char *domain); +CLI_POLICY_HND *cm_get_sam_handle(char *domain); +CLI_POLICY_HND *cm_get_sam_dom_handle(char *domain); +CLI_POLICY_HND *cm_get_sam_user_handle(char *domain, char *user); +CLI_POLICY_HND *cm_get_sam_group_handle(char *domain, char *group); + /* The following definitions come from nsswitch/winbindd_group.c */ enum winbindd_result winbindd_getgrnam_from_group(struct winbindd_cli_state @@ -73,8 +82,8 @@ BOOL winbindd_idmap_init(void); void winbindd_idmap_dump_status(void); /* The following definitions come from nsswitch/winbindd_misc.c */ -enum winbindd_result winbindd_check_machine_acct( - struct winbindd_cli_state *state); + +enum winbindd_result winbindd_check_machine_acct(struct winbindd_cli_state *state); enum winbindd_result winbindd_list_trusted_domains(struct winbindd_cli_state *state); @@ -106,7 +115,6 @@ enum winbindd_result winbindd_list_users(struct winbindd_cli_state *state); /* The following definitions come from nsswitch/winbindd_util.c */ -void debug_conn_state(void); BOOL domain_handles_open(struct winbindd_domain *domain); void winbindd_kill_all_connections(void); void establish_connections(BOOL force_reestablish) ; @@ -121,8 +129,6 @@ BOOL winbindd_lookup_userinfo(struct winbindd_domain *domain, BOOL winbindd_lookup_usergroups(struct winbindd_domain *domain, uint32 user_rid, uint32 *num_groups, DOM_GID **user_groups); -BOOL winbindd_lookup_groupinfo(struct winbindd_domain *domain, - uint32 group_rid, GROUP_INFO_CTR *info); BOOL winbindd_lookup_groupmem(struct winbindd_domain *domain, uint32 group_rid, uint32 *num_names, uint32 **rid_mem, char ***names, @@ -131,10 +137,9 @@ struct winbindd_domain *find_domain_from_name(char *domain_name); struct winbindd_domain *find_domain_from_sid(DOM_SID *sid); void free_getent_state(struct getent_state *state); BOOL winbindd_param_init(void); -char *winbindd_cmd_to_string(enum winbindd_cmd cmd); -uint32 domain_sequence_number(char *domain_name); NTSTATUS winbindd_query_dispinfo(struct winbindd_domain *domain, - uint32 *start_ndx, uint16 info_level, - uint32 *num_entries, SAM_DISPINFO_CTR *ctr); + uint32 *start_ndx, uint16 info_level, + uint32 *num_entries, SAM_DISPINFO_CTR *ctr); BOOL check_domain_env(char *domain_env, char *domain); +void parse_domain_user(char *domuser, fstring domain, fstring user); #endif /* _PROTO_H_ */ diff --git a/source3/nsswitch/winbindd_user.c b/source3/nsswitch/winbindd_user.c index aa138cfdeb..bb5b1e354e 100644 --- a/source3/nsswitch/winbindd_user.c +++ b/source3/nsswitch/winbindd_user.c @@ -98,7 +98,6 @@ enum winbindd_result winbindd_getpwnam_from_user(struct winbindd_cli_state SAM_USERINFO_CTR *user_info; DOM_SID user_sid; fstring name_domain, name_user, name, gecos_name; - struct winbindd_domain *domain; enum SID_NAME_USE name_type; DEBUG(3, ("[%5d]: getpwnam %s\n", state->pid, @@ -116,18 +115,6 @@ enum winbindd_result winbindd_getpwnam_from_user(struct winbindd_cli_state return WINBINDD_ERROR; } - /* Get info for the domain */ - - if ((domain = find_domain_from_name(name_domain)) == NULL) { - DEBUG(0, ("could not find domain entry for domain %s\n", - name_domain)); - return WINBINDD_ERROR; - } - - if (!domain_handles_open(domain)) { - return WINBINDD_ERROR; - } - /* Check for cached user entry */ if (winbindd_fetch_user_cache_entry(name_domain, name_user, @@ -158,6 +145,8 @@ enum winbindd_result winbindd_getpwnam_from_user(struct winbindd_cli_state /* The following costs 3 packets */ +#if 0 + if (!winbindd_lookup_userinfo(domain, user_rid, &user_info)) { DEBUG(1, ("pwnam_from_user(): error getting user info for " "user '%s'\n", name_user)); @@ -167,10 +156,15 @@ enum winbindd_result winbindd_getpwnam_from_user(struct winbindd_cli_state group_rid = user_info->info.id21->group_rid; unistr2_to_ascii(gecos_name, &user_info->info.id21->uni_full_name, sizeof(gecos_name) - 1); + +#endif + + group_rid = DOMAIN_GROUP_RID_GUESTS; + fstrcpy(gecos_name, "foo"); /* Now take all this information and fill in a passwd structure */ - if (!winbindd_fill_pwent(domain->name, state->request.data.username, + if (!winbindd_fill_pwent(name_domain, state->request.data.username, user_rid, group_rid, gecos_name, &state->response.data.pw)) { return WINBINDD_ERROR; @@ -214,10 +208,6 @@ enum winbindd_result winbindd_getpwnam_from_uid(struct winbindd_cli_state return WINBINDD_ERROR; } - if (!domain_handles_open(domain)) { - return WINBINDD_ERROR; - } - /* Check for cached uid entry */ if (winbindd_fetch_uid_cache_entry(domain->name, @@ -246,6 +236,8 @@ enum winbindd_result winbindd_getpwnam_from_uid(struct winbindd_cli_state /* Get some user info */ +#if 0 + if (!winbindd_lookup_userinfo(domain, user_rid, &user_info)) { DEBUG(1, ("pwnam_from_uid(): error getting user info for " "user '%s'\n", user_name)); @@ -255,6 +247,10 @@ enum winbindd_result winbindd_getpwnam_from_uid(struct winbindd_cli_state group_rid = user_info->info.id21->group_rid; unistr2_to_ascii(gecos_name, &user_info->info.id21->uni_full_name, sizeof(gecos_name) - 1); +#endif + + group_rid = DOMAIN_GROUP_RID_GUESTS; + fstrcpy(gecos_name, "foo"); /* Resolve gid number */ @@ -276,6 +272,8 @@ enum winbindd_result winbindd_getpwnam_from_uid(struct winbindd_cli_state return WINBINDD_OK; } +#if 0 + /* * set/get/endpwent functions */ @@ -694,3 +692,5 @@ enum winbindd_result winbindd_list_users(struct winbindd_cli_state *state) return WINBINDD_OK; } + +#endif diff --git a/source3/nsswitch/winbindd_util.c b/source3/nsswitch/winbindd_util.c index 86517c4e2d..c5b3c7585b 100644 --- a/source3/nsswitch/winbindd_util.c +++ b/source3/nsswitch/winbindd_util.c @@ -24,26 +24,9 @@ #include "winbindd.h" #include "sids.h" -static void winbindd_kill_connections(struct winbindd_domain *domain); - -/* Debug connection state */ - -void debug_conn_state(void) -{ - struct winbindd_domain *domain; - - DEBUG(3, ("server: dc=%s, pwdb_init=%d, lsa_hnd=%d\n", - server_state.controller, - server_state.pwdb_initialised, - server_state.lsa_handle_open)); +#if 0 - for (domain = domain_list; domain; domain = domain->next) { - DEBUG(3, ("%s: dc=%s, got_sid=%d, sam_hnd=%d sam_dom_hnd=%d\n", - domain->name, domain->controller, - domain->got_domain_info, domain->sam_handle_open, - domain->sam_dom_handle_open)); - } -} +static void winbindd_kill_connections(struct winbindd_domain *domain); /* Add a trusted domain to our list of domains */ @@ -187,7 +170,6 @@ BOOL domain_handles_open(struct winbindd_domain *domain) } DEBUG(3, ("checking domain handles for domain %s\n", domain->name)); - debug_conn_state(); domain->last_check = t; @@ -246,8 +228,6 @@ static void winbindd_kill_connections(struct winbindd_domain *domain) DEBUG(0, ("killing connections to domain %s with controller %s\n", domain->name, domain->controller)); - debug_conn_state(); - /* Close LSA connections if we are killing connections to the dc that has them open. */ @@ -303,37 +283,6 @@ void winbindd_kill_all_connections(void) } } -static BOOL get_any_dc_name(char *domain, fstring srv_name) -{ - struct in_addr *ip_list, dc_ip; - extern pstring global_myname; - int count, i; - - /* Lookup domain controller name */ - - if (!get_dc_list(False, domain, &ip_list, &count)) - return False; - - /* Firstly choose a PDC/BDC who has the same network address as any - of our interfaces. */ - - for (i = 0; i < count; i++) { - if(!is_local_net(ip_list[i])) - goto got_ip; - } - - i = (sys_random() % count); - - got_ip: - dc_ip = ip_list[i]; - SAFE_FREE(ip_list); - - if (!lookup_pdc_name(global_myname, domain, &dc_ip, srv_name)) - return False; - - return True; -} - /* Attempt to connect to all domain controllers we know about */ void establish_connections(BOOL force_reestablish) @@ -350,7 +299,6 @@ void establish_connections(BOOL force_reestablish) lastt = t; DEBUG(3, ("establishing connections\n")); - debug_conn_state(); /* Maybe the connection died - if so then close up and restart */ @@ -401,96 +349,88 @@ void establish_connections(BOOL force_reestablish) get_trusted_domains(); } - - debug_conn_state(); } +#endif + /* Connect to a domain controller using get_any_dc_name() to discover the domain name and sid */ BOOL lookup_domain_sid(char *domain_name, struct winbindd_domain *domain) { - fstring level5_dom; - BOOL res; - uint32 enum_ctx = 0; - uint32 num_doms = 0; - char **domains = NULL; - DOM_SID *sids = NULL; - - if (domain == NULL) { - return False; - } - - DEBUG(1, ("looking up sid for domain %s\n", domain_name)); - - /* Get controller name for domain */ - - if (!get_any_dc_name(domain_name, domain->controller)) { - DEBUG(0, ("Could not resolve domain controller for domain %s\n", - domain_name)); - return False; - } - - /* Do a level 5 query info policy if we are looking up our own SID */ - - if (strequal(domain_name, lp_workgroup())) { - return wb_lsa_query_info_pol(&server_state.lsa_handle, 0x05, - level5_dom, &domain->sid); - } - - /* Use lsaenumdomains to get sid for this domain */ - - res = wb_lsa_enum_trust_dom(&server_state.lsa_handle, &enum_ctx, - &num_doms, &domains, &sids); - - /* Look for domain name */ - - if (res && domains && sids) { - int found = False; - int i; - - for(i = 0; i < num_doms; i++) { - if (strequal(domain_name, domains[i])) { - sid_copy(&domain->sid, &sids[i]); - found = True; + fstring level5_dom; + uint32 enum_ctx = 0; + uint32 num_doms = 0; + char **domains = NULL; + DOM_SID *sids = NULL; + CLI_POLICY_HND *hnd; + NTSTATUS result; + + DEBUG(1, ("looking up sid for domain %s\n", domain_name)); + + if (!(hnd = cm_get_lsa_handle(domain_name))) + return False; + + /* Do a level 5 query info policy if we are looking up the SID for + our own domain. */ + + if (strequal(domain_name, lp_workgroup())) { + + result = cli_lsa_query_info_policy(hnd->cli, hnd->cli->mem_ctx, + &hnd->pol, 0x05, level5_dom, + &domain->sid); + + return NT_STATUS_IS_OK(result); + } + + /* Use lsaenumdomains to get sid for this domain */ + + result = cli_lsa_enum_trust_dom(hnd->cli, hnd->cli->mem_ctx, &hnd->pol, + &enum_ctx, &num_doms, &domains, &sids); + + /* Look for domain name */ + + if (NT_STATUS_IS_OK(result) && domains && sids) { + int found = False; + int i; + + for(i = 0; i < num_doms; i++) { + if (strequal(domain_name, domains[i])) { + sid_copy(&domain->sid, &sids[i]); + found = True; break; - } - } - - res = found; - } - - return res; + } + } + + return found; + } + + return NT_STATUS_IS_OK(result); } /* Lookup domain controller and sid for a domain */ BOOL get_domain_info(struct winbindd_domain *domain) { - fstring sid_str; - - DEBUG(1, ("Getting domain info for domain %s\n", domain->name)); - - /* Lookup domain sid */ - - if (!lookup_domain_sid(domain->name, domain)) { - DEBUG(0, ("could not find sid for domain %s\n", domain->name)); - - /* Could be a DC failure - shut down connections to this domain */ - - winbindd_kill_connections(domain); - - return False; - } - - /* Lookup OK */ - - domain->got_domain_info = 1; + fstring sid_str; + + DEBUG(1, ("Getting domain info for domain %s\n", domain->name)); - sid_to_string(sid_str, &domain->sid); - DEBUG(1, ("found sid %s for domain %s\n", sid_str, domain->name)); + /* Lookup domain sid */ + + if (!lookup_domain_sid(domain->name, domain)) { + DEBUG(0, ("could not find sid for domain %s\n", domain->name)); + return False; + } + + /* Lookup OK */ - return True; + domain->got_domain_info = 1; + + sid_to_string(sid_str, &domain->sid); + DEBUG(1, ("found sid %s for domain %s\n", sid_str, domain->name)); + + return True; } /* Lookup a sid in a domain from a name */ @@ -498,40 +438,44 @@ BOOL get_domain_info(struct winbindd_domain *domain) BOOL winbindd_lookup_sid_by_name(char *name, DOM_SID *sid, enum SID_NAME_USE *type) { - int num_sids = 0, num_names = 1; - DOM_SID *sids = NULL; - uint32 *types = NULL; - BOOL res; - - /* Don't bother with machine accounts */ - - if (name[strlen(name) - 1] == '$') { - return False; - } - - /* Lookup name */ - - res = wb_lsa_lookup_names(&server_state.lsa_handle, num_names, - (char **)&name, &sids, &types, &num_sids); - - /* Return rid and type if lookup successful */ - - if (res) { - - /* Return sid */ - - if ((sid != NULL) && (sids != NULL)) { - sid_copy(sid, &sids[0]); - } - - /* Return name type */ - - if ((type != NULL) && (types != NULL)) { - *type = types[0]; + int num_sids = 0, num_names = 1; + DOM_SID *sids = NULL; + uint32 *types = NULL; + CLI_POLICY_HND *hnd; + NTSTATUS result; + + /* Don't bother with machine accounts */ + + if (name[strlen(name) - 1] == '$') + return False; + + /* Lookup name */ + + if (!(hnd = cm_get_lsa_handle(lp_workgroup()))) + return False; + + result = cli_lsa_lookup_names(hnd->cli, hnd->cli->mem_ctx, &hnd->pol, + num_names, (char **)&name, &sids, + &types, &num_sids); + + /* Return rid and type if lookup successful */ + + if (NT_STATUS_IS_OK(result)) { + + /* Return sid */ + + if ((sid != NULL) && (sids != NULL)) + sid_copy(sid, &sids[0]); + + /* Return name type */ + + if ((type != NULL) && (types != NULL)) + *type = types[0]; + + return True; } - } - - return res; + + return False; } /* Lookup a name in a domain from a sid */ @@ -539,36 +483,43 @@ BOOL winbindd_lookup_sid_by_name(char *name, DOM_SID *sid, BOOL winbindd_lookup_name_by_sid(DOM_SID *sid, fstring name, enum SID_NAME_USE *type) { - int num_sids = 1, num_names = 0; - uint32 *types = NULL; - char **names; - BOOL res; - - /* Lookup name */ - - res = wb_lsa_lookup_sids(&server_state.lsa_handle, num_sids, sid, - &names, &types, &num_names); - - /* Return name and type if successful */ - - if (res) { - - /* Return name */ - - if ((names != NULL) && (name != NULL)) { - fstrcpy(name, names[0]); - } - - /* Return name type */ + int num_sids = 1, num_names = 0; + uint32 *types = NULL; + char **names; + CLI_POLICY_HND *hnd; + NTSTATUS result; + + /* Lookup name */ + + if (!(hnd = cm_get_lsa_handle(lp_workgroup()))) + return False; + + result = cli_lsa_lookup_sids(hnd->cli, hnd->cli->mem_ctx, &hnd->pol, + num_sids, sid, &names, &types, + &num_names); - if ((type != NULL) && (types != NULL)) { - *type = types[0]; + /* Return name and type if successful */ + + if (NT_STATUS_IS_OK(result)) { + + /* Return name */ + + if ((names != NULL) && (name != NULL)) + fstrcpy(name, names[0]); + + /* Return name type */ + + if ((type != NULL) && (types != NULL)) + *type = types[0]; + + return True; } - } - - return res; + + return False; } +#if 0 + /* Lookup user information from a rid */ BOOL winbindd_lookup_userinfo(struct winbindd_domain *domain, @@ -620,6 +571,8 @@ BOOL winbindd_lookup_groupmem(struct winbindd_domain *domain, num_names, rid_mem, names, name_types); } +#endif + /* Globals for domain list stuff */ struct winbindd_domain *domain_list = NULL; @@ -751,31 +704,7 @@ BOOL winbindd_param_init(void) return True; } -/* find the sequence number for a domain */ - -uint32 domain_sequence_number(char *domain_name) -{ - struct winbindd_domain *domain; - SAM_UNK_CTR ctr; - - domain = find_domain_from_name(domain_name); - if (!domain) return DOM_SEQUENCE_NONE; - - if (!wb_samr_query_dom_info(&domain->sam_dom_handle, 2, &ctr)) { - - /* If this fails, something bad has gone wrong */ - - winbindd_kill_connections(domain); - - DEBUG(2,("domain sequence query failed\n")); - return DOM_SEQUENCE_NONE; - } - - DEBUG(4,("got domain sequence number for %s of %u\n", - domain_name, (unsigned)ctr.info.inf2.seq_num)); - - return ctr.info.inf2.seq_num; -} +#if 0 /* Query display info for a domain. This returns enough information plus a bit extra to give an overview of domain users for the User Manager @@ -805,6 +734,7 @@ BOOL check_domain_env(char *domain_env, char *domain) return False; } +#endif /* Parse a string of the form DOMAIN/user into a domain and a user */ -- cgit