Winbind daemon for ntdom nss module
- Copyright (C) by Tim Potter 2000, 2001
+ Copyright (C) by Tim Potter 2000-2002
Copyright (C) Andrew Tridgell 2002
This program is free software; you can redistribute it and/or modify
#include "winbindd.h"
-/* List of all connected clients */
-
-struct winbindd_cli_state *client_list;
-static int num_clients;
BOOL opt_nocache = False;
BOOL opt_dual_daemon = False;
return(ret);
}
+/*******************************************************************
+ Print out all talloc memory info.
+********************************************************************/
+
+void return_all_talloc_info(int msg_type, pid_t src_pid, void *buf, size_t len)
+{
+ TALLOC_CTX *ctx = talloc_init("info context");
+ char *info = NULL;
+
+ if (!ctx)
+ return;
+
+ info = talloc_describe_all(ctx);
+ if (info)
+ DEBUG(10,(info));
+ message_send_pid(src_pid, MSG_TALLOC_USAGE, info, info ? strlen(info) + 1: 0, True);
+ talloc_destroy(ctx);
+}
+
#if DUMP_CORE
/**************************************************************************** **
/* Print client state information */
- DEBUG(0, ("\t%d clients currently active\n", num_clients));
+ DEBUG(0, ("\t%d clients currently active\n", winbindd_num_clients()));
- if (DEBUGLEVEL >= 2 && num_clients) {
+ if (DEBUGLEVEL >= 2 && winbindd_num_clients()) {
DEBUG(2, ("\tclient list:\n"));
- for(tmp = client_list; tmp; tmp = tmp->next) {
+ for(tmp = winbindd_client_list(); tmp; tmp = tmp->next) {
DEBUG(2, ("\t\tpid %d, sock %d, rbl %d, wbl %d\n",
tmp->pid, tmp->sock, tmp->read_buf_len,
tmp->write_buf_len));
sys_select_signal();
}
-/* Create winbindd socket */
-
-static int create_sock(void)
-{
- return create_pipe_sock( WINBINDD_SOCKET_DIR,
- WINBINDD_SOCKET_NAME, 0755);
-}
-
struct dispatch_table {
enum winbindd_cmd cmd;
enum winbindd_result (*fn)(struct winbindd_cli_state *state);
- char *winbindd_cmd_name;
+ const char *winbindd_cmd_name;
};
static struct dispatch_table dispatch_table[] = {
{ WINBINDD_SETGRENT, winbindd_setgrent, "SETGRENT" },
{ WINBINDD_ENDGRENT, winbindd_endgrent, "ENDGRENT" },
{ WINBINDD_GETGRENT, winbindd_getgrent, "GETGRENT" },
+ { WINBINDD_GETGRLST, winbindd_getgrent, "GETGRLST" },
/* PAM auth functions */
{ WINBINDD_INFO, winbindd_info, "INFO" },
{ WINBINDD_INTERFACE_VERSION, winbindd_interface_version, "INTERFACE_VERSION" },
{ WINBINDD_DOMAIN_NAME, winbindd_domain_name, "DOMAIN_NAME" },
+ { WINBINDD_NETBIOS_NAME, winbindd_netbios_name, "NETBIOS_NAME" },
/* WINS functions */
/* Process a new connection by adding it to the client connection list */
-static void new_connection(int accept_sock)
+static void new_connection(int listen_sock)
{
struct sockaddr_un sunaddr;
struct winbindd_cli_state *state;
len = sizeof(sunaddr);
do {
- sock = accept(accept_sock, (struct sockaddr *)&sunaddr, &len);
+ sock = accept(listen_sock, (struct sockaddr *)&sunaddr, &len);
} while (sock == -1 && errno == EINTR);
if (sock == -1)
/* Add to connection list */
- DLIST_ADD(client_list, state);
- num_clients++;
+ winbindd_add_client(state);
}
/* Remove a client connection from client connection list */
/* Remove from list and free */
- DLIST_REMOVE(client_list, state);
+ winbindd_remove_client(state);
SAFE_FREE(state);
- num_clients--;
}
}
{
/* Process request */
+ /* Ensure null termination of entire request */
+ state->request.null_term = '\0';
+
state->pid = state->request.pid;
process_request(state);
/* Read data */
- do {
-
- n = read(state->sock, state->read_buf_len +
- (char *)&state->request,
- sizeof(state->request) - state->read_buf_len);
-
- } while (n == -1 && errno == EINTR);
+ n = sys_read(state->sock, state->read_buf_len +
+ (char *)&state->request,
+ sizeof(state->request) - state->read_buf_len);
DEBUG(10,("client_read: read %d bytes. Need %d more for a full request.\n", n, sizeof(state->request) - n - state->read_buf_len ));
state->write_buf_len;
}
- do {
- num_written = write(state->sock, data, state->write_buf_len);
- } while (num_written == -1 && errno == EINTR);
+ num_written = sys_write(state->sock, data, state->write_buf_len);
DEBUG(10,("client_write: wrote %d bytes.\n", num_written ));
simultaneous connections while remaining impervious to many denial of
service attacks. */
-static void process_loop(int accept_sock)
+static void process_loop(void)
{
/* We'll be doing this a lot */
while (1) {
struct winbindd_cli_state *state;
fd_set r_fds, w_fds;
- int maxfd = accept_sock, selret;
+ int maxfd, listen_sock, selret;
struct timeval timeout;
/* Handle messages */
message_dispatch();
+ /* rescan the trusted domains list. This must be done
+ regularly to cope with transitive trusts */
+ rescan_trusted_domains();
+
/* Free up temporary memory */
lp_talloc_free();
/* Initialise fd lists for select() */
+ listen_sock = open_winbindd_socket();
+
+ if (listen_sock == -1) {
+ perror("open_winbind_socket");
+ exit(1);
+ }
+
+ maxfd = listen_sock;
+
FD_ZERO(&r_fds);
FD_ZERO(&w_fds);
- FD_SET(accept_sock, &r_fds);
+ FD_SET(listen_sock, &r_fds);
timeout.tv_sec = WINBINDD_ESTABLISH_LOOP;
timeout.tv_usec = 0;
/* Set up client readers and writers */
- state = client_list;
+ state = winbindd_client_list();
while (state) {
dual_select(&w_fds);
}
- if (FD_ISSET(accept_sock, &r_fds))
- new_connection(accept_sock);
+ if (FD_ISSET(listen_sock, &r_fds))
+ new_connection(listen_sock);
/* Process activity on client connections */
- for (state = client_list; state; state = state->next) {
+ for (state = winbindd_client_list(); state;
+ state = state->next) {
/* Data available for reading */
if (state->read_buf_len >= sizeof(uint32)
&& *(uint32 *) &state->request != sizeof(state->request)) {
- DEBUG(0,("process_loop: Invalid request size (%d) send, should be (%d)\n",
- *(uint32 *) &state->request, sizeof(state->request)));
+ DEBUG(0,("process_loop: Invalid request size from pid %d: %d bytes sent, should be %d\n",
+ state->request.pid, *(uint32 *) &state->request, sizeof(state->request)));
remove_client(state);
break;
if (do_sighup) {
- /* Flush winbindd cache */
+ DEBUG(3, ("got SIGHUP\n"));
+
+ /* Flush various caches */
flush_caches();
reload_services_file(True);
/*
these are split out from the main winbindd for use by the background daemon
*/
-int winbind_setup_common(void)
+BOOL winbind_setup_common(void)
{
- load_interfaces();
+ load_interfaces();
- secrets_init();
+ if (!secrets_init()) {
- /* Get list of domains we look up requests for. This includes the
- domain which we are a member of as well as any trusted
- domains. */
+ DEBUG(0,("Could not initialize domain trust account secrets. Giving up\n"));
+ return False;
+ }
- init_domain_list();
+ namecache_enable(); /* Enable netbios namecache */
- ZERO_STRUCT(server_state);
+ /* Check winbindd parameters are valid */
- /* Winbind daemon initialisation */
+ ZERO_STRUCT(server_state);
if (!winbindd_param_init())
- return 1;
+ return False;
+
+ /* Winbind daemon initialisation */
if (!winbindd_idmap_init())
- return 1;
+ return False;
/* Unblock all signals we are interested in as they may have been
blocked by the parent process. */
CatchSignal(SIGUSR2, sigusr2_handler); /* Debugging sigs */
CatchSignal(SIGHUP, sighup_handler);
- return 0;
+ return True;
}
static void usage(void)
{
printf("Usage: winbindd [options]\n");
+ printf("\t-F daemon in foreground mode\n");
+ printf("\t-S log to stdout\n");
printf("\t-i interactive mode\n");
printf("\t-B dual daemon mode\n");
printf("\t-n disable cacheing\n");
int main(int argc, char **argv)
{
extern BOOL AllowDebugChange;
- extern pstring global_myname;
- extern fstring global_myworkgroup;
- extern BOOL append_log;
pstring logfile;
- int accept_sock;
BOOL interactive = False;
+ BOOL Fork = True;
+ BOOL log_stdout = False;
int opt;
/* glibc (?) likes to print "User defined signal 1" and exit if a
fault_setup((void (*)(void *))fault_quit );
- /* Append to log file by default as we are a single process daemon
- program. */
-
- append_log = True;
-
snprintf(logfile, sizeof(logfile), "%s/log.winbindd", dyn_LOGFILEBASE);
lp_set_logfile(logfile);
/* Initialise samba/rpc client stuff */
- while ((opt = getopt(argc, argv, "id:s:nhB")) != EOF) {
+ while ((opt = getopt(argc, argv, "FSid:s:nhB")) != EOF) {
switch (opt) {
+ case 'F':
+ Fork = False;
+ break;
+ case 'S':
+ log_stdout = True;
+ break;
/* Don't become a daemon */
case 'i':
interactive = True;
+ log_stdout = True;
+ Fork = False;
break;
/* dual daemon system */
}
}
+ if (log_stdout && Fork) {
+ printf("Can't log to stdout (-S) unless daemon is in foreground +(-F) or interactive (-i)\n");
+ usage();
+ exit(1);
+ }
+
snprintf(logfile, sizeof(logfile), "%s/log.winbindd", dyn_LOGFILEBASE);
lp_set_logfile(logfile);
- setup_logging("winbindd", interactive);
+ setup_logging("winbindd", log_stdout);
reopen_logs();
DEBUG(1, ("winbindd version %s started.\n", VERSION ) );
exit(1);
}
- pidfile_create("winbindd");
-
/* Setup names. */
- if (!*global_myname) {
- char *p;
+ if (!init_names())
+ exit(1);
- fstrcpy(global_myname, myhostname());
- p = strchr(global_myname, '.');
- if (p)
- *p = 0;
+ if (!interactive) {
+ become_daemon(Fork);
+ pidfile_create("winbindd");
}
- fstrcpy(global_myworkgroup, lp_workgroup());
-
- if (!interactive)
- become_daemon();
#if HAVE_SETPGID
/*
setpgid( (pid_t)0, (pid_t)0);
#endif
- if (opt_dual_daemon) {
- do_dual_daemon();
+ if (!winbind_setup_common()) {
+ return 1;
}
- if (winbind_setup_common() != 0) {
- return 1;
+ if (opt_dual_daemon) {
+ do_dual_daemon();
}
/* Initialise messaging system */
}
register_msg_pool_usage();
-
- /* Create UNIX domain socket */
-
- if ((accept_sock = create_sock()) == -1) {
- DEBUG(0, ("failed to create socket\n"));
- return 1;
- }
+ message_register(MSG_REQ_TALLOC_USAGE, return_all_talloc_info);
/* Loop waiting for requests */
- process_loop(accept_sock);
+ process_loop();
uni_group_cache_shutdown();
return 0;