updated the 3.0 branch from the head branch - ready for alpha18
[nivanova/samba-autobuild/.git] / source3 / nsswitch / winbindd.c
index ee373c7101f2cd0f94e0a968d245a01804b7af9c..358d9add3a388c10f3de544bcbfe8f3a8e946c2d 100644 (file)
@@ -1,10 +1,10 @@
 /* 
-   Unix SMB/Netbios implementation.
-   Version 3.0
+   Unix SMB/CIFS implementation.
 
    Winbind daemon for ntdom nss module
 
    Copyright (C) by Tim Potter 2000, 2001
+   Copyright (C) Andrew Tridgell 2002
    
    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
@@ -27,7 +27,8 @@
 
 struct winbindd_cli_state *client_list;
 static int num_clients;
-BOOL opt_nocache;
+BOOL opt_nocache = False;
+BOOL opt_dual_daemon = False;
 
 /* Reload configuration */
 
@@ -169,6 +170,7 @@ static BOOL do_sigterm;
 static void termination_handler(int signum)
 {
        do_sigterm = True;
+       sys_select_signal();
 }
 
 static BOOL do_sigusr2;
@@ -176,6 +178,7 @@ static BOOL do_sigusr2;
 static void sigusr2_handler(int signum)
 {
        do_sigusr2 = True;
+       sys_select_signal();
 }
 
 static BOOL do_sighup;
@@ -183,6 +186,7 @@ static BOOL do_sighup;
 static void sighup_handler(int signum)
 {
        do_sighup = True;
+       sys_select_signal();
 }
 
 /* Create winbindd socket */
@@ -219,6 +223,7 @@ 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 */
 
@@ -231,6 +236,7 @@ static struct dispatch_table dispatch_table[] = {
        { WINBINDD_LIST_USERS, winbindd_list_users, "LIST_USERS" },
        { WINBINDD_LIST_GROUPS, winbindd_list_groups, "LIST_GROUPS" },
        { WINBINDD_LIST_TRUSTDOM, winbindd_list_trusted_domains, "LIST_TRUSTDOM" },
+       { WINBINDD_SHOW_SEQUENCE, winbindd_show_sequence, "SHOW_SEQUENCE" },
 
        /* SID related functions */
 
@@ -250,6 +256,12 @@ static struct dispatch_table dispatch_table[] = {
        { WINBINDD_PING, winbindd_ping, "PING" },
        { WINBINDD_INFO, winbindd_info, "INFO" },
        { WINBINDD_INTERFACE_VERSION, winbindd_interface_version, "INTERFACE_VERSION" },
+       { WINBINDD_DOMAIN_NAME, winbindd_domain_name, "DOMAIN_NAME" },
+
+       /* WINS functions */
+
+       { WINBINDD_WINS_BYNAME, winbindd_wins_byname, "WINS_BYNAME" },
+       { WINBINDD_WINS_BYIP, winbindd_wins_byip, "WINS_BYIP" },
 
        /* End of list */
 
@@ -356,9 +368,10 @@ static void remove_client(struct winbindd_cli_state *state)
        }
 }
 
+
 /* Process a complete received packet from a client */
 
-static void process_packet(struct winbindd_cli_state *state)
+void winbind_process_packet(struct winbindd_cli_state *state)
 {
        /* Process request */
        
@@ -370,11 +383,16 @@ static void process_packet(struct winbindd_cli_state *state)
        
        state->read_buf_len = 0;
        state->write_buf_len = sizeof(struct winbindd_response);
+
+       /* we might need to send it to the dual daemon */
+       if (opt_dual_daemon) {
+               dual_send_request(state);
+       }
 }
 
 /* Read some data from a client connection */
 
