root/source3/winbindd/winbindd.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. winbind_event_context
  2. winbind_messaging_context
  3. reload_services_file
  4. fault_quit
  5. winbindd_status
  6. print_winbindd_status
  7. flush_caches
  8. flush_caches_noinit
  9. terminate
  10. winbindd_sig_term_handler
  11. winbindd_setup_sig_term_handler
  12. winbindd_sig_hup_handler
  13. winbindd_setup_sig_hup_handler
  14. winbindd_sig_chld_handler
  15. winbindd_setup_sig_chld_handler
  16. winbindd_sig_usr2_handler
  17. winbindd_setup_sig_usr2_handler
  18. msg_reload_services
  19. msg_shutdown
  20. winbind_msg_validate_cache
  21. process_request
  22. add_fd_event
  23. remove_fd_event
  24. rw_callback
  25. setup_async_read
  26. setup_async_write
  27. response_extra_sent
  28. response_main_sent
  29. request_finished
  30. request_error
  31. request_ok
  32. request_len_recv
  33. request_main_recv
  34. request_recv
  35. new_connection
  36. remove_client
  37. remove_idle_client
  38. winbindd_listen_fde_handler
  39. winbindd_setup_listeners
  40. process_loop
  41. winbindd_use_idmap_cache
  42. winbindd_use_cache
  43. main

   1 /* 
   2    Unix SMB/CIFS implementation.
   3 
   4    Winbind daemon for ntdom nss module
   5 
   6    Copyright (C) by Tim Potter 2000-2002
   7    Copyright (C) Andrew Tridgell 2002
   8    Copyright (C) Jelmer Vernooij 2003
   9    Copyright (C) Volker Lendecke 2004
  10 
  11    This program is free software; you can redistribute it and/or modify
  12    it under the terms of the GNU General Public License as published by
  13    the Free Software Foundation; either version 3 of the License, or
  14    (at your option) any later version.
  15 
  16    This program is distributed in the hope that it will be useful,
  17    but WITHOUT ANY WARRANTY; without even the implied warranty of
  18    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  19    GNU General Public License for more details.
  20 
  21    You should have received a copy of the GNU General Public License
  22    along with this program.  If not, see <http://www.gnu.org/licenses/>.
  23 */
  24 
  25 #include "includes.h"
  26 #include "winbindd.h"
  27 
  28 #undef DBGC_CLASS
  29 #define DBGC_CLASS DBGC_WINBIND
  30 
  31 static bool opt_nocache = False;
  32 static bool interactive = False;
  33 
  34 extern bool override_logfile;
  35 
  36 struct event_context *winbind_event_context(void)
     /* [<][>][^][v][top][bottom][index][help] */
  37 {
  38         static struct event_context *ctx;
  39 
  40         if (!ctx && !(ctx = event_context_init(NULL))) {
  41                 smb_panic("Could not init winbind event context");
  42         }
  43         return ctx;
  44 }
  45 
  46 struct messaging_context *winbind_messaging_context(void)
     /* [<][>][^][v][top][bottom][index][help] */
  47 {
  48         static struct messaging_context *ctx;
  49 
  50         if (ctx == NULL) {
  51                 ctx = messaging_init(NULL, server_id_self(),
  52                                      winbind_event_context());
  53         }
  54         if (ctx == NULL) {
  55                 DEBUG(0, ("Could not init winbind messaging context.\n"));
  56         }
  57         return ctx;
  58 }
  59 
  60 /* Reload configuration */
  61 
  62 static bool reload_services_file(const char *lfile)
     /* [<][>][^][v][top][bottom][index][help] */
  63 {
  64         bool ret;
  65 
  66         if (lp_loaded()) {
  67                 const char *fname = lp_configfile();
  68 
  69                 if (file_exist(fname) && !strcsequal(fname,get_dyn_CONFIGFILE())) {
  70                         set_dyn_CONFIGFILE(fname);
  71                 }
  72         }
  73 
  74         /* if this is a child, restore the logfile to the special
  75            name - <domain>, idmap, etc. */
  76         if (lfile && *lfile) {
  77                 lp_set_logfile(lfile);
  78         }
  79 
  80         reopen_logs();
  81         ret = lp_load(get_dyn_CONFIGFILE(),False,False,True,True);
  82 
  83         reopen_logs();
  84         load_interfaces();
  85 
  86         return(ret);
  87 }
  88 
  89 
  90 /**************************************************************************** **
  91  Handle a fault..
  92  **************************************************************************** */
  93 
  94 static void fault_quit(void)
     /* [<][>][^][v][top][bottom][index][help] */
  95 {
  96         dump_core();
  97 }
  98 
  99 static void winbindd_status(void)
     /* [<][>][^][v][top][bottom][index][help] */
 100 {
 101         struct winbindd_cli_state *tmp;
 102 
 103         DEBUG(0, ("winbindd status:\n"));
 104 
 105         /* Print client state information */
 106 
 107         DEBUG(0, ("\t%d clients currently active\n", winbindd_num_clients()));
 108 
 109         if (DEBUGLEVEL >= 2 && winbindd_num_clients()) {
 110                 DEBUG(2, ("\tclient list:\n"));
 111                 for(tmp = winbindd_client_list(); tmp; tmp = tmp->next) {
 112                         DEBUGADD(2, ("\t\tpid %lu, sock %d\n",
 113                                   (unsigned long)tmp->pid, tmp->sock));
 114                 }
 115         }
 116 }
 117 
 118 /* Print winbindd status to log file */
 119 
 120 static void print_winbindd_status(void)
     /* [<][>][^][v][top][bottom][index][help] */
 121 {
 122         winbindd_status();
 123 }
 124 
 125 /* Flush client cache */
 126 
 127 static void flush_caches(void)
     /* [<][>][^][v][top][bottom][index][help] */
 128 {
 129         /* We need to invalidate cached user list entries on a SIGHUP 
 130            otherwise cached access denied errors due to restrict anonymous
 131            hang around until the sequence number changes. */
 132 
 133         if (!wcache_invalidate_cache()) {
 134                 DEBUG(0, ("invalidating the cache failed; revalidate the cache\n"));
 135                 if (!winbindd_cache_validate_and_initialize()) {
 136                         exit(1);
 137                 }
 138         }
 139 }
 140 
 141 static void flush_caches_noinit(void)
     /* [<][>][^][v][top][bottom][index][help] */
 142 {
 143         /*
 144          * We need to invalidate cached user list entries on a SIGHUP
 145          * otherwise cached access denied errors due to restrict anonymous
 146          * hang around until the sequence number changes.
 147          * NB
 148          * Skip uninitialized domains when flush cache.
 149          * If domain is not initialized, it means it is never
 150          * used or never become online. look, wcache_invalidate_cache()
 151          * -> get_cache() -> init_dc_connection(). It causes a lot of traffic
 152          * for unused domains and large traffic for primay domain's DC if there
 153          * are many domains..
 154          */
 155 
 156         if (!wcache_invalidate_cache_noinit()) {
 157                 DEBUG(0, ("invalidating the cache failed; revalidate the cache\n"));
 158                 if (!winbindd_cache_validate_and_initialize()) {
 159                         exit(1);
 160                 }
 161         }
 162 }
 163 
 164 /* Handle the signal by unlinking socket and exiting */
 165 
 166 static void terminate(bool is_parent)
     /* [<][>][^][v][top][bottom][index][help] */
 167 {
 168         if (is_parent) {
 169                 /* When parent goes away we should
 170                  * remove the socket file. Not so
 171                  * when children terminate.
 172                  */ 
 173                 char *path = NULL;
 174 
 175                 if (asprintf(&path, "%s/%s",
 176                         get_winbind_pipe_dir(), WINBINDD_SOCKET_NAME) > 0) {
 177                         unlink(path);
 178                         SAFE_FREE(path);
 179                 }
 180         }
 181 
 182         idmap_close();
 183 
 184         trustdom_cache_shutdown();
 185 
 186 #if 0
 187         if (interactive) {
 188                 TALLOC_CTX *mem_ctx = talloc_init("end_description");
 189                 char *description = talloc_describe_all(mem_ctx);
 190 
 191                 DEBUG(3, ("tallocs left:\n%s\n", description));
 192                 talloc_destroy(mem_ctx);
 193         }
 194 #endif
 195 
 196         if (is_parent) {
 197                 pidfile_unlink();
 198         }
 199 
 200         exit(0);
 201 }
 202 
 203 static void winbindd_sig_term_handler(struct tevent_context *ev,
     /* [<][>][^][v][top][bottom][index][help] */
 204                                       struct tevent_signal *se,
 205                                       int signum,
 206                                       int count,
 207                                       void *siginfo,
 208                                       void *private_data)
 209 {
 210         bool *is_parent = talloc_get_type_abort(private_data, bool);
 211 
 212         DEBUG(0,("Got sig[%d] terminate (is_parent=%d)\n",
 213                  signum, (int)*is_parent));
 214         terminate(*is_parent);
 215 }
 216 
 217 bool winbindd_setup_sig_term_handler(bool parent)
     /* [<][>][^][v][top][bottom][index][help] */
 218 {
 219         struct tevent_signal *se;
 220         bool *is_parent;
 221 
 222         is_parent = talloc(winbind_event_context(), bool);
 223         if (!is_parent) {
 224                 return false;
 225         }
 226 
 227         *is_parent = parent;
 228 
 229         se = tevent_add_signal(winbind_event_context(),
 230                                is_parent,
 231                                SIGTERM, 0,
 232                                winbindd_sig_term_handler,
 233                                is_parent);
 234         if (!se) {
 235                 DEBUG(0,("failed to setup SIGTERM handler"));
 236                 talloc_free(is_parent);
 237                 return false;
 238         }
 239 
 240         se = tevent_add_signal(winbind_event_context(),
 241                                is_parent,
 242                                SIGINT, 0,
 243                                winbindd_sig_term_handler,
 244                                is_parent);
 245         if (!se) {
 246                 DEBUG(0,("failed to setup SIGINT handler"));
 247                 talloc_free(is_parent);
 248                 return false;
 249         }
 250 
 251         se = tevent_add_signal(winbind_event_context(),
 252                                is_parent,
 253                                SIGQUIT, 0,
 254                                winbindd_sig_term_handler,
 255                                is_parent);
 256         if (!se) {
 257                 DEBUG(0,("failed to setup SIGINT handler"));
 258                 talloc_free(is_parent);
 259                 return false;
 260         }
 261 
 262         return true;
 263 }
 264 
 265 static void winbindd_sig_hup_handler(struct tevent_context *ev,
     /* [<][>][^][v][top][bottom][index][help] */
 266                                      struct tevent_signal *se,
 267                                      int signum,
 268                                      int count,
 269                                      void *siginfo,
 270                                      void *private_data)
 271 {
 272         const char *file = (const char *)private_data;
 273 
 274         DEBUG(1,("Reloading services after SIGHUP\n"));
 275         flush_caches_noinit();
 276         reload_services_file(file);
 277 }
 278 
 279 bool winbindd_setup_sig_hup_handler(const char *lfile)
     /* [<][>][^][v][top][bottom][index][help] */
 280 {
 281         struct tevent_signal *se;
 282         char *file = NULL;
 283 
 284         if (lfile) {
 285                 file = talloc_strdup(winbind_event_context(),
 286                                      lfile);
 287                 if (!file) {
 288                         return false;
 289                 }
 290         }
 291 
 292         se = tevent_add_signal(winbind_event_context(),
 293                                winbind_event_context(),
 294                                SIGHUP, 0,
 295                                winbindd_sig_hup_handler,
 296                                file);
 297         if (!se) {
 298                 return false;
 299         }
 300 
 301         return true;
 302 }
 303 
 304 static void winbindd_sig_chld_handler(struct tevent_context *ev,
     /* [<][>][^][v][top][bottom][index][help] */
 305                                       struct tevent_signal *se,
 306                                       int signum,
 307                                       int count,
 308                                       void *siginfo,
 309                                       void *private_data)
 310 {
 311         pid_t pid;
 312 
 313         while ((pid = sys_waitpid(-1, NULL, WNOHANG)) > 0) {
 314                 winbind_child_died(pid);
 315         }
 316 }
 317 
 318 static bool winbindd_setup_sig_chld_handler(void)
     /* [<][>][^][v][top][bottom][index][help] */
 319 {
 320         struct tevent_signal *se;
 321 
 322         se = tevent_add_signal(winbind_event_context(),
 323                                winbind_event_context(),
 324                                SIGCHLD, 0,
 325                                winbindd_sig_chld_handler,
 326                                NULL);
 327         if (!se) {
 328                 return false;
 329         }
 330 
 331         return true;
 332 }
 333 
 334 static void winbindd_sig_usr2_handler(struct tevent_context *ev,
     /* [<][>][^][v][top][bottom][index][help] */
 335                                       struct tevent_signal *se,
 336                                       int signum,
 337                                       int count,
 338                                       void *siginfo,
 339                                       void *private_data)
 340 {
 341         print_winbindd_status();
 342 }
 343 
 344 static bool winbindd_setup_sig_usr2_handler(void)
     /* [<][>][^][v][top][bottom][index][help] */
 345 {
 346         struct tevent_signal *se;
 347 
 348         se = tevent_add_signal(winbind_event_context(),
 349                                winbind_event_context(),
 350                                SIGUSR2, 0,
 351                                winbindd_sig_usr2_handler,
 352                                NULL);
 353         if (!se) {
 354                 return false;
 355         }
 356 
 357         return true;
 358 }
 359 
 360 /* React on 'smbcontrol winbindd reload-config' in the same way as on SIGHUP*/
 361 static void msg_reload_services(struct messaging_context *msg,
     /* [<][>][^][v][top][bottom][index][help] */
 362                                 void *private_data,
 363                                 uint32_t msg_type,
 364                                 struct server_id server_id,
 365                                 DATA_BLOB *data)
 366 {
 367         /* Flush various caches */
 368         flush_caches();
 369         reload_services_file((const char *) private_data);
 370 }
 371 
 372 /* React on 'smbcontrol winbindd shutdown' in the same way as on SIGTERM*/
 373 static void msg_shutdown(struct messaging_context *msg,
     /* [<][>][^][v][top][bottom][index][help] */
 374                          void *private_data,
 375                          uint32_t msg_type,
 376                          struct server_id server_id,
 377                          DATA_BLOB *data)
 378 {
 379         /* only the parent waits for this message */
 380         DEBUG(0,("Got shutdown message\n"));
 381         terminate(true);
 382 }
 383 
 384 
 385 static void winbind_msg_validate_cache(struct messaging_context *msg_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
 386                                        void *private_data,
 387                                        uint32_t msg_type,
 388                                        struct server_id server_id,
 389                                        DATA_BLOB *data)
 390 {
 391         uint8 ret;
 392         pid_t child_pid;
 393         struct sigaction act;
 394         struct sigaction oldact;
 395 
 396         DEBUG(10, ("winbindd_msg_validate_cache: got validate-cache "
 397                    "message.\n"));
 398 
 399         /*
 400          * call the validation code from a child:
 401          * so we don't block the main winbindd and the validation
 402          * code can safely use fork/waitpid...
 403          */
 404         CatchChild();
 405         child_pid = sys_fork();
 406 
 407         if (child_pid == -1) {
 408                 DEBUG(1, ("winbind_msg_validate_cache: Could not fork: %s\n",
 409                           strerror(errno)));
 410                 return;
 411         }
 412 
 413         if (child_pid != 0) {
 414                 /* parent */
 415                 DEBUG(5, ("winbind_msg_validate_cache: child created with "
 416                           "pid %d.\n", (int)child_pid));
 417                 return;
 418         }
 419 
 420         /* child */
 421 
 422         /* install default SIGCHLD handler: validation code uses fork/waitpid */
 423         ZERO_STRUCT(act);
 424         act.sa_handler = SIG_DFL;
 425 #ifdef SA_RESTART
 426         /* We *want* SIGALRM to interrupt a system call. */
 427         act.sa_flags = SA_RESTART;
 428 #endif
 429         sigemptyset(&act.sa_mask);
 430         sigaddset(&act.sa_mask,SIGCHLD);
 431         sigaction(SIGCHLD,&act,&oldact);
 432 
 433         ret = (uint8)winbindd_validate_cache_nobackup();
 434         DEBUG(10, ("winbindd_msg_validata_cache: got return value %d\n", ret));
 435         messaging_send_buf(msg_ctx, server_id, MSG_WINBIND_VALIDATE_CACHE, &ret,
 436                            (size_t)1);
 437         _exit(0);
 438 }
 439 
 440 static struct winbindd_dispatch_table {
 441         enum winbindd_cmd cmd;
 442         void (*fn)(struct winbindd_cli_state *state);
 443         const char *winbindd_cmd_name;
 444 } dispatch_table[] = {
 445 
 446         /* User functions */
 447 
 448         { WINBINDD_GETPWNAM, winbindd_getpwnam, "GETPWNAM" },
 449         { WINBINDD_GETPWUID, winbindd_getpwuid, "GETPWUID" },
 450         { WINBINDD_GETPWSID, winbindd_getpwsid, "GETPWSID" },
 451 
 452         { WINBINDD_SETPWENT, winbindd_setpwent, "SETPWENT" },
 453         { WINBINDD_ENDPWENT, winbindd_endpwent, "ENDPWENT" },
 454         { WINBINDD_GETPWENT, winbindd_getpwent, "GETPWENT" },
 455 
 456         { WINBINDD_GETGROUPS, winbindd_getgroups, "GETGROUPS" },
 457         { WINBINDD_GETUSERSIDS, winbindd_getusersids, "GETUSERSIDS" },
 458         { WINBINDD_GETUSERDOMGROUPS, winbindd_getuserdomgroups,
 459           "GETUSERDOMGROUPS" },
 460         { WINBINDD_GETSIDALIASES, winbindd_getsidaliases,
 461            "LOOKUPUSERALIASES" },
 462 
 463         /* Group functions */
 464 
 465         { WINBINDD_GETGRNAM, winbindd_getgrnam, "GETGRNAM" },
 466         { WINBINDD_GETGRGID, winbindd_getgrgid, "GETGRGID" },
 467         { WINBINDD_SETGRENT, winbindd_setgrent, "SETGRENT" },
 468         { WINBINDD_ENDGRENT, winbindd_endgrent, "ENDGRENT" },
 469         { WINBINDD_GETGRENT, winbindd_getgrent, "GETGRENT" },
 470         { WINBINDD_GETGRLST, winbindd_getgrent, "GETGRLST" },
 471 
 472         /* PAM auth functions */
 473 
 474         { WINBINDD_PAM_AUTH, winbindd_pam_auth, "PAM_AUTH" },
 475         { WINBINDD_PAM_AUTH_CRAP, winbindd_pam_auth_crap, "AUTH_CRAP" },
 476         { WINBINDD_PAM_CHAUTHTOK, winbindd_pam_chauthtok, "CHAUTHTOK" },
 477         { WINBINDD_PAM_LOGOFF, winbindd_pam_logoff, "PAM_LOGOFF" },
 478         { WINBINDD_PAM_CHNG_PSWD_AUTH_CRAP, winbindd_pam_chng_pswd_auth_crap, "CHNG_PSWD_AUTH_CRAP" },
 479 
 480         /* Enumeration functions */
 481 
 482         { WINBINDD_LIST_USERS, winbindd_list_users, "LIST_USERS" },
 483         { WINBINDD_LIST_GROUPS, winbindd_list_groups, "LIST_GROUPS" },
 484         { WINBINDD_LIST_TRUSTDOM, winbindd_list_trusted_domains,
 485           "LIST_TRUSTDOM" },
 486         { WINBINDD_SHOW_SEQUENCE, winbindd_show_sequence, "SHOW_SEQUENCE" },
 487 
 488         /* SID related functions */
 489 
 490         { WINBINDD_LOOKUPSID, winbindd_lookupsid, "LOOKUPSID" },
 491         { WINBINDD_LOOKUPNAME, winbindd_lookupname, "LOOKUPNAME" },
 492         { WINBINDD_LOOKUPRIDS, winbindd_lookuprids, "LOOKUPRIDS" },
 493 
 494         /* Lookup related functions */
 495 
 496         { WINBINDD_SID_TO_UID, winbindd_sid_to_uid, "SID_TO_UID" },
 497         { WINBINDD_SID_TO_GID, winbindd_sid_to_gid, "SID_TO_GID" },
 498         { WINBINDD_UID_TO_SID, winbindd_uid_to_sid, "UID_TO_SID" },
 499         { WINBINDD_GID_TO_SID, winbindd_gid_to_sid, "GID_TO_SID" },
 500         { WINBINDD_ALLOCATE_UID, winbindd_allocate_uid, "ALLOCATE_UID" },
 501         { WINBINDD_ALLOCATE_GID, winbindd_allocate_gid, "ALLOCATE_GID" },
 502         { WINBINDD_SET_MAPPING, winbindd_set_mapping, "SET_MAPPING" },
 503         { WINBINDD_REMOVE_MAPPING, winbindd_remove_mapping, "REMOVE_MAPPING" },
 504         { WINBINDD_SET_HWM, winbindd_set_hwm, "SET_HWMS" },
 505 
 506         /* Miscellaneous */
 507 
 508         { WINBINDD_CHECK_MACHACC, winbindd_check_machine_acct, "CHECK_MACHACC" },
 509         { WINBINDD_PING, winbindd_ping, "PING" },
 510         { WINBINDD_INFO, winbindd_info, "INFO" },
 511         { WINBINDD_INTERFACE_VERSION, winbindd_interface_version,
 512           "INTERFACE_VERSION" },
 513         { WINBINDD_DOMAIN_NAME, winbindd_domain_name, "DOMAIN_NAME" },
 514         { WINBINDD_DOMAIN_INFO, winbindd_domain_info, "DOMAIN_INFO" },
 515         { WINBINDD_NETBIOS_NAME, winbindd_netbios_name, "NETBIOS_NAME" },
 516         { WINBINDD_PRIV_PIPE_DIR, winbindd_priv_pipe_dir,
 517           "WINBINDD_PRIV_PIPE_DIR" },
 518         { WINBINDD_GETDCNAME, winbindd_getdcname, "GETDCNAME" },
 519         { WINBINDD_DSGETDCNAME, winbindd_dsgetdcname, "DSGETDCNAME" },
 520 
 521         /* Credential cache access */
 522         { WINBINDD_CCACHE_NTLMAUTH, winbindd_ccache_ntlm_auth, "NTLMAUTH" },
 523 
 524         /* WINS functions */
 525 
 526         { WINBINDD_WINS_BYNAME, winbindd_wins_byname, "WINS_BYNAME" },
 527         { WINBINDD_WINS_BYIP, winbindd_wins_byip, "WINS_BYIP" },
 528 
 529         /* End of list */
 530 
 531         { WINBINDD_NUM_CMDS, NULL, "NONE" }
 532 };
 533 
 534 static void process_request(struct winbindd_cli_state *state)
     /* [<][>][^][v][top][bottom][index][help] */
 535 {
 536         struct winbindd_dispatch_table *table = dispatch_table;
 537 
 538         /* Free response data - we may be interrupted and receive another
 539            command before being able to send this data off. */
 540 
 541         SAFE_FREE(state->response.extra_data.data);  
 542 
 543         ZERO_STRUCT(state->response);
 544 
 545         state->response.result = WINBINDD_PENDING;
 546         state->response.length = sizeof(struct winbindd_response);
 547 
 548         state->mem_ctx = talloc_init("winbind request");
 549         if (state->mem_ctx == NULL)
 550                 return;
 551 
 552         /* Remember who asked us. */
 553         state->pid = state->request.pid;
 554 
 555         /* Process command */
 556 
 557         for (table = dispatch_table; table->fn; table++) {
 558                 if (state->request.cmd == table->cmd) {
 559                         DEBUG(10,("process_request: request fn %s\n",
 560                                   table->winbindd_cmd_name ));
 561                         table->fn(state);
 562                         break;
 563                 }
 564         }
 565 
 566         if (!table->fn) {
 567                 DEBUG(10,("process_request: unknown request fn number %d\n",
 568                           (int)state->request.cmd ));
 569                 request_error(state);
 570         }
 571 }
 572 
 573 /*
 574  * A list of file descriptors being monitored by select in the main processing
 575  * loop. winbindd_fd_event->handler is called whenever the socket is readable/writable.
 576  */
 577 
 578 static struct winbindd_fd_event *fd_events = NULL;
 579 
 580 void add_fd_event(struct winbindd_fd_event *ev)
     /* [<][>][^][v][top][bottom][index][help] */
 581 {
 582         struct winbindd_fd_event *match;
 583 
 584         /* only add unique winbindd_fd_event structs */
 585 
 586         for (match=fd_events; match; match=match->next ) {
 587 #ifdef DEVELOPER
 588                 SMB_ASSERT( match != ev );
 589 #else
 590                 if ( match == ev )
 591                         return;
 592 #endif
 593         }
 594 
 595         DLIST_ADD(fd_events, ev);
 596 }
 597 
 598 void remove_fd_event(struct winbindd_fd_event *ev)
     /* [<][>][^][v][top][bottom][index][help] */
 599 {
 600         DLIST_REMOVE(fd_events, ev);
 601 }
 602 
 603 /*
 604  * Handler for winbindd_fd_events to complete a read/write request, set up by
 605  * setup_async_read/setup_async_write.
 606  */
 607 
 608 static void rw_callback(struct winbindd_fd_event *event, int flags)
     /* [<][>][^][v][top][bottom][index][help] */
 609 {
 610         size_t todo;
 611         ssize_t done = 0;
 612 
 613         todo = event->length - event->done;
 614 
 615         if (event->flags & EVENT_FD_WRITE) {
 616                 SMB_ASSERT(flags == EVENT_FD_WRITE);
 617                 done = sys_write(event->fd,
 618                                  &((char *)event->data)[event->done],
 619                                  todo);
 620 
 621                 if (done <= 0) {
 622                         event->flags = 0;
 623                         event->finished(event->private_data, False);
 624                         return;
 625                 }
 626         }
 627 
 628         if (event->flags & EVENT_FD_READ) {
 629                 SMB_ASSERT(flags == EVENT_FD_READ);
 630                 done = sys_read(event->fd, &((char *)event->data)[event->done],
 631                                 todo);
 632 
 633                 if (done <= 0) {
 634                         event->flags = 0;
 635                         event->finished(event->private_data, False);
 636                         return;
 637                 }
 638         }
 639 
 640         event->done += done;
 641 
 642         if (event->done == event->length) {
 643                 event->flags = 0;
 644                 event->finished(event->private_data, True);
 645         }
 646 }
 647 
 648 /*
 649  * Request an async read/write on a winbindd_fd_event structure. (*finished) is called
 650  * when the request is completed or an error had occurred.
 651  */
 652 
 653 void setup_async_read(struct winbindd_fd_event *event, void *data, size_t length,
     /* [<][>][^][v][top][bottom][index][help] */
 654                       void (*finished)(void *private_data, bool success),
 655                       void *private_data)
 656 {
 657         SMB_ASSERT(event->flags == 0);
 658         event->data = data;
 659         event->length = length;
 660         event->done = 0;
 661         event->handler = rw_callback;
 662         event->finished = finished;
 663         event->private_data = private_data;
 664         event->flags = EVENT_FD_READ;
 665 }
 666 
 667 void setup_async_write(struct winbindd_fd_event *event, void *data, size_t length,
     /* [<][>][^][v][top][bottom][index][help] */
 668                        void (*finished)(void *private_data, bool success),
 669                        void *private_data)
 670 {
 671         SMB_ASSERT(event->flags == 0);
 672         event->data = data;
 673         event->length = length;
 674         event->done = 0;
 675         event->handler = rw_callback;
 676         event->finished = finished;
 677         event->private_data = private_data;
 678         event->flags = EVENT_FD_WRITE;
 679 }
 680 
 681 /*
 682  * This is the main event loop of winbind requests. It goes through a
 683  * state-machine of 3 read/write requests, 4 if you have extra data to send.
 684  *
 685  * An idle winbind client has a read request of 4 bytes outstanding,
 686  * finalizing function is request_len_recv, checking the length. request_recv
 687  * then processes the packet. The processing function then at some point has
 688  * to call request_finished which schedules sending the response.
 689  */
 690 
 691 static void request_len_recv(void *private_data, bool success);
 692 static void request_recv(void *private_data, bool success);
 693 static void request_main_recv(void *private_data, bool success);
 694 static void request_finished(struct winbindd_cli_state *state);
 695 static void response_main_sent(void *private_data, bool success);
 696 static void response_extra_sent(void *private_data, bool success);
 697 
 698 static void response_extra_sent(void *private_data, bool success)
     /* [<][>][^][v][top][bottom][index][help] */
 699 {
 700         struct winbindd_cli_state *state =
 701                 talloc_get_type_abort(private_data, struct winbindd_cli_state);
 702 
 703         TALLOC_FREE(state->mem_ctx);
 704 
 705         if (!success) {
 706                 state->finished = True;
 707                 return;
 708         }
 709 
 710         SAFE_FREE(state->response.extra_data.data);
 711 
 712         setup_async_read(&state->fd_event, &state->request, sizeof(uint32),
 713                          request_len_recv, state);
 714 }
 715 
 716 static void response_main_sent(void *private_data, bool success)
     /* [<][>][^][v][top][bottom][index][help] */
 717 {
 718         struct winbindd_cli_state *state =
 719                 talloc_get_type_abort(private_data, struct winbindd_cli_state);
 720 
 721         if (!success) {
 722                 state->finished = True;
 723                 return;
 724         }
 725 
 726         if (state->response.length == sizeof(state->response)) {
 727                 TALLOC_FREE(state->mem_ctx);
 728 
 729                 setup_async_read(&state->fd_event, &state->request,
 730                                  sizeof(uint32), request_len_recv, state);
 731                 return;
 732         }
 733 
 734         setup_async_write(&state->fd_event, state->response.extra_data.data,
 735                           state->response.length - sizeof(state->response),
 736                           response_extra_sent, state);
 737 }
 738 
 739 static void request_finished(struct winbindd_cli_state *state)
     /* [<][>][^][v][top][bottom][index][help] */
 740 {
 741         /* Make sure request.extra_data is freed when finish processing a request */
 742         SAFE_FREE(state->request.extra_data.data);
 743         setup_async_write(&state->fd_event, &state->response,
 744                           sizeof(state->response), response_main_sent, state);
 745 }
 746 
 747 void request_error(struct winbindd_cli_state *state)
     /* [<][>][^][v][top][bottom][index][help] */
 748 {
 749         SMB_ASSERT(state->response.result == WINBINDD_PENDING);
 750         state->response.result = WINBINDD_ERROR;
 751         request_finished(state);
 752 }
 753 
 754 void request_ok(struct winbindd_cli_state *state)
     /* [<][>][^][v][top][bottom][index][help] */
 755 {
 756         SMB_ASSERT(state->response.result == WINBINDD_PENDING);
 757         state->response.result = WINBINDD_OK;
 758         request_finished(state);
 759 }
 760 
 761 static void request_len_recv(void *private_data, bool success)
     /* [<][>][^][v][top][bottom][index][help] */
 762 {
 763         struct winbindd_cli_state *state =
 764                 talloc_get_type_abort(private_data, struct winbindd_cli_state);
 765 
 766         if (!success) {
 767                 state->finished = True;
 768                 return;
 769         }
 770 
 771         if (*(uint32 *)(&state->request) != sizeof(state->request)) {
 772                 DEBUG(0,("request_len_recv: Invalid request size received: %d (expected %u)\n",
 773                          *(uint32_t *)(&state->request), (uint32_t)sizeof(state->request)));
 774                 state->finished = True;
 775                 return;
 776         }
 777 
 778         setup_async_read(&state->fd_event, (uint32 *)(&state->request)+1,
 779                          sizeof(state->request) - sizeof(uint32),
 780                          request_main_recv, state);
 781 }
 782 
 783 static void request_main_recv(void *private_data, bool success)
     /* [<][>][^][v][top][bottom][index][help] */
 784 {
 785         struct winbindd_cli_state *state =
 786                 talloc_get_type_abort(private_data, struct winbindd_cli_state);
 787 
 788         if (!success) {
 789                 state->finished = True;
 790                 return;
 791         }
 792 
 793         if (state->request.extra_len == 0) {
 794                 state->request.extra_data.data = NULL;
 795                 request_recv(state, True);
 796                 return;
 797         }
 798 
 799         if ((!state->privileged) &&
 800             (state->request.extra_len > WINBINDD_MAX_EXTRA_DATA)) {
 801                 DEBUG(3, ("Got request with %d bytes extra data on "
 802                           "unprivileged socket\n", (int)state->request.extra_len));
 803                 state->request.extra_data.data = NULL;
 804                 state->finished = True;
 805                 return;
 806         }
 807 
 808         state->request.extra_data.data =
 809                 SMB_MALLOC_ARRAY(char, state->request.extra_len + 1);
 810 
 811         if (state->request.extra_data.data == NULL) {
 812                 DEBUG(0, ("malloc failed\n"));
 813                 state->finished = True;
 814                 return;
 815         }
 816 
 817         /* Ensure null termination */
 818         state->request.extra_data.data[state->request.extra_len] = '\0';
 819 
 820         setup_async_read(&state->fd_event, state->request.extra_data.data,
 821                          state->request.extra_len, request_recv, state);
 822 }
 823 
 824 static void request_recv(void *private_data, bool success)
     /* [<][>][^][v][top][bottom][index][help] */
 825 {
 826         struct winbindd_cli_state *state =
 827                 talloc_get_type_abort(private_data, struct winbindd_cli_state);
 828 
 829         if (!success) {
 830                 state->finished = True;
 831                 return;
 832         }
 833 
 834         process_request(state);
 835 }
 836 
 837 /* Process a new connection by adding it to the client connection list */
 838 
 839 static void new_connection(int listen_sock, bool privileged)
     /* [<][>][^][v][top][bottom][index][help] */
 840 {
 841         struct sockaddr_un sunaddr;
 842         struct winbindd_cli_state *state;
 843         socklen_t len;
 844         int sock;
 845 
 846         /* Accept connection */
 847 
 848         len = sizeof(sunaddr);
 849 
 850         do {
 851                 sock = accept(listen_sock, (struct sockaddr *)&sunaddr, &len);
 852         } while (sock == -1 && errno == EINTR);
 853 
 854         if (sock == -1)
 855                 return;
 856 
 857         DEBUG(6,("accepted socket %d\n", sock));
 858 
 859         /* Create new connection structure */
 860 
 861         if ((state = TALLOC_ZERO_P(NULL, struct winbindd_cli_state)) == NULL) {
 862                 close(sock);
 863                 return;
 864         }
 865 
 866         state->sock = sock;
 867 
 868         state->last_access = time(NULL);        
 869 
 870         state->privileged = privileged;
 871 
 872         state->fd_event.fd = state->sock;
 873         state->fd_event.flags = 0;
 874         add_fd_event(&state->fd_event);
 875 
 876         setup_async_read(&state->fd_event, &state->request, sizeof(uint32),
 877                          request_len_recv, state);
 878 
 879         /* Add to connection list */
 880 
 881         winbindd_add_client(state);
 882 }
 883 
 884 /* Remove a client connection from client connection list */
 885 
 886 static void remove_client(struct winbindd_cli_state *state)
     /* [<][>][^][v][top][bottom][index][help] */
 887 {
 888         char c = 0;
 889         int nwritten;
 890 
 891         /* It's a dead client - hold a funeral */
 892 
 893         if (state == NULL) {
 894                 return;
 895         }
 896 
 897         if (!state->finished) {
 898                 /* tell client, we are closing ... */
 899                 nwritten = write(state->sock, &c, sizeof(c));
 900                 if (nwritten == -1) {
 901                         DEBUG(2, ("final write to client failed: %s\n",
 902                                   strerror(errno)));
 903                 }
 904         }
 905 
 906         /* Close socket */
 907 
 908         close(state->sock);
 909 
 910         /* Free any getent state */
 911 
 912         free_getent_state(state->getpwent_state);
 913         free_getent_state(state->getgrent_state);
 914 
 915         /* We may have some extra data that was not freed if the client was
 916            killed unexpectedly */
 917 
 918         SAFE_FREE(state->response.extra_data.data);
 919 
 920         TALLOC_FREE(state->mem_ctx);
 921 
 922         remove_fd_event(&state->fd_event);
 923 
 924         /* Remove from list and free */
 925 
 926         winbindd_remove_client(state);
 927         TALLOC_FREE(state);
 928 }
 929 
 930 /* Shutdown client connection which has been idle for the longest time */
 931 
 932 static bool remove_idle_client(void)
     /* [<][>][^][v][top][bottom][index][help] */
 933 {
 934         struct winbindd_cli_state *state, *remove_state = NULL;
 935         time_t last_access = 0;
 936         int nidle = 0;
 937 
 938         for (state = winbindd_client_list(); state; state = state->next) {
 939                 if (state->response.result != WINBINDD_PENDING &&
 940                     state->fd_event.flags == EVENT_FD_READ &&
 941                     !state->getpwent_state && !state->getgrent_state) {
 942                         nidle++;
 943                         if (!last_access || state->last_access < last_access) {
 944                                 last_access = state->last_access;
 945                                 remove_state = state;
 946                         }
 947                 }
 948         }
 949 
 950         if (remove_state) {
 951                 DEBUG(5,("Found %d idle client connections, shutting down sock %d, pid %u\n",
 952                         nidle, remove_state->sock, (unsigned int)remove_state->pid));
 953                 remove_client(remove_state);
 954                 return True;
 955         }
 956 
 957         return False;
 958 }
 959 
 960 struct winbindd_listen_state {
 961         bool privileged;
 962         int fd;
 963         struct tevent_fd *fde;
 964 };
 965 
 966 static void winbindd_listen_fde_handler(struct tevent_context *ev,
     /* [<][>][^][v][top][bottom][index][help] */
 967                                         struct tevent_fd *fde,
 968                                         uint16_t flags,
 969                                         void *private_data)
 970 {
 971         struct winbindd_listen_state *s = talloc_get_type_abort(private_data,
 972                                           struct winbindd_listen_state);
 973 
 974         while (winbindd_num_clients() >
 975                WINBINDD_MAX_SIMULTANEOUS_CLIENTS - 1) {
 976                 DEBUG(5,("winbindd: Exceeding %d client "
 977                          "connections, removing idle "
 978                          "connection.\n",
 979                          WINBINDD_MAX_SIMULTANEOUS_CLIENTS));
 980                 if (!remove_idle_client()) {
 981                         DEBUG(0,("winbindd: Exceeding %d "
 982                                  "client connections, no idle "
 983                                  "connection found\n",
 984                                  WINBINDD_MAX_SIMULTANEOUS_CLIENTS));
 985                         break;
 986                 }
 987         }
 988 
 989         /* new, non-privileged connection */
 990         new_connection(s->fd, s->privileged);
 991 }
 992 
 993 static bool winbindd_setup_listeners(void)
     /* [<][>][^][v][top][bottom][index][help] */
 994 {
 995         struct winbindd_listen_state *pub_state = NULL;
 996         struct winbindd_listen_state *priv_state = NULL;
 997 
 998         pub_state = talloc(winbind_event_context(),
 999                            struct winbindd_listen_state);
1000         if (!pub_state) {
1001                 goto failed;
1002         }
1003 
1004         pub_state->privileged = false;
1005         pub_state->fd = open_winbindd_socket();
1006         if (pub_state->fd == -1) {
1007                 goto failed;
1008         }
1009 
1010         pub_state->fde = tevent_add_fd(winbind_event_context(),
1011                                        pub_state, pub_state->fd,
1012                                        TEVENT_FD_READ,
1013                                        winbindd_listen_fde_handler,
1014                                        pub_state);
1015         if (!pub_state->fde) {
1016                 close(pub_state->fd);
1017                 goto failed;
1018         }
1019         tevent_fd_set_auto_close(pub_state->fde);
1020 
1021         priv_state = talloc(winbind_event_context(),
1022                             struct winbindd_listen_state);
1023         if (!priv_state) {
1024                 goto failed;
1025         }
1026 
1027         priv_state->privileged = true;
1028         priv_state->fd = open_winbindd_priv_socket();
1029         if (priv_state->fd == -1) {
1030                 goto failed;
1031         }
1032 
1033         priv_state->fde = tevent_add_fd(winbind_event_context(),
1034                                         priv_state, priv_state->fd,
1035                                         TEVENT_FD_READ,
1036                                         winbindd_listen_fde_handler,
1037                                         priv_state);
1038         if (!priv_state->fde) {
1039                 close(priv_state->fd);
1040                 goto failed;
1041         }
1042         tevent_fd_set_auto_close(priv_state->fde);
1043 
1044         return true;
1045 failed:
1046         TALLOC_FREE(pub_state);
1047         TALLOC_FREE(priv_state);
1048         return false;
1049 }
1050 
1051 /* Process incoming clients on listen_sock.  We use a tricky non-blocking,
1052    non-forking, non-threaded model which allows us to handle many
1053    simultaneous connections while remaining impervious to many denial of
1054    service attacks. */
1055 
1056 static void process_loop(void)
     /* [<][>][^][v][top][bottom][index][help] */
1057 {
1058         struct winbindd_fd_event *ev;
1059         fd_set r_fds, w_fds;
1060         int maxfd = 0, selret;
1061         struct timeval timeout, ev_timeout;
1062 
1063         if (run_events(winbind_event_context(), 0, NULL, NULL)) {
1064                 return;
1065         }
1066 
1067         /* Initialise fd lists for select() */
1068 
1069         FD_ZERO(&r_fds);
1070         FD_ZERO(&w_fds);
1071 
1072         timeout.tv_sec = WINBINDD_ESTABLISH_LOOP;
1073         timeout.tv_usec = 0;
1074 
1075         /* Check for any event timeouts. */
1076         {
1077                 struct timeval now;
1078                 GetTimeOfDay(&now);
1079 
1080                 event_add_to_select_args(winbind_event_context(), &now,
1081                                          &r_fds, &w_fds, &ev_timeout, &maxfd);
1082         }
1083         if (get_timed_events_timeout(winbind_event_context(), &ev_timeout)) {
1084                 timeout = timeval_min(&timeout, &ev_timeout);
1085         }
1086 
1087         for (ev = fd_events; ev; ev = ev->next) {
1088                 if (ev->flags & EVENT_FD_READ) {
1089                         FD_SET(ev->fd, &r_fds);
1090                         maxfd = MAX(ev->fd, maxfd);
1091                 }
1092                 if (ev->flags & EVENT_FD_WRITE) {
1093                         FD_SET(ev->fd, &w_fds);
1094                         maxfd = MAX(ev->fd, maxfd);
1095                 }
1096         }
1097 
1098         /* Call select */
1099 
1100         selret = sys_select(maxfd + 1, &r_fds, &w_fds, NULL, &timeout);
1101 
1102         if (selret == 0) {
1103                 goto no_fds_ready;
1104         }
1105 
1106         if (selret == -1) {
1107                 if (errno == EINTR) {
1108                         goto no_fds_ready;
1109                 }
1110 
1111                 /* Select error, something is badly wrong */
1112 
1113                 perror("select");
1114                 exit(1);
1115         }
1116 
1117         /* selret > 0 */
1118 
1119         if (run_events(winbind_event_context(), selret, &r_fds, &w_fds)) {
1120                 return;
1121         }
1122 
1123         ev = fd_events;
1124         while (ev != NULL) {
1125                 struct winbindd_fd_event *next = ev->next;
1126                 int flags = 0;
1127                 if (FD_ISSET(ev->fd, &r_fds))
1128                         flags |= EVENT_FD_READ;
1129                 if (FD_ISSET(ev->fd, &w_fds))
1130                         flags |= EVENT_FD_WRITE;
1131                 if (flags) {
1132                         ev->handler(ev, flags);
1133                         return;
1134                 }
1135                 ev = next;
1136         }
1137 
1138         return;
1139 
1140  no_fds_ready:
1141 
1142         run_events(winbind_event_context(), selret, &r_fds, &w_fds);
1143 
1144 #if 0
1145         winbindd_check_cache_size(time(NULL));
1146 #endif
1147 }
1148 
1149 bool winbindd_use_idmap_cache(void)
     /* [<][>][^][v][top][bottom][index][help] */
