2 Unix SMB/CIFS implementation.
4 Winbind daemon for ntdom nss module
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
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.
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.
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/>.
26 #include "popt_common.h"
28 #include "nsswitch/winbind_client.h"
29 #include "nsswitch/wb_reqtrans.h"
31 #include "../librpc/gen_ndr/srv_lsa.h"
32 #include "../librpc/gen_ndr/srv_samr.h"
35 #include "lib/addrchange.h"
39 #include "../lib/util/pidfile.h"
42 #define DBGC_CLASS DBGC_WINBIND
44 static bool client_is_idle(struct winbindd_cli_state *state);
45 static void remove_client(struct winbindd_cli_state *state);
47 static bool opt_nocache = False;
48 static bool interactive = False;
50 extern bool override_logfile;
52 struct tevent_context *winbind_event_context(void)
54 static struct tevent_context *ev = NULL;
61 * Note we MUST use the NULL context here, not the autofree context,
62 * to avoid side effects in forked children exiting.
64 ev = samba_tevent_context_init(NULL);
66 smb_panic("Could not init winbindd's messaging context.\n");
71 struct messaging_context *winbind_messaging_context(void)
73 static struct messaging_context *msg = NULL;
80 * Note we MUST use the NULL context here, not the autofree context,
81 * to avoid side effects in forked children exiting.
83 msg = messaging_init(NULL, winbind_event_context());
85 smb_panic("Could not init winbindd's messaging context.\n");
90 /* Reload configuration */
92 static bool reload_services_file(const char *lfile)
97 char *fname = lp_configfile(talloc_tos());
99 if (file_exist(fname) && !strcsequal(fname,get_dyn_CONFIGFILE())) {
100 set_dyn_CONFIGFILE(fname);
105 /* if this is a child, restore the logfile to the special
106 name - <domain>, idmap, etc. */
107 if (lfile && *lfile) {
108 lp_set_logfile(lfile);
112 ret = lp_load_global(get_dyn_CONFIGFILE());
121 static void winbindd_status(void)
123 struct winbindd_cli_state *tmp;
125 DEBUG(0, ("winbindd status:\n"));
127 /* Print client state information */
129 DEBUG(0, ("\t%d clients currently active\n", winbindd_num_clients()));
131 if (DEBUGLEVEL >= 2 && winbindd_num_clients()) {
132 DEBUG(2, ("\tclient list:\n"));
133 for(tmp = winbindd_client_list(); tmp; tmp = tmp->next) {
134 DEBUGADD(2, ("\t\tpid %lu, sock %d (%s)\n",
135 (unsigned long)tmp->pid, tmp->sock,
136 client_is_idle(tmp) ? "idle" : "active"));
141 /* Flush client cache */
143 static void flush_caches(void)
145 /* We need to invalidate cached user list entries on a SIGHUP
146 otherwise cached access denied errors due to restrict anonymous
147 hang around until the sequence number changes. */
149 if (!wcache_invalidate_cache()) {
150 DEBUG(0, ("invalidating the cache failed; revalidate the cache\n"));
151 if (!winbindd_cache_validate_and_initialize()) {
157 static void flush_caches_noinit(void)
160 * We need to invalidate cached user list entries on a SIGHUP
161 * otherwise cached access denied errors due to restrict anonymous
162 * hang around until the sequence number changes.
164 * Skip uninitialized domains when flush cache.
165 * If domain is not initialized, it means it is never
166 * used or never become online. look, wcache_invalidate_cache()
167 * -> get_cache() -> init_dc_connection(). It causes a lot of traffic
168 * for unused domains and large traffic for primay domain's DC if there
172 if (!wcache_invalidate_cache_noinit()) {
173 DEBUG(0, ("invalidating the cache failed; revalidate the cache\n"));
174 if (!winbindd_cache_validate_and_initialize()) {
180 /* Handle the signal by unlinking socket and exiting */
182 static void terminate(bool is_parent)
185 /* When parent goes away we should
186 * remove the socket file. Not so
187 * when children terminate.
191 if (asprintf(&path, "%s/%s",
192 get_winbind_pipe_dir(), WINBINDD_SOCKET_NAME) > 0) {
200 trustdom_cache_shutdown();
202 gencache_stabilize();
206 TALLOC_CTX *mem_ctx = talloc_init("end_description");
207 char *description = talloc_describe_all(mem_ctx);
209 DEBUG(3, ("tallocs left:\n%s\n", description));
210 talloc_destroy(mem_ctx);
215 struct messaging_context *msg = winbind_messaging_context();
216 struct server_id self = messaging_server_id(msg);
217 serverid_deregister(self);
218 pidfile_unlink(lp_piddir(), "winbindd");
224 static void winbindd_sig_term_handler(struct tevent_context *ev,
225 struct tevent_signal *se,
231 bool *is_parent = talloc_get_type_abort(private_data, bool);
233 DEBUG(0,("Got sig[%d] terminate (is_parent=%d)\n",
234 signum, (int)*is_parent));
235 terminate(*is_parent);
239 handle stdin becoming readable when we are in --foreground mode
241 static void winbindd_stdin_handler(struct tevent_context *ev,
242 struct tevent_fd *fde,
247 if (read(0, &c, 1) != 1) {
248 bool *is_parent = talloc_get_type_abort(private_data, bool);
250 /* we have reached EOF on stdin, which means the
251 parent has exited. Shutdown the server */
252 DEBUG(0,("EOF on stdin (is_parent=%d)\n",
254 terminate(*is_parent);
258 bool winbindd_setup_sig_term_handler(bool parent)
260 struct tevent_signal *se;
263 is_parent = talloc(winbind_event_context(), bool);
270 se = tevent_add_signal(winbind_event_context(),
273 winbindd_sig_term_handler,
276 DEBUG(0,("failed to setup SIGTERM handler"));
277 talloc_free(is_parent);
281 se = tevent_add_signal(winbind_event_context(),
284 winbindd_sig_term_handler,
287 DEBUG(0,("failed to setup SIGINT handler"));
288 talloc_free(is_parent);
292 se = tevent_add_signal(winbind_event_context(),
295 winbindd_sig_term_handler,
298 DEBUG(0,("failed to setup SIGINT handler"));
299 talloc_free(is_parent);
306 bool winbindd_setup_stdin_handler(bool parent, bool foreground)
313 is_parent = talloc(winbind_event_context(), bool);
320 /* if we are running in the foreground then look for
321 EOF on stdin, and exit if it happens. This allows
322 us to die if the parent process dies
323 Only do this on a pipe or socket, no other device.
325 if (fstat(0, &st) != 0) {
328 if (S_ISFIFO(st.st_mode) || S_ISSOCK(st.st_mode)) {
329 tevent_add_fd(winbind_event_context(),
333 winbindd_stdin_handler,
341 static void winbindd_sig_hup_handler(struct tevent_context *ev,
342 struct tevent_signal *se,
348 const char *file = (const char *)private_data;
350 DEBUG(1,("Reloading services after SIGHUP\n"));
351 flush_caches_noinit();
352 reload_services_file(file);
355 bool winbindd_setup_sig_hup_handler(const char *lfile)
357 struct tevent_signal *se;
361 file = talloc_strdup(winbind_event_context(),
368 se = tevent_add_signal(winbind_event_context(),
369 winbind_event_context(),
371 winbindd_sig_hup_handler,
380 static void winbindd_sig_chld_handler(struct tevent_context *ev,
381 struct tevent_signal *se,
389 while ((pid = sys_waitpid(-1, NULL, WNOHANG)) > 0) {
390 winbind_child_died(pid);
394 static bool winbindd_setup_sig_chld_handler(void)
396 struct tevent_signal *se;
398 se = tevent_add_signal(winbind_event_context(),
399 winbind_event_context(),
401 winbindd_sig_chld_handler,
410 static void winbindd_sig_usr2_handler(struct tevent_context *ev,
411 struct tevent_signal *se,
420 static bool winbindd_setup_sig_usr2_handler(void)
422 struct tevent_signal *se;
424 se = tevent_add_signal(winbind_event_context(),
425 winbind_event_context(),
427 winbindd_sig_usr2_handler,
436 /* React on 'smbcontrol winbindd reload-config' in the same way as on SIGHUP*/
437 static void msg_reload_services(struct messaging_context *msg,
440 struct server_id server_id,
443 /* Flush various caches */
445 reload_services_file((const char *) private_data);
448 /* React on 'smbcontrol winbindd shutdown' in the same way as on SIGTERM*/
449 static void msg_shutdown(struct messaging_context *msg,
452 struct server_id server_id,
455 /* only the parent waits for this message */
456 DEBUG(0,("Got shutdown message\n"));
461 static void winbind_msg_validate_cache(struct messaging_context *msg_ctx,
464 struct server_id server_id,
471 DEBUG(10, ("winbindd_msg_validate_cache: got validate-cache "
475 * call the validation code from a child:
476 * so we don't block the main winbindd and the validation
477 * code can safely use fork/waitpid...
481 if (child_pid == -1) {
482 DEBUG(1, ("winbind_msg_validate_cache: Could not fork: %s\n",
487 if (child_pid != 0) {
489 DEBUG(5, ("winbind_msg_validate_cache: child created with "
490 "pid %d.\n", (int)child_pid));
496 status = winbindd_reinit_after_fork(NULL, NULL);
497 if (!NT_STATUS_IS_OK(status)) {
498 DEBUG(1, ("winbindd_reinit_after_fork failed: %s\n",
503 /* install default SIGCHLD handler: validation code uses fork/waitpid */
504 CatchSignal(SIGCHLD, SIG_DFL);
506 ret = (uint8)winbindd_validate_cache_nobackup();
507 DEBUG(10, ("winbindd_msg_validata_cache: got return value %d\n", ret));
508 messaging_send_buf(msg_ctx, server_id, MSG_WINBIND_VALIDATE_CACHE, &ret,
513 static struct winbindd_dispatch_table {
514 enum winbindd_cmd cmd;
515 void (*fn)(struct winbindd_cli_state *state);
516 const char *winbindd_cmd_name;
517 } dispatch_table[] = {
519 /* Enumeration functions */
521 { WINBINDD_LIST_TRUSTDOM, winbindd_list_trusted_domains,
526 { WINBINDD_INFO, winbindd_info, "INFO" },
527 { WINBINDD_INTERFACE_VERSION, winbindd_interface_version,
528 "INTERFACE_VERSION" },
529 { WINBINDD_DOMAIN_NAME, winbindd_domain_name, "DOMAIN_NAME" },
530 { WINBINDD_DOMAIN_INFO, winbindd_domain_info, "DOMAIN_INFO" },
531 { WINBINDD_DC_INFO, winbindd_dc_info, "DC_INFO" },
532 { WINBINDD_NETBIOS_NAME, winbindd_netbios_name, "NETBIOS_NAME" },
533 { WINBINDD_PRIV_PIPE_DIR, winbindd_priv_pipe_dir,
534 "WINBINDD_PRIV_PIPE_DIR" },
536 /* Credential cache access */
537 { WINBINDD_CCACHE_NTLMAUTH, winbindd_ccache_ntlm_auth, "NTLMAUTH" },
538 { WINBINDD_CCACHE_SAVE, winbindd_ccache_save, "CCACHE_SAVE" },
542 { WINBINDD_NUM_CMDS, NULL, "NONE" }
545 struct winbindd_async_dispatch_table {
546 enum winbindd_cmd cmd;
547 const char *cmd_name;
548 struct tevent_req *(*send_req)(TALLOC_CTX *mem_ctx,
549 struct tevent_context *ev,
550 struct winbindd_cli_state *cli,
551 struct winbindd_request *request);
552 NTSTATUS (*recv_req)(struct tevent_req *req,
553 struct winbindd_response *presp);
556 static struct winbindd_async_dispatch_table async_nonpriv_table[] = {
557 { WINBINDD_PING, "PING",
558 wb_ping_send, wb_ping_recv },
559 { WINBINDD_LOOKUPSID, "LOOKUPSID",
560 winbindd_lookupsid_send, winbindd_lookupsid_recv },
561 { WINBINDD_LOOKUPSIDS, "LOOKUPSIDS",
562 winbindd_lookupsids_send, winbindd_lookupsids_recv },
563 { WINBINDD_LOOKUPNAME, "LOOKUPNAME",
564 winbindd_lookupname_send, winbindd_lookupname_recv },
565 { WINBINDD_SID_TO_UID, "SID_TO_UID",
566 winbindd_sid_to_uid_send, winbindd_sid_to_uid_recv },
567 { WINBINDD_SID_TO_GID, "SID_TO_GID",
568 winbindd_sid_to_gid_send, winbindd_sid_to_gid_recv },
569 { WINBINDD_UID_TO_SID, "UID_TO_SID",
570 winbindd_uid_to_sid_send, winbindd_uid_to_sid_recv },
571 { WINBINDD_GID_TO_SID, "GID_TO_SID",
572 winbindd_gid_to_sid_send, winbindd_gid_to_sid_recv },
573 { WINBINDD_SIDS_TO_XIDS, "SIDS_TO_XIDS",
574 winbindd_sids_to_xids_send, winbindd_sids_to_xids_recv },
575 { WINBINDD_GETPWSID, "GETPWSID",
576 winbindd_getpwsid_send, winbindd_getpwsid_recv },
577 { WINBINDD_GETPWNAM, "GETPWNAM",
578 winbindd_getpwnam_send, winbindd_getpwnam_recv },
579 { WINBINDD_GETPWUID, "GETPWUID",
580 winbindd_getpwuid_send, winbindd_getpwuid_recv },
581 { WINBINDD_GETSIDALIASES, "GETSIDALIASES",
582 winbindd_getsidaliases_send, winbindd_getsidaliases_recv },
583 { WINBINDD_GETUSERDOMGROUPS, "GETUSERDOMGROUPS",
584 winbindd_getuserdomgroups_send, winbindd_getuserdomgroups_recv },
585 { WINBINDD_GETGROUPS, "GETGROUPS",
586 winbindd_getgroups_send, winbindd_getgroups_recv },
587 { WINBINDD_SHOW_SEQUENCE, "SHOW_SEQUENCE",
588 winbindd_show_sequence_send, winbindd_show_sequence_recv },
589 { WINBINDD_GETGRGID, "GETGRGID",
590 winbindd_getgrgid_send, winbindd_getgrgid_recv },
591 { WINBINDD_GETGRNAM, "GETGRNAM",
592 winbindd_getgrnam_send, winbindd_getgrnam_recv },
593 { WINBINDD_GETUSERSIDS, "GETUSERSIDS",
594 winbindd_getusersids_send, winbindd_getusersids_recv },
595 { WINBINDD_LOOKUPRIDS, "LOOKUPRIDS",
596 winbindd_lookuprids_send, winbindd_lookuprids_recv },
597 { WINBINDD_SETPWENT, "SETPWENT",
598 winbindd_setpwent_send, winbindd_setpwent_recv },
599 { WINBINDD_GETPWENT, "GETPWENT",
600 winbindd_getpwent_send, winbindd_getpwent_recv },
601 { WINBINDD_ENDPWENT, "ENDPWENT",
602 winbindd_endpwent_send, winbindd_endpwent_recv },
603 { WINBINDD_DSGETDCNAME, "DSGETDCNAME",
604 winbindd_dsgetdcname_send, winbindd_dsgetdcname_recv },
605 { WINBINDD_GETDCNAME, "GETDCNAME",
606 winbindd_getdcname_send, winbindd_getdcname_recv },
607 { WINBINDD_SETGRENT, "SETGRENT",
608 winbindd_setgrent_send, winbindd_setgrent_recv },
609 { WINBINDD_GETGRENT, "GETGRENT",
610 winbindd_getgrent_send, winbindd_getgrent_recv },
611 { WINBINDD_ENDGRENT, "ENDGRENT",
612 winbindd_endgrent_send, winbindd_endgrent_recv },
613 { WINBINDD_LIST_USERS, "LIST_USERS",
614 winbindd_list_users_send, winbindd_list_users_recv },
615 { WINBINDD_LIST_GROUPS, "LIST_GROUPS",
616 winbindd_list_groups_send, winbindd_list_groups_recv },
617 { WINBINDD_CHECK_MACHACC, "CHECK_MACHACC",
618 winbindd_check_machine_acct_send, winbindd_check_machine_acct_recv },
619 { WINBINDD_PING_DC, "PING_DC",
620 winbindd_ping_dc_send, winbindd_ping_dc_recv },
621 { WINBINDD_PAM_AUTH, "PAM_AUTH",
622 winbindd_pam_auth_send, winbindd_pam_auth_recv },
623 { WINBINDD_PAM_LOGOFF, "PAM_LOGOFF",
624 winbindd_pam_logoff_send, winbindd_pam_logoff_recv },
625 { WINBINDD_PAM_CHAUTHTOK, "PAM_CHAUTHTOK",
626 winbindd_pam_chauthtok_send, winbindd_pam_chauthtok_recv },
627 { WINBINDD_PAM_CHNG_PSWD_AUTH_CRAP, "PAM_CHNG_PSWD_AUTH_CRAP",
628 winbindd_pam_chng_pswd_auth_crap_send,
629 winbindd_pam_chng_pswd_auth_crap_recv },
630 { WINBINDD_WINS_BYIP, "WINS_BYIP",
631 winbindd_wins_byip_send, winbindd_wins_byip_recv },
632 { WINBINDD_WINS_BYNAME, "WINS_BYNAME",
633 winbindd_wins_byname_send, winbindd_wins_byname_recv },
635 { 0, NULL, NULL, NULL }
638 static struct winbindd_async_dispatch_table async_priv_table[] = {
639 { WINBINDD_ALLOCATE_UID, "ALLOCATE_UID",
640 winbindd_allocate_uid_send, winbindd_allocate_uid_recv },
641 { WINBINDD_ALLOCATE_GID, "ALLOCATE_GID",
642 winbindd_allocate_gid_send, winbindd_allocate_gid_recv },
643 { WINBINDD_CHANGE_MACHACC, "CHANGE_MACHACC",
644 winbindd_change_machine_acct_send, winbindd_change_machine_acct_recv },
645 { WINBINDD_PAM_AUTH_CRAP, "PAM_AUTH_CRAP",
646 winbindd_pam_auth_crap_send, winbindd_pam_auth_crap_recv },
648 { 0, NULL, NULL, NULL }
651 static void wb_request_done(struct tevent_req *req);
653 static void process_request(struct winbindd_cli_state *state)
655 struct winbindd_dispatch_table *table = dispatch_table;
656 struct winbindd_async_dispatch_table *atable;
658 state->mem_ctx = talloc_named(state, 0, "winbind request");
659 if (state->mem_ctx == NULL)
662 /* Remember who asked us. */
663 state->pid = state->request->pid;
665 state->cmd_name = "unknown request";
666 state->recv_fn = NULL;
667 state->last_access = time(NULL);
669 /* Process command */
671 for (atable = async_nonpriv_table; atable->send_req; atable += 1) {
672 if (state->request->cmd == atable->cmd) {
677 if ((atable->send_req == NULL) && state->privileged) {
678 for (atable = async_priv_table; atable->send_req;
680 if (state->request->cmd == atable->cmd) {
686 if (atable->send_req != NULL) {
687 struct tevent_req *req;
689 state->cmd_name = atable->cmd_name;
690 state->recv_fn = atable->recv_req;
692 DEBUG(10, ("process_request: Handling async request %d:%s\n",
693 (int)state->pid, state->cmd_name));
695 req = atable->send_req(state->mem_ctx, winbind_event_context(),
696 state, state->request);
698 DEBUG(0, ("process_request: atable->send failed for "
699 "%s\n", atable->cmd_name));
700 request_error(state);
703 tevent_req_set_callback(req, wb_request_done, state);
707 state->response = talloc_zero(state->mem_ctx,
708 struct winbindd_response);
709 if (state->response == NULL) {
710 DEBUG(10, ("talloc failed\n"));
711 remove_client(state);
714 state->response->result = WINBINDD_PENDING;
715 state->response->length = sizeof(struct winbindd_response);
717 for (table = dispatch_table; table->fn; table++) {
718 if (state->request->cmd == table->cmd) {
719 DEBUG(10,("process_request: request fn %s\n",
720 table->winbindd_cmd_name ));
721 state->cmd_name = table->winbindd_cmd_name;
728 DEBUG(10,("process_request: unknown request fn number %d\n",
729 (int)state->request->cmd ));
730 request_error(state);
734 static void wb_request_done(struct tevent_req *req)
736 struct winbindd_cli_state *state = tevent_req_callback_data(
737 req, struct winbindd_cli_state);
740 state->response = talloc_zero(state->mem_ctx,
741 struct winbindd_response);
742 if (state->response == NULL) {
743 DEBUG(0, ("wb_request_done[%d:%s]: talloc_zero failed - removing client\n",
744 (int)state->pid, state->cmd_name));
745 remove_client(state);
748 state->response->result = WINBINDD_PENDING;
749 state->response->length = sizeof(struct winbindd_response);
751 status = state->recv_fn(req, state->response);
754 DEBUG(10,("wb_request_done[%d:%s]: %s\n",
755 (int)state->pid, state->cmd_name, nt_errstr(status)));
757 if (!NT_STATUS_IS_OK(status)) {
758 request_error(state);
765 * This is the main event loop of winbind requests. It goes through a
766 * state-machine of 3 read/write requests, 4 if you have extra data to send.
768 * An idle winbind client has a read request of 4 bytes outstanding,
769 * finalizing function is request_len_recv, checking the length. request_recv
770 * then processes the packet. The processing function then at some point has
771 * to call request_finished which schedules sending the response.
774 static void request_finished(struct winbindd_cli_state *state);
776 static void winbind_client_request_read(struct tevent_req *req);
777 static void winbind_client_response_written(struct tevent_req *req);
779 static void request_finished(struct winbindd_cli_state *state)
781 struct tevent_req *req;
783 TALLOC_FREE(state->request);
785 req = wb_resp_write_send(state, winbind_event_context(),
786 state->out_queue, state->sock,
789 DEBUG(10,("request_finished[%d:%s]: wb_resp_write_send() failed\n",
790 (int)state->pid, state->cmd_name));
791 remove_client(state);
794 tevent_req_set_callback(req, winbind_client_response_written, state);
797 static void winbind_client_response_written(struct tevent_req *req)
799 struct winbindd_cli_state *state = tevent_req_callback_data(
800 req, struct winbindd_cli_state);
804 ret = wb_resp_write_recv(req, &err);
809 DEBUG(2, ("Could not write response[%d:%s] to client: %s\n",
810 (int)state->pid, state->cmd_name, strerror(err)));
811 remove_client(state);
815 DEBUG(10,("winbind_client_response_written[%d:%s]: delivered response "
816 "to client\n", (int)state->pid, state->cmd_name));
818 TALLOC_FREE(state->mem_ctx);
819 state->response = NULL;
820 state->cmd_name = "no request";
821 state->recv_fn = NULL;
823 req = wb_req_read_send(state, winbind_event_context(), state->sock,
824 WINBINDD_MAX_EXTRA_DATA);
826 remove_client(state);
829 tevent_req_set_callback(req, winbind_client_request_read, state);
832 void request_error(struct winbindd_cli_state *state)
834 SMB_ASSERT(state->response->result == WINBINDD_PENDING);
835 state->response->result = WINBINDD_ERROR;
836 request_finished(state);
839 void request_ok(struct winbindd_cli_state *state)
841 SMB_ASSERT(state->response->result == WINBINDD_PENDING);
842 state->response->result = WINBINDD_OK;
843 request_finished(state);
846 /* Process a new connection by adding it to the client connection list */
848 static void new_connection(int listen_sock, bool privileged)
850 struct sockaddr_un sunaddr;
851 struct winbindd_cli_state *state;
852 struct tevent_req *req;
856 /* Accept connection */
858 len = sizeof(sunaddr);
860 sock = accept(listen_sock, (struct sockaddr *)(void *)&sunaddr, &len);
863 if (errno != EINTR) {
864 DEBUG(0, ("Failed to accept socket - %s\n",
870 DEBUG(6,("accepted socket %d\n", sock));
872 /* Create new connection structure */
874 if ((state = talloc_zero(NULL, struct winbindd_cli_state)) == NULL) {
881 state->out_queue = tevent_queue_create(state, "winbind client reply");
882 if (state->out_queue == NULL) {
888 state->last_access = time(NULL);
890 state->privileged = privileged;
892 req = wb_req_read_send(state, winbind_event_context(), state->sock,
893 WINBINDD_MAX_EXTRA_DATA);
899 tevent_req_set_callback(req, winbind_client_request_read, state);
901 /* Add to connection list */
903 winbindd_add_client(state);
906 static void winbind_client_request_read(struct tevent_req *req)
908 struct winbindd_cli_state *state = tevent_req_callback_data(
909 req, struct winbindd_cli_state);
913 ret = wb_req_read_recv(req, state, &state->request, &err);
917 DEBUG(6, ("closing socket %d, client exited\n",
920 DEBUG(2, ("Could not read client request from fd %d: "
921 "%s\n", state->sock, strerror(err)));
925 remove_client(state);
928 process_request(state);
931 /* Remove a client connection from client connection list */
933 static void remove_client(struct winbindd_cli_state *state)
938 /* It's a dead client - hold a funeral */
944 if (state->sock != -1) {
945 /* tell client, we are closing ... */
946 nwritten = write(state->sock, &c, sizeof(c));
947 if (nwritten == -1) {
948 DEBUG(2, ("final write to client failed: %s\n",
958 TALLOC_FREE(state->mem_ctx);
960 /* Remove from list and free */
962 winbindd_remove_client(state);
966 /* Is a client idle? */
968 static bool client_is_idle(struct winbindd_cli_state *state) {
969 return (state->request == NULL &&
970 state->response == NULL &&
971 !state->pwent_state && !state->grent_state);
974 /* Shutdown client connection which has been idle for the longest time */
976 static bool remove_idle_client(void)
978 struct winbindd_cli_state *state, *remove_state = NULL;
979 time_t last_access = 0;
982 for (state = winbindd_client_list(); state; state = state->next) {
983 if (client_is_idle(state)) {
985 if (!last_access || state->last_access < last_access) {
986 last_access = state->last_access;
987 remove_state = state;
993 DEBUG(5,("Found %d idle client connections, shutting down sock %d, pid %u\n",
994 nidle, remove_state->sock, (unsigned int)remove_state->pid));
995 remove_client(remove_state);
1002 struct winbindd_listen_state {
1007 static void winbindd_listen_fde_handler(struct tevent_context *ev,
1008 struct tevent_fd *fde,
1012 struct winbindd_listen_state *s = talloc_get_type_abort(private_data,
1013 struct winbindd_listen_state);
1015 while (winbindd_num_clients() > lp_winbind_max_clients() - 1) {
1016 DEBUG(5,("winbindd: Exceeding %d client "
1017 "connections, removing idle "
1018 "connection.\n", lp_winbind_max_clients()));
1019 if (!remove_idle_client()) {
1020 DEBUG(0,("winbindd: Exceeding %d "
1021 "client connections, no idle "
1022 "connection found\n",
1023 lp_winbind_max_clients()));
1027 new_connection(s->fd, s->privileged);
1031 * Winbindd socket accessor functions
1034 const char *get_winbind_pipe_dir(void)
1036 return lp_parm_const_string(-1, "winbindd", "socket dir", get_dyn_WINBINDD_SOCKET_DIR());
1039 char *get_winbind_priv_pipe_dir(void)
1041 return state_path(WINBINDD_PRIV_SOCKET_SUBDIR);
1044 static bool winbindd_setup_listeners(void)
1046 struct winbindd_listen_state *pub_state = NULL;
1047 struct winbindd_listen_state *priv_state = NULL;
1048 struct tevent_fd *fde;
1051 pub_state = talloc(winbind_event_context(),
1052 struct winbindd_listen_state);
1057 pub_state->privileged = false;
1058 pub_state->fd = create_pipe_sock(
1059 get_winbind_pipe_dir(), WINBINDD_SOCKET_NAME, 0755);
1060 if (pub_state->fd == -1) {
1063 rc = listen(pub_state->fd, 5);
1068 fde = tevent_add_fd(winbind_event_context(), pub_state, pub_state->fd,
1069 TEVENT_FD_READ, winbindd_listen_fde_handler,
1072 close(pub_state->fd);
1075 tevent_fd_set_auto_close(fde);
1077 priv_state = talloc(winbind_event_context(),
1078 struct winbindd_listen_state);
1083 priv_state->privileged = true;
1084 priv_state->fd = create_pipe_sock(
1085 get_winbind_priv_pipe_dir(), WINBINDD_SOCKET_NAME, 0750);
1086 if (priv_state->fd == -1) {
1089 rc = listen(priv_state->fd, 5);
1094 fde = tevent_add_fd(winbind_event_context(), priv_state,
1095 priv_state->fd, TEVENT_FD_READ,
1096 winbindd_listen_fde_handler, priv_state);
1098 close(priv_state->fd);
1101 tevent_fd_set_auto_close(fde);
1105 TALLOC_FREE(pub_state);
1106 TALLOC_FREE(priv_state);
1110 bool winbindd_use_idmap_cache(void)
1112 return !opt_nocache;
1115 bool winbindd_use_cache(void)
1117 return !opt_nocache;
1120 static void winbindd_register_handlers(struct messaging_context *msg_ctx,
1123 /* Setup signal handlers */
1125 if (!winbindd_setup_sig_term_handler(true))
1127 if (!winbindd_setup_stdin_handler(true, foreground))
1129 if (!winbindd_setup_sig_hup_handler(NULL))
1131 if (!winbindd_setup_sig_chld_handler())
1133 if (!winbindd_setup_sig_usr2_handler())
1136 CatchSignal(SIGPIPE, SIG_IGN); /* Ignore sigpipe */
1139 * Ensure all cache and idmap caches are consistent
1140 * and initialized before we startup.
1142 if (!winbindd_cache_validate_and_initialize()) {
1146 /* get broadcast messages */
1148 if (!serverid_register(messaging_server_id(msg_ctx),
1152 DEBUG(1, ("Could not register myself in serverid.tdb\n"));
1156 /* React on 'smbcontrol winbindd reload-config' in the same way
1157 as to SIGHUP signal */
1158 messaging_register(msg_ctx, NULL,
1159 MSG_SMB_CONF_UPDATED, msg_reload_services);
1160 messaging_register(msg_ctx, NULL,
1161 MSG_SHUTDOWN, msg_shutdown);
1163 /* Handle online/offline messages. */
1164 messaging_register(msg_ctx, NULL,
1165 MSG_WINBIND_OFFLINE, winbind_msg_offline);
1166 messaging_register(msg_ctx, NULL,
1167 MSG_WINBIND_ONLINE, winbind_msg_online);
1168 messaging_register(msg_ctx, NULL,
1169 MSG_WINBIND_ONLINESTATUS, winbind_msg_onlinestatus);
1171 /* Handle domain online/offline messages for domains */
1172 messaging_register(winbind_messaging_context(), NULL,
1173 MSG_WINBIND_DOMAIN_OFFLINE, winbind_msg_domain_offline);
1174 messaging_register(winbind_messaging_context(), NULL,
1175 MSG_WINBIND_DOMAIN_ONLINE, winbind_msg_domain_online);
1177 messaging_register(msg_ctx, NULL,
1178 MSG_DUMP_EVENT_LIST, winbind_msg_dump_event_list);
1180 messaging_register(msg_ctx, NULL,
1181 MSG_WINBIND_VALIDATE_CACHE,
1182 winbind_msg_validate_cache);
1184 messaging_register(msg_ctx, NULL,
1185 MSG_WINBIND_DUMP_DOMAIN_LIST,
1186 winbind_msg_dump_domain_list);
1188 messaging_register(msg_ctx, NULL,
1189 MSG_WINBIND_IP_DROPPED,
1190 winbind_msg_ip_dropped_parent);
1192 /* Register handler for MSG_DEBUG. */
1193 messaging_register(msg_ctx, NULL,
1197 netsamlogon_cache_init(); /* Non-critical */
1199 /* clear the cached list of trusted domains */
1203 if (!init_domain_list()) {
1204 DEBUG(0,("unable to initialize domain list\n"));
1209 init_locator_child();
1211 smb_nscd_flush_user_cache();
1212 smb_nscd_flush_group_cache();
1214 if (lp_allow_trusted_domains()) {
1215 if (tevent_add_timer(winbind_event_context(), NULL, timeval_zero(),
1216 rescan_trusted_domains, NULL) == NULL) {
1217 DEBUG(0, ("Could not trigger rescan_trusted_domains()\n"));
1224 struct winbindd_addrchanged_state {
1225 struct addrchange_context *ctx;
1226 struct tevent_context *ev;
1227 struct messaging_context *msg_ctx;
1230 static void winbindd_addr_changed(struct tevent_req *req);
1232 static void winbindd_init_addrchange(TALLOC_CTX *mem_ctx,
1233 struct tevent_context *ev,
1234 struct messaging_context *msg_ctx)
1236 struct winbindd_addrchanged_state *state;
1237 struct tevent_req *req;
1240 state = talloc(mem_ctx, struct winbindd_addrchanged_state);
1241 if (state == NULL) {
1242 DEBUG(10, ("talloc failed\n"));
1246 state->msg_ctx = msg_ctx;
1248 status = addrchange_context_create(state, &state->ctx);
1249 if (!NT_STATUS_IS_OK(status)) {
1250 DEBUG(10, ("addrchange_context_create failed: %s\n",
1251 nt_errstr(status)));
1255 req = addrchange_send(state, ev, state->ctx);
1257 DEBUG(0, ("addrchange_send failed\n"));
1261 tevent_req_set_callback(req, winbindd_addr_changed, state);
1264 static void winbindd_addr_changed(struct tevent_req *req)
1266 struct winbindd_addrchanged_state *state = tevent_req_callback_data(
1267 req, struct winbindd_addrchanged_state);
1268 enum addrchange_type type;
1269 struct sockaddr_storage addr;
1272 status = addrchange_recv(req, &type, &addr);
1274 if (!NT_STATUS_IS_OK(status)) {
1275 DEBUG(10, ("addrchange_recv failed: %s, stop listening\n",
1276 nt_errstr(status)));
1280 if (type == ADDRCHANGE_DEL) {
1281 char addrstr[INET6_ADDRSTRLEN];
1284 print_sockaddr(addrstr, sizeof(addrstr), &addr);
1286 DEBUG(3, ("winbindd: kernel (AF_NETLINK) dropped ip %s\n",
1289 blob = data_blob_const(addrstr, strlen(addrstr)+1);
1291 status = messaging_send(state->msg_ctx,
1292 messaging_server_id(state->msg_ctx),
1293 MSG_WINBIND_IP_DROPPED, &blob);
1294 if (!NT_STATUS_IS_OK(status)) {
1295 DEBUG(10, ("messaging_send failed: %s - ignoring\n",
1296 nt_errstr(status)));
1299 req = addrchange_send(state, state->ev, state->ctx);
1301 DEBUG(0, ("addrchange_send failed\n"));
1305 tevent_req_set_callback(req, winbindd_addr_changed, state);
1310 int main(int argc, char **argv, char **envp)
1312 static bool is_daemon = False;
1313 static bool Fork = True;
1314 static bool log_stdout = False;
1315 static bool no_process_group = False;
1319 OPT_NO_PROCESS_GROUP,
1322 struct poptOption long_options[] = {
1324 { "stdout", 'S', POPT_ARG_NONE, NULL, OPT_LOG_STDOUT, "Log to stdout" },
1325 { "foreground", 'F', POPT_ARG_NONE, NULL, OPT_FORK, "Daemon in foreground mode" },
1326 { "no-process-group", 0, POPT_ARG_NONE, NULL, OPT_NO_PROCESS_GROUP, "Don't create a new process group" },
1327 { "daemon", 'D', POPT_ARG_NONE, NULL, OPT_DAEMON, "Become a daemon (default)" },
1328 { "interactive", 'i', POPT_ARG_NONE, NULL, 'i', "Interactive mode" },
1329 { "no-caching", 'n', POPT_ARG_NONE, NULL, 'n', "Disable caching" },
1340 * Do this before any other talloc operation
1342 talloc_enable_null_tracking();
1343 frame = talloc_stackframe();
1346 * We want total control over the permissions on created files,
1347 * so set our umask to 0.
1351 setup_logging("winbindd", DEBUG_DEFAULT_STDOUT);
1353 /* glibc (?) likes to print "User defined signal 1" and exit if a
1354 SIGUSR[12] is received before a handler is installed */
1356 CatchSignal(SIGUSR1, SIG_IGN);
1357 CatchSignal(SIGUSR2, SIG_IGN);
1360 dump_core_setup("winbindd", lp_logfile(talloc_tos()));
1364 /* Initialise for running in non-root mode */
1368 set_remote_machine_name("winbindd", False);
1370 /* Set environment variable so we don't recursively call ourselves.
1371 This may also be useful interactively. */
1373 if ( !winbind_off() ) {
1374 DEBUG(0,("Failed to disable recusive winbindd calls. Exiting.\n"));
1378 /* Initialise samba/rpc client stuff */
1380 pc = poptGetContext("winbindd", argc, (const char **)argv, long_options, 0);
1382 while ((opt = poptGetNextOpt(pc)) != -1) {
1384 /* Don't become a daemon */
1396 case OPT_NO_PROCESS_GROUP:
1397 no_process_group = true;
1399 case OPT_LOG_STDOUT:
1406 d_fprintf(stderr, "\nInvalid option %s: %s\n\n",
1407 poptBadOption(pc, 0), poptStrerror(opt));
1408 poptPrintUsage(pc, stderr, 0);
1413 /* We call dump_core_setup one more time because the command line can
1414 * set the log file or the log-basename and this will influence where
1415 * cores are stored. Without this call get_dyn_LOGFILEBASE will be
1416 * the default value derived from build's prefix. For EOM this value
1417 * is often not related to the path where winbindd is actually run
1420 dump_core_setup("winbindd", lp_logfile(talloc_tos()));
1421 if (is_daemon && interactive) {
1422 d_fprintf(stderr,"\nERROR: "
1423 "Option -i|--interactive is not allowed together with -D|--daemon\n\n");
1424 poptPrintUsage(pc, stderr, 0);
1428 if (log_stdout && Fork) {
1429 d_fprintf(stderr, "\nERROR: "
1430 "Can't log to stdout (-S) unless daemon is in foreground +(-F) or interactive (-i)\n\n");
1431 poptPrintUsage(pc, stderr, 0);
1435 poptFreeContext(pc);
1437 if (!override_logfile) {
1439 if (asprintf(&lfile,"%s/log.winbindd",
1440 get_dyn_LOGFILEBASE()) > 0) {
1441 lp_set_logfile(lfile);
1447 setup_logging("winbindd", DEBUG_STDOUT);
1449 setup_logging("winbindd", DEBUG_FILE);
1453 DEBUG(0,("winbindd version %s started.\n", samba_version_string()));
1454 DEBUGADD(0,("%s\n", COPYRIGHT_STARTUP_MESSAGE));
1456 if (!lp_load_initial_only(get_dyn_CONFIGFILE())) {
1457 DEBUG(0, ("error opening config file '%s'\n", get_dyn_CONFIGFILE()));
1460 /* After parsing the configuration file we setup the core path one more time
1461 * as the log file might have been set in the configuration and cores's
1462 * path is by default basename(lp_logfile()).
1464 dump_core_setup("winbindd", lp_logfile(talloc_tos()));
1466 if (lp_server_role() == ROLE_ACTIVE_DIRECTORY_DC) {
1467 DEBUG(0, ("server role = 'active directory domain controller' not compatible with running the winbindd binary. \n"));
1468 DEBUGADD(0, ("You should start 'samba' instead, and it will control starting the internal AD DC winbindd implementation, which is not the same as this one\n"));
1472 /* Initialise messaging system */
1474 if (winbind_messaging_context() == NULL) {
1478 if (!reload_services_file(NULL)) {
1479 DEBUG(0, ("error opening config file\n"));
1483 ok = directory_create_or_exist(lp_lockdir(), geteuid(), 0755);
1485 DEBUG(0, ("Failed to create directory %s for lock files - %s\n",
1486 lp_lockdir(), strerror(errno)));
1490 ok = directory_create_or_exist(lp_piddir(), geteuid(), 0755);
1492 DEBUG(0, ("Failed to create directory %s for pid files - %s\n",
1493 lp_piddir(), strerror(errno)));
1504 if (!secrets_init()) {
1506 DEBUG(0,("Could not initialize domain trust account secrets. Giving up\n"));
1510 /* Unblock all signals we are interested in as they may have been
1511 blocked by the parent process. */
1513 BlockSignals(False, SIGINT);
1514 BlockSignals(False, SIGQUIT);
1515 BlockSignals(False, SIGTERM);
1516 BlockSignals(False, SIGUSR1);
1517 BlockSignals(False, SIGUSR2);
1518 BlockSignals(False, SIGHUP);
1519 BlockSignals(False, SIGCHLD);
1522 become_daemon(Fork, no_process_group, log_stdout);
1524 pidfile_create(lp_piddir(), "winbindd");
1528 * If we're interactive we want to set our own process group for
1529 * signal management.
1531 if (interactive && !no_process_group)
1532 setpgid( (pid_t)0, (pid_t)0);
1537 /* Don't use winbindd_reinit_after_fork here as
1538 * we're just starting up and haven't created any
1539 * winbindd-specific resources we must free yet. JRA.
1542 status = reinit_after_fork(winbind_messaging_context(),
1543 winbind_event_context(),
1545 if (!NT_STATUS_IS_OK(status)) {
1546 DEBUG(0,("reinit_after_fork() failed\n"));
1551 * Do not initialize the parent-child-pipe before becoming
1552 * a daemon: this is used to detect a died parent in the child
1555 status = init_before_fork();
1556 if (!NT_STATUS_IS_OK(status)) {
1557 DEBUG(0, ("init_before_fork failed: %s\n", nt_errstr(status)));
1561 winbindd_register_handlers(winbind_messaging_context(), !Fork);
1563 status = init_system_session_info();
1564 if (!NT_STATUS_IS_OK(status)) {
1565 DEBUG(1, ("ERROR: failed to setup system user info: %s.\n",
1566 nt_errstr(status)));
1570 rpc_lsarpc_init(NULL);
1571 rpc_samr_init(NULL);
1573 winbindd_init_addrchange(NULL, winbind_event_context(),
1574 winbind_messaging_context());
1576 /* setup listen sockets */
1578 if (!winbindd_setup_listeners()) {
1579 DEBUG(0,("winbindd_setup_listeners() failed\n"));
1584 /* Loop waiting for requests */
1586 frame = talloc_stackframe();
1588 if (tevent_loop_once(winbind_event_context()) == -1) {
1589 DEBUG(1, ("tevent_loop_once() failed: %s\n",