-static void client_read(struct winbindd_cli_state *state)
+void winbind_client_read(struct winbindd_cli_state *state)
 {
        int n;
     
@@ -502,9 +520,14 @@ static void process_loop(int accept_sock)
                int maxfd = accept_sock, selret;
                struct timeval timeout;
 
+               /* Handle messages */
+
+               message_dispatch();
+
                /* Free up temporary memory */
 
                lp_talloc_free();
+               main_loop_talloc_free();
 
                /* Initialise fd lists for select() */
 
@@ -515,6 +538,10 @@ static void process_loop(int accept_sock)
                timeout.tv_sec = WINBINDD_ESTABLISH_LOOP;
                timeout.tv_usec = 0;
 
+               if (opt_dual_daemon) {
+                       maxfd = dual_select_setup(&w_fds, maxfd);
+               }
+
                /* Set up client readers and writers */
 
                state = client_list;
@@ -552,7 +579,7 @@ static void process_loop(int accept_sock)
 
                /* Call select */
         
-               selret = select(maxfd + 1, &r_fds, &w_fds, NULL, &timeout);
+               selret = sys_select(maxfd + 1, &r_fds, &w_fds, NULL, &timeout);
 
                if (selret == 0)
                        continue;
@@ -569,6 +596,10 @@ static void process_loop(int accept_sock)
 
                if (selret > 0) {
 
+                       if (opt_dual_daemon) {
+                               dual_select(&w_fds);
+                       }
+
                        if (FD_ISSET(accept_sock, &r_fds))
                                new_connection(accept_sock);
             
@@ -582,7 +613,7 @@ static void process_loop(int accept_sock)
                     
                                        /* Read data */
                     
-                                       client_read(state);
+                                       winbind_client_read(state);
 
                                        /* 
                                         * If we have the start of a
@@ -606,7 +637,7 @@ static void process_loop(int accept_sock)
                     
                                        if (state->read_buf_len == 
                                            sizeof(state->request)) {
-                                               process_packet(state);
+                                               winbind_process_packet(state);
                                        }
                                }
                 
@@ -617,6 +648,10 @@ static void process_loop(int accept_sock)
                        }
                }
 
+#if 0
+               winbindd_check_cache_size(time(NULL));
+#endif
+
                /* Check signal handling things */
 
                if (do_sigterm)
@@ -638,23 +673,93 @@ static void process_loop(int accept_sock)
        }
 }
 
+
+/*
+  these are split out from the main winbindd for use by the background daemon
+ */
+int winbind_setup_common(void)
+{
+       load_interfaces();
+
+       if (!secrets_init()) {
+
+               DEBUG(0,("Could not initialize domain trust account secrets. Giving up\n"));
+               return 1;
+
+       }
+
+       /* 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. */ 
+
+       init_domain_list();
+
+       ZERO_STRUCT(server_state);
+
+       /* Winbind daemon initialisation */
+
+       if (!winbindd_param_init())
+               return 1;
+
+       if (!winbindd_idmap_init())
+               return 1;
+
+       /* Unblock all signals we are interested in as they may have been
+          blocked by the parent process. */
+
+       BlockSignals(False, SIGINT);
+       BlockSignals(False, SIGQUIT);
+       BlockSignals(False, SIGTERM);
+       BlockSignals(False, SIGUSR1);
+       BlockSignals(False, SIGUSR2);
+       BlockSignals(False, SIGHUP);
+
+       /* Setup signal handlers */
+       
+       CatchSignal(SIGINT, termination_handler);      /* Exit on these sigs */
+       CatchSignal(SIGQUIT, termination_handler);
+       CatchSignal(SIGTERM, termination_handler);
+
+       CatchSignal(SIGPIPE, SIG_IGN);                 /* Ignore sigpipe */
+
+       CatchSignal(SIGUSR2, sigusr2_handler);         /* Debugging sigs */
+       CatchSignal(SIGHUP, sighup_handler);
+
+       return 0;
+}
+
+
 /* Main function */
 
 struct winbindd_state server_state;   /* Server state information */
 
-int main(int argc, char **argv)
+
+static void usage(void)
+{
+       printf("Usage: winbindd [options]\n");
+       printf("\t-i                interactive mode\n");
+       printf("\t-B                dual daemon mode\n");
+       printf("\t-n                disable cacheing\n");
+       printf("\t-d level          set debug level\n");
+       printf("\t-s configfile     choose smb.conf location\n");
+       printf("\t-h                show this help message\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;
-       int opt, new_debuglevel = -1;
+       int opt;
 
        /* glibc (?) likes to print "User defined signal 1" and exit if a
-          SIGUSR2 is received before a handler is installed */
+          SIGUSR[12] is received before a handler is installed */
 
+       CatchSignal(SIGUSR1, SIG_IGN);
        CatchSignal(SIGUSR2, SIG_IGN);
 
        fault_setup((void (*)(void *))fault_quit );
@@ -678,7 +783,7 @@ int main(int argc, char **argv)
 
        /* Initialise samba/rpc client stuff */
 
-       while ((opt = getopt(argc, argv, "id:s:n")) != EOF) {
+       while ((opt = getopt(argc, argv, "id:s:nhB")) != EOF) {
                switch (opt) {
 
                        /* Don't become a daemon */
@@ -686,6 +791,11 @@ int main(int argc, char **argv)
                        interactive = True;
                        break;
 
+                       /* dual daemon system */
+               case 'B':
+                       opt_dual_daemon = True;
+                       break;
+
                        /* disable cacheing */
                case 'n':
                        opt_nocache = True;
@@ -693,7 +803,8 @@ int main(int argc, char **argv)
 
                        /* Run with specified debug level */
                case 'd':
-                       new_debuglevel = atoi(optarg);
+                       DEBUGLEVEL = atoi(optarg);
+                       AllowDebugChange = False;
                        break;
 
                        /* Load a different smb.conf file */
@@ -701,6 +812,10 @@ int main(int argc, char **argv)
                        pstrcpy(dyn_CONFIGFILE,optarg);
                        break;
 
+               case 'h':
+                       usage();
+                       exit(0);
+
                default:
                        printf("Unknown option %c\n", (char)opt);
                        exit(1);
@@ -721,6 +836,7 @@ int main(int argc, char **argv)
        }
 
        /* Setup names. */
+
        if (!*global_myname) {
                char *p;
 
@@ -732,11 +848,10 @@ int main(int argc, char **argv)
 
         fstrcpy(global_myworkgroup, lp_workgroup());
 
-       if (new_debuglevel != -1)
-               DEBUGLEVEL = new_debuglevel;
-
-       if (!interactive)
+       if (!interactive) {
                become_daemon();
+               pidfile_create("winbindd");
+       }
 
 #if HAVE_SETPGID
        /*
@@ -747,46 +862,22 @@ int main(int argc, char **argv)
                setpgid( (pid_t)0, (pid_t)0);
 #endif
 
-       load_interfaces();
-
-       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. */ 
-
-       init_domain_list();
-
-       ZERO_STRUCT(server_state);
-
-       /* Winbind daemon initialisation */
-
-       if (!winbindd_param_init())
-               return 1;
+       if (opt_dual_daemon) {
+               do_dual_daemon();
+       }
 
-       if (!winbindd_idmap_init())
+       if (winbind_setup_common() != 0) {
                return 1;
+       }
 
-       /* Unblock all signals we are interested in as they may have been
-          blocked by the parent process. */
-
-       BlockSignals(False, SIGINT);
-       BlockSignals(False, SIGQUIT);
-       BlockSignals(False, SIGTERM);
-       BlockSignals(False, SIGUSR2);
-       BlockSignals(False, SIGHUP);
-
-       /* Setup signal handlers */
-       
-       CatchSignal(SIGINT, termination_handler);      /* Exit on these sigs */
-       CatchSignal(SIGQUIT, termination_handler);
-       CatchSignal(SIGTERM, termination_handler);
+       /* Initialise messaging system */
 
-       CatchSignal(SIGPIPE, SIG_IGN);                 /* Ignore sigpipe */
-       CatchSignal(SIGUSR1, SIG_IGN);                 /* Samba messages */
+       if (!message_init()) {
+               DEBUG(0, ("unable to initialise messaging system\n"));
+               exit(1);
+       }
 
-       CatchSignal(SIGUSR2, sigusr2_handler);         /* Debugging sigs */
-       CatchSignal(SIGHUP, sighup_handler);
+       register_msg_pool_usage();
 
        /* Create UNIX domain socket */