1
0
mirror of https://github.com/samba-team/samba.git synced 2024-12-25 23:21:54 +03:00

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 commit is contained in:
Tim Potter 0001-01-01 00:00:00 +00:00
parent 880201b52b
commit c369cf5af7
9 changed files with 587 additions and 379 deletions

View File

@ -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;
}
} 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;
/* 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;
}
}
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;
/* Create the socket file */
old_umask = umask(0);
sock = socket(AF_UNIX, SOCK_STREAM, 0);
if (sock == -1) {
perror("socket");
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;
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;
}
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();

View File

@ -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"

View File

@ -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)
{

View File

@ -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;
}

View File

@ -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

View File

@ -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;

View File

@ -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_ */

View File

@ -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

View File

@ -24,27 +24,10 @@
#include "winbindd.h"
#include "sids.h"
#if 0
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));
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));
}
}
/* Add a trusted domain to our list of domains */
static struct winbindd_domain *add_trusted_domain(char *domain_name)
@ -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;
fstring sid_str;
DEBUG(1, ("Getting domain info for domain %s\n", domain->name));
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));
return False;
}
/* Lookup OK */
/* 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;
sid_to_string(sid_str, &domain->sid);
DEBUG(1, ("found sid %s for domain %s\n", sid_str, domain->name));
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;
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];
/* Don't bother with machine accounts */
if (name[strlen(name) - 1] == '$') {
return True;
}
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];
}
}
return res;
}
/* 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;
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);
/* Lookup name */
/* 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 */
res = wb_lsa_lookup_sids(&server_state.lsa_handle, num_sids, sid,
&names, &types, &num_names);
if ((type != NULL) && (types != NULL))
*type = types[0];
/* Return name and type if successful */
if (res) {
/* Return name */
if ((names != NULL) && (name != NULL)) {
fstrcpy(name, names[0]);
return True;
}
/* Return name type */
if ((type != NULL) && (types != NULL)) {
*type = types[0];
}
}
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 */