1150 {
1151         return !opt_nocache;
1152 }
1153 
1154 bool winbindd_use_cache(void)
     /* [<][>][^][v][top][bottom][index][help] */
1155 {
1156         return !opt_nocache;
1157 }
1158 
1159 /* Main function */
1160 
1161 int main(int argc, char **argv, char **envp)
     /* [<][>][^][v][top][bottom][index][help] */
1162 {
1163         static bool is_daemon = False;
1164         static bool Fork = True;
1165         static bool log_stdout = False;
1166         static bool no_process_group = False;
1167         enum {
1168                 OPT_DAEMON = 1000,
1169                 OPT_FORK,
1170                 OPT_NO_PROCESS_GROUP,
1171                 OPT_LOG_STDOUT
1172         };
1173         struct poptOption long_options[] = {
1174                 POPT_AUTOHELP
1175                 { "stdout", 'S', POPT_ARG_NONE, NULL, OPT_LOG_STDOUT, "Log to stdout" },
1176                 { "foreground", 'F', POPT_ARG_NONE, NULL, OPT_FORK, "Daemon in foreground mode" },
1177                 { "no-process-group", 0, POPT_ARG_NONE, NULL, OPT_NO_PROCESS_GROUP, "Don't create a new process group" },
1178                 { "daemon", 'D', POPT_ARG_NONE, NULL, OPT_DAEMON, "Become a daemon (default)" },
1179                 { "interactive", 'i', POPT_ARG_NONE, NULL, 'i', "Interactive mode" },
1180                 { "no-caching", 'n', POPT_ARG_NONE, NULL, 'n', "Disable caching" },
1181                 POPT_COMMON_SAMBA
1182                 POPT_TABLEEND
1183         };
1184         poptContext pc;
1185         int opt;
1186         TALLOC_CTX *frame = talloc_stackframe();
1187 
1188         /* glibc (?) likes to print "User defined signal 1" and exit if a
1189            SIGUSR[12] is received before a handler is installed */
1190 
1191         CatchSignal(SIGUSR1, SIG_IGN);
1192         CatchSignal(SIGUSR2, SIG_IGN);
1193 
1194         fault_setup((void (*)(void *))fault_quit );
1195         dump_core_setup("winbindd");
1196 
1197         load_case_tables();
1198 
1199         /* Initialise for running in non-root mode */
1200 
1201         sec_init();
1202 
1203         set_remote_machine_name("winbindd", False);
1204 
1205         /* Set environment variable so we don't recursively call ourselves.
1206            This may also be useful interactively. */
1207 
1208         if ( !winbind_off() ) {
1209                 DEBUG(0,("Failed to disable recusive winbindd calls.  Exiting.\n"));
1210                 exit(1);
1211         }
1212 
1213         /* Initialise samba/rpc client stuff */
1214 
1215         pc = poptGetContext("winbindd", argc, (const char **)argv, long_options, 0);
1216 
1217         while ((opt = poptGetNextOpt(pc)) != -1) {
1218                 switch (opt) {
1219                         /* Don't become a daemon */
1220                 case OPT_DAEMON:
1221                         is_daemon = True;
1222                         break;
1223                 case 'i':
1224                         interactive = True;
1225                         log_stdout = True;
1226                         Fork = False;
1227                         break;
1228                 case OPT_FORK:
1229                         Fork = false;
1230                         break;
1231                 case OPT_NO_PROCESS_GROUP:
1232                         no_process_group = true;
1233                         break;
1234                 case OPT_LOG_STDOUT:
1235                         log_stdout = true;
1236                         break;
1237                 case 'n':
1238                         opt_nocache = true;
1239                         break;
1240                 default:
1241                         d_fprintf(stderr, "\nInvalid option %s: %s\n\n",
1242                                   poptBadOption(pc, 0), poptStrerror(opt));
1243                         poptPrintUsage(pc, stderr, 0);
1244                         exit(1);
1245                 }
1246         }
1247 
1248         if (is_daemon && interactive) {
1249                 d_fprintf(stderr,"\nERROR: "
1250                           "Option -i|--interactive is not allowed together with -D|--daemon\n\n");
1251                 poptPrintUsage(pc, stderr, 0);
1252                 exit(1);
1253         }
1254 
1255         if (log_stdout && Fork) {
1256                 d_fprintf(stderr, "\nERROR: "
1257                           "Can't log to stdout (-S) unless daemon is in foreground +(-F) or interactive (-i)\n\n");
1258                 poptPrintUsage(pc, stderr, 0);
1259                 exit(1);
1260         }
1261 
1262         poptFreeContext(pc);
1263 
1264         if (!override_logfile) {
1265                 char *lfile = NULL;
1266                 if (asprintf(&lfile,"%s/log.winbindd",
1267                                 get_dyn_LOGFILEBASE()) > 0) {
1268                         lp_set_logfile(lfile);
1269                         SAFE_FREE(lfile);
1270                 }
1271         }
1272         setup_logging("winbindd", log_stdout);
1273         reopen_logs();
1274 
1275         DEBUG(0,("winbindd version %s started.\n", samba_version_string()));
1276         DEBUGADD(0,("%s\n", COPYRIGHT_STARTUP_MESSAGE));
1277 
1278         if (!lp_load_initial_only(get_dyn_CONFIGFILE())) {
1279                 DEBUG(0, ("error opening config file\n"));
1280                 exit(1);
1281         }
1282 
1283         /* Initialise messaging system */
1284 
1285         if (winbind_messaging_context() == NULL) {
1286                 exit(1);
1287         }
1288 
1289         if (!reload_services_file(NULL)) {
1290                 DEBUG(0, ("error opening config file\n"));
1291                 exit(1);
1292         }
1293 
1294         if (!directory_exist(lp_lockdir())) {
1295                 mkdir(lp_lockdir(), 0755);
1296         }
1297 
1298         /* Setup names. */
1299 
1300         if (!init_names())
1301                 exit(1);
1302 
1303         load_interfaces();
1304 
1305         if (!secrets_init()) {
1306 
1307                 DEBUG(0,("Could not initialize domain trust account secrets. Giving up\n"));
1308                 return False;
1309         }
1310 
1311         /* Enable netbios namecache */
1312 
1313         namecache_enable();
1314 
1315         /* Unblock all signals we are interested in as they may have been
1316            blocked by the parent process. */
1317 
1318         BlockSignals(False, SIGINT);
1319         BlockSignals(False, SIGQUIT);
1320         BlockSignals(False, SIGTERM);
1321         BlockSignals(False, SIGUSR1);
1322         BlockSignals(False, SIGUSR2);
1323         BlockSignals(False, SIGHUP);
1324         BlockSignals(False, SIGCHLD);
1325 
1326         if (!interactive)
1327                 become_daemon(Fork, no_process_group);
1328 
1329         pidfile_create("winbindd");
1330 
1331 #if HAVE_SETPGID
1332         /*
1333          * If we're interactive we want to set our own process group for
1334          * signal management.
1335          */
1336         if (interactive && !no_process_group)
1337                 setpgid( (pid_t)0, (pid_t)0);
1338 #endif
1339 
1340         TimeInit();
1341 
1342         /* Don't use winbindd_reinit_after_fork here as
1343          * we're just starting up and haven't created any
1344          * winbindd-specific resources we must free yet. JRA.
1345          */
1346 
1347         if (!NT_STATUS_IS_OK(reinit_after_fork(winbind_messaging_context(),
1348                                                winbind_event_context(),
1349                                                false))) {
1350                 DEBUG(0,("reinit_after_fork() failed\n"));
1351                 exit(1);
1352         }
1353 
1354         /* Setup signal handlers */
1355 
1356         if (!winbindd_setup_sig_term_handler(true))
1357                 exit(1);
1358         if (!winbindd_setup_sig_hup_handler(NULL))
1359                 exit(1);
1360         if (!winbindd_setup_sig_chld_handler())
1361                 exit(1);
1362         if (!winbindd_setup_sig_usr2_handler())
1363                 exit(1);
1364 
1365         CatchSignal(SIGPIPE, SIG_IGN);                 /* Ignore sigpipe */
1366 
1367         /*
1368          * Ensure all cache and idmap caches are consistent
1369          * and initialized before we startup.
1370          */
1371         if (!winbindd_cache_validate_and_initialize()) {
1372                 exit(1);
1373         }
1374 
1375         /* get broadcast messages */
1376         claim_connection(NULL,"",FLAG_MSG_GENERAL|FLAG_MSG_DBWRAP);
1377 
1378         /* React on 'smbcontrol winbindd reload-config' in the same way
1379            as to SIGHUP signal */
1380         messaging_register(winbind_messaging_context(), NULL,
1381                            MSG_SMB_CONF_UPDATED, msg_reload_services);
1382         messaging_register(winbind_messaging_context(), NULL,
1383                            MSG_SHUTDOWN, msg_shutdown);
1384 
1385         /* Handle online/offline messages. */
1386         messaging_register(winbind_messaging_context(), NULL,
1387                            MSG_WINBIND_OFFLINE, winbind_msg_offline);
1388         messaging_register(winbind_messaging_context(), NULL,
1389                            MSG_WINBIND_ONLINE, winbind_msg_online);
1390         messaging_register(winbind_messaging_context(), NULL,
1391                            MSG_WINBIND_ONLINESTATUS, winbind_msg_onlinestatus);
1392 
1393         messaging_register(winbind_messaging_context(), NULL,
1394                            MSG_DUMP_EVENT_LIST, winbind_msg_dump_event_list);
1395 
1396         messaging_register(winbind_messaging_context(), NULL,
1397                            MSG_WINBIND_VALIDATE_CACHE,
1398                            winbind_msg_validate_cache);
1399 
1400         messaging_register(winbind_messaging_context(), NULL,
1401                            MSG_WINBIND_DUMP_DOMAIN_LIST,
1402                            winbind_msg_dump_domain_list);
1403 
1404         /* Register handler for MSG_DEBUG. */
1405         messaging_register(winbind_messaging_context(), NULL,
1406                            MSG_DEBUG,
1407                            winbind_msg_debug);
1408 
1409         netsamlogon_cache_init(); /* Non-critical */
1410 
1411         /* clear the cached list of trusted domains */
1412 
1413         wcache_tdc_clear();     
1414 
1415         if (!init_domain_list()) {
1416                 DEBUG(0,("unable to initialize domain list\n"));
1417                 exit(1);
1418         }
1419 
1420         init_idmap_child();
1421         init_locator_child();
1422 
1423         smb_nscd_flush_user_cache();
1424         smb_nscd_flush_group_cache();
1425 
1426         /* setup listen sockets */
1427 
1428         if (!winbindd_setup_listeners()) {
1429                 DEBUG(0,("winbindd_setup_listeners() failed\n"));
1430                 exit(1);
1431         }
1432 
1433         TALLOC_FREE(frame);
1434         /* Loop waiting for requests */
1435         while (1) {
1436                 struct winbindd_cli_state *state;
1437 
1438                 frame = talloc_stackframe();
1439 
1440                 /* refresh the trusted domain cache */
1441 
1442                 rescan_trusted_domains();
1443 
1444                 /* Dispose of client connection if it is marked as
1445                    finished */
1446                 state = winbindd_client_list();
1447                 while (state) {
1448                         struct winbindd_cli_state *next = state->next;
1449 
1450                         if (state->finished) {
1451                                 remove_client(state);
1452                         }
1453 
1454                         state = next;
1455                 }
1456 
1457                 process_loop();
1458 
1459                 TALLOC_FREE(frame);
1460         }
1461 
1462         return 0;
1463 }

/* [<][>][^][v][top][bottom][index][help] */