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 messaging_context
*winbind_messaging_context(void)
54 struct messaging_context
*msg_ctx
= server_messaging_context();
55 if (likely(msg_ctx
!= NULL
)) {
58 smb_panic("Could not init winbindd's messaging context.\n");
62 /* Reload configuration */
64 static bool reload_services_file(const char *lfile
)
69 char *fname
= lp_configfile(talloc_tos());
71 if (file_exist(fname
) && !strcsequal(fname
,get_dyn_CONFIGFILE())) {
72 set_dyn_CONFIGFILE(fname
);
77 /* if this is a child, restore the logfile to the special
78 name - <domain>, idmap, etc. */
79 if (lfile
&& *lfile
) {
80 lp_set_logfile(lfile
);
84 ret
= lp_load_global(get_dyn_CONFIGFILE());
93 static void winbindd_status(void)
95 struct winbindd_cli_state
*tmp
;
97 DEBUG(0, ("winbindd status:\n"));
99 /* Print client state information */
101 DEBUG(0, ("\t%d clients currently active\n", winbindd_num_clients()));
103 if (DEBUGLEVEL
>= 2 && winbindd_num_clients()) {
104 DEBUG(2, ("\tclient list:\n"));
105 for(tmp
= winbindd_client_list(); tmp
; tmp
= tmp
->next
) {
106 DEBUGADD(2, ("\t\tpid %lu, sock %d (%s)\n",
107 (unsigned long)tmp
->pid
, tmp
->sock
,
108 client_is_idle(tmp
) ? "idle" : "active"));
113 /* Flush client cache */
115 static void flush_caches(void)
117 /* We need to invalidate cached user list entries on a SIGHUP
118 otherwise cached access denied errors due to restrict anonymous
119 hang around until the sequence number changes. */
121 if (!wcache_invalidate_cache()) {
122 DEBUG(0, ("invalidating the cache failed; revalidate the cache\n"));
123 if (!winbindd_cache_validate_and_initialize()) {
129 static void flush_caches_noinit(void)
132 * We need to invalidate cached user list entries on a SIGHUP
133 * otherwise cached access denied errors due to restrict anonymous
134 * hang around until the sequence number changes.
136 * Skip uninitialized domains when flush cache.
137 * If domain is not initialized, it means it is never
138 * used or never become online. look, wcache_invalidate_cache()
139 * -> get_cache() -> init_dc_connection(). It causes a lot of traffic
140 * for unused domains and large traffic for primay domain's DC if there
144 if (!wcache_invalidate_cache_noinit()) {
145 DEBUG(0, ("invalidating the cache failed; revalidate the cache\n"));
146 if (!winbindd_cache_validate_and_initialize()) {
152 /* Handle the signal by unlinking socket and exiting */
154 static void terminate(bool is_parent
)
157 /* When parent goes away we should
158 * remove the socket file. Not so
159 * when children terminate.
163 if (asprintf(&path
, "%s/%s",
164 get_winbind_pipe_dir(), WINBINDD_SOCKET_NAME
) > 0) {
172 trustdom_cache_shutdown();
174 gencache_stabilize();
178 TALLOC_CTX
*mem_ctx
= talloc_init("end_description");
179 char *description
= talloc_describe_all(mem_ctx
);
181 DEBUG(3, ("tallocs left:\n%s\n", description
));
182 talloc_destroy(mem_ctx
);
187 serverid_deregister(procid_self());
188 pidfile_unlink(lp_piddir(), "winbindd");
194 static void winbindd_sig_term_handler(struct tevent_context
*ev
,
195 struct tevent_signal
*se
,
201 bool *is_parent
= talloc_get_type_abort(private_data
, bool);
203 DEBUG(0,("Got sig[%d] terminate (is_parent=%d)\n",
204 signum
, (int)*is_parent
));
205 terminate(*is_parent
);
209 handle stdin becoming readable when we are in --foreground mode
211 static void winbindd_stdin_handler(struct tevent_context
*ev
,
212 struct tevent_fd
*fde
,
217 if (read(0, &c
, 1) != 1) {
218 bool *is_parent
= talloc_get_type_abort(private_data
, bool);
220 /* we have reached EOF on stdin, which means the
221 parent has exited. Shutdown the server */
222 DEBUG(0,("EOF on stdin (is_parent=%d)\n",
224 terminate(*is_parent
);
228 bool winbindd_setup_sig_term_handler(bool parent
)
230 struct tevent_signal
*se
;
233 is_parent
= talloc(winbind_event_context(), bool);
240 se
= tevent_add_signal(winbind_event_context(),
243 winbindd_sig_term_handler
,
246 DEBUG(0,("failed to setup SIGTERM handler"));
247 talloc_free(is_parent
);
251 se
= tevent_add_signal(winbind_event_context(),
254 winbindd_sig_term_handler
,
257 DEBUG(0,("failed to setup SIGINT handler"));
258 talloc_free(is_parent
);
262 se
= tevent_add_signal(winbind_event_context(),
265 winbindd_sig_term_handler
,
268 DEBUG(0,("failed to setup SIGINT handler"));
269 talloc_free(is_parent
);
276 bool winbindd_setup_stdin_handler(bool parent
, bool foreground
)
283 is_parent
= talloc(winbind_event_context(), bool);
290 /* if we are running in the foreground then look for
291 EOF on stdin, and exit if it happens. This allows
292 us to die if the parent process dies
293 Only do this on a pipe or socket, no other device.
295 if (fstat(0, &st
) != 0) {
298 if (S_ISFIFO(st
.st_mode
) || S_ISSOCK(st
.st_mode
)) {
299 tevent_add_fd(winbind_event_context(),
303 winbindd_stdin_handler
,
311 static void winbindd_sig_hup_handler(struct tevent_context
*ev
,
312 struct tevent_signal
*se
,
318 const char *file
= (const char *)private_data
;
320 DEBUG(1,("Reloading services after SIGHUP\n"));
321 flush_caches_noinit();
322 reload_services_file(file
);
325 bool winbindd_setup_sig_hup_handler(const char *lfile
)
327 struct tevent_signal
*se
;
331 file
= talloc_strdup(winbind_event_context(),
338 se
= tevent_add_signal(winbind_event_context(),
339 winbind_event_context(),
341 winbindd_sig_hup_handler
,
350 static void winbindd_sig_chld_handler(struct tevent_context
*ev
,
351 struct tevent_signal
*se
,
359 while ((pid
= sys_waitpid(-1, NULL
, WNOHANG
)) > 0) {
360 winbind_child_died(pid
);
364 static bool winbindd_setup_sig_chld_handler(void)
366 struct tevent_signal
*se
;
368 se
= tevent_add_signal(winbind_event_context(),
369 winbind_event_context(),
371 winbindd_sig_chld_handler
,
380 static void winbindd_sig_usr2_handler(struct tevent_context
*ev
,
381 struct tevent_signal
*se
,
390 static bool winbindd_setup_sig_usr2_handler(void)
392 struct tevent_signal
*se
;
394 se
= tevent_add_signal(winbind_event_context(),
395 winbind_event_context(),
397 winbindd_sig_usr2_handler
,
406 /* React on 'smbcontrol winbindd reload-config' in the same way as on SIGHUP*/
407 static void msg_reload_services(struct messaging_context
*msg
,
410 struct server_id server_id
,
413 /* Flush various caches */
415 reload_services_file((const char *) private_data
);
418 /* React on 'smbcontrol winbindd shutdown' in the same way as on SIGTERM*/
419 static void msg_shutdown(struct messaging_context
*msg
,
422 struct server_id server_id
,
425 /* only the parent waits for this message */
426 DEBUG(0,("Got shutdown message\n"));
431 static void winbind_msg_validate_cache(struct messaging_context
*msg_ctx
,
434 struct server_id server_id
,
441 DEBUG(10, ("winbindd_msg_validate_cache: got validate-cache "
445 * call the validation code from a child:
446 * so we don't block the main winbindd and the validation
447 * code can safely use fork/waitpid...
451 if (child_pid
== -1) {
452 DEBUG(1, ("winbind_msg_validate_cache: Could not fork: %s\n",
457 if (child_pid
!= 0) {
459 DEBUG(5, ("winbind_msg_validate_cache: child created with "
460 "pid %d.\n", (int)child_pid
));
466 status
= winbindd_reinit_after_fork(NULL
, NULL
);
467 if (!NT_STATUS_IS_OK(status
)) {
468 DEBUG(1, ("winbindd_reinit_after_fork failed: %s\n",
473 /* install default SIGCHLD handler: validation code uses fork/waitpid */
474 CatchSignal(SIGCHLD
, SIG_DFL
);
476 ret
= (uint8
)winbindd_validate_cache_nobackup();
477 DEBUG(10, ("winbindd_msg_validata_cache: got return value %d\n", ret
));
478 messaging_send_buf(msg_ctx
, server_id
, MSG_WINBIND_VALIDATE_CACHE
, &ret
,
483 static struct winbindd_dispatch_table
{
484 enum winbindd_cmd cmd
;
485 void (*fn
)(struct winbindd_cli_state
*state
);
486 const char *winbindd_cmd_name
;
487 } dispatch_table
[] = {
489 /* Enumeration functions */
491 { WINBINDD_LIST_TRUSTDOM
, winbindd_list_trusted_domains
,
496 { WINBINDD_INFO
, winbindd_info
, "INFO" },
497 { WINBINDD_INTERFACE_VERSION
, winbindd_interface_version
,
498 "INTERFACE_VERSION" },
499 { WINBINDD_DOMAIN_NAME
, winbindd_domain_name
, "DOMAIN_NAME" },
500 { WINBINDD_DOMAIN_INFO
, winbindd_domain_info
, "DOMAIN_INFO" },
501 { WINBINDD_DC_INFO
, winbindd_dc_info
, "DC_INFO" },
502 { WINBINDD_NETBIOS_NAME
, winbindd_netbios_name
, "NETBIOS_NAME" },
503 { WINBINDD_PRIV_PIPE_DIR
, winbindd_priv_pipe_dir
,
504 "WINBINDD_PRIV_PIPE_DIR" },
506 /* Credential cache access */
507 { WINBINDD_CCACHE_NTLMAUTH
, winbindd_ccache_ntlm_auth
, "NTLMAUTH" },
508 { WINBINDD_CCACHE_SAVE
, winbindd_ccache_save
, "CCACHE_SAVE" },
512 { WINBINDD_NUM_CMDS
, NULL
, "NONE" }
515 struct winbindd_async_dispatch_table
{
516 enum winbindd_cmd cmd
;
517 const char *cmd_name
;
518 struct tevent_req
*(*send_req
)(TALLOC_CTX
*mem_ctx
,
519 struct tevent_context
*ev
,
520 struct winbindd_cli_state
*cli
,
521 struct winbindd_request
*request
);
522 NTSTATUS (*recv_req
)(struct tevent_req
*req
,
523 struct winbindd_response
*presp
);
526 static struct winbindd_async_dispatch_table async_nonpriv_table
[] = {
527 { WINBINDD_PING
, "PING",
528 wb_ping_send
, wb_ping_recv
},
529 { WINBINDD_LOOKUPSID
, "LOOKUPSID",
530 winbindd_lookupsid_send
, winbindd_lookupsid_recv
},
531 { WINBINDD_LOOKUPSIDS
, "LOOKUPSIDS",
532 winbindd_lookupsids_send
, winbindd_lookupsids_recv
},
533 { WINBINDD_LOOKUPNAME
, "LOOKUPNAME",
534 winbindd_lookupname_send
, winbindd_lookupname_recv
},
535 { WINBINDD_SID_TO_UID
, "SID_TO_UID",
536 winbindd_sid_to_uid_send
, winbindd_sid_to_uid_recv
},
537 { WINBINDD_SID_TO_GID
, "SID_TO_GID",
538 winbindd_sid_to_gid_send
, winbindd_sid_to_gid_recv
},
539 { WINBINDD_UID_TO_SID
, "UID_TO_SID",
540 winbindd_uid_to_sid_send
, winbindd_uid_to_sid_recv
},
541 { WINBINDD_GID_TO_SID
, "GID_TO_SID",
542 winbindd_gid_to_sid_send
, winbindd_gid_to_sid_recv
},
543 { WINBINDD_SIDS_TO_XIDS
, "SIDS_TO_XIDS",
544 winbindd_sids_to_xids_send
, winbindd_sids_to_xids_recv
},
545 { WINBINDD_GETPWSID
, "GETPWSID",
546 winbindd_getpwsid_send
, winbindd_getpwsid_recv
},
547 { WINBINDD_GETPWNAM
, "GETPWNAM",
548 winbindd_getpwnam_send
, winbindd_getpwnam_recv
},
549 { WINBINDD_GETPWUID
, "GETPWUID",
550 winbindd_getpwuid_send
, winbindd_getpwuid_recv
},
551 { WINBINDD_GETSIDALIASES
, "GETSIDALIASES",
552 winbindd_getsidaliases_send
, winbindd_getsidaliases_recv
},
553 { WINBINDD_GETUSERDOMGROUPS
, "GETUSERDOMGROUPS",
554 winbindd_getuserdomgroups_send
, winbindd_getuserdomgroups_recv
},
555 { WINBINDD_GETGROUPS
, "GETGROUPS",
556 winbindd_getgroups_send
, winbindd_getgroups_recv
},
557 { WINBINDD_SHOW_SEQUENCE
, "SHOW_SEQUENCE",
558 winbindd_show_sequence_send
, winbindd_show_sequence_recv
},
559 { WINBINDD_GETGRGID
, "GETGRGID",
560 winbindd_getgrgid_send
, winbindd_getgrgid_recv
},
561 { WINBINDD_GETGRNAM
, "GETGRNAM",
562 winbindd_getgrnam_send
, winbindd_getgrnam_recv
},
563 { WINBINDD_GETUSERSIDS
, "GETUSERSIDS",
564 winbindd_getusersids_send
, winbindd_getusersids_recv
},
565 { WINBINDD_LOOKUPRIDS
, "LOOKUPRIDS",
566 winbindd_lookuprids_send
, winbindd_lookuprids_recv
},
567 { WINBINDD_SETPWENT
, "SETPWENT",
568 winbindd_setpwent_send
, winbindd_setpwent_recv
},
569 { WINBINDD_GETPWENT
, "GETPWENT",
570 winbindd_getpwent_send
, winbindd_getpwent_recv
},
571 { WINBINDD_ENDPWENT
, "ENDPWENT",
572 winbindd_endpwent_send
, winbindd_endpwent_recv
},
573 { WINBINDD_DSGETDCNAME
, "DSGETDCNAME",
574 winbindd_dsgetdcname_send
, winbindd_dsgetdcname_recv
},
575 { WINBINDD_GETDCNAME
, "GETDCNAME",
576 winbindd_getdcname_send
, winbindd_getdcname_recv
},
577 { WINBINDD_SETGRENT
, "SETGRENT",
578 winbindd_setgrent_send
, winbindd_setgrent_recv
},
579 { WINBINDD_GETGRENT
, "GETGRENT",
580 winbindd_getgrent_send
, winbindd_getgrent_recv
},
581 { WINBINDD_ENDGRENT
, "ENDGRENT",
582 winbindd_endgrent_send
, winbindd_endgrent_recv
},
583 { WINBINDD_LIST_USERS
, "LIST_USERS",
584 winbindd_list_users_send
, winbindd_list_users_recv
},
585 { WINBINDD_LIST_GROUPS
, "LIST_GROUPS",
586 winbindd_list_groups_send
, winbindd_list_groups_recv
},
587 { WINBINDD_CHECK_MACHACC
, "CHECK_MACHACC",
588 winbindd_check_machine_acct_send
, winbindd_check_machine_acct_recv
},
589 { WINBINDD_PING_DC
, "PING_DC",
590 winbindd_ping_dc_send
, winbindd_ping_dc_recv
},
591 { WINBINDD_PAM_AUTH
, "PAM_AUTH",
592 winbindd_pam_auth_send
, winbindd_pam_auth_recv
},
593 { WINBINDD_PAM_LOGOFF
, "PAM_LOGOFF",
594 winbindd_pam_logoff_send
, winbindd_pam_logoff_recv
},
595 { WINBINDD_PAM_CHAUTHTOK
, "PAM_CHAUTHTOK",
596 winbindd_pam_chauthtok_send
, winbindd_pam_chauthtok_recv
},
597 { WINBINDD_PAM_CHNG_PSWD_AUTH_CRAP
, "PAM_CHNG_PSWD_AUTH_CRAP",
598 winbindd_pam_chng_pswd_auth_crap_send
,
599 winbindd_pam_chng_pswd_auth_crap_recv
},
600 { WINBINDD_WINS_BYIP
, "WINS_BYIP",
601 winbindd_wins_byip_send
, winbindd_wins_byip_recv
},
602 { WINBINDD_WINS_BYNAME
, "WINS_BYNAME",
603 winbindd_wins_byname_send
, winbindd_wins_byname_recv
},
605 { 0, NULL
, NULL
, NULL
}
608 static struct winbindd_async_dispatch_table async_priv_table
[] = {
609 { WINBINDD_ALLOCATE_UID
, "ALLOCATE_UID",
610 winbindd_allocate_uid_send
, winbindd_allocate_uid_recv
},
611 { WINBINDD_ALLOCATE_GID
, "ALLOCATE_GID",
612 winbindd_allocate_gid_send
, winbindd_allocate_gid_recv
},
613 { WINBINDD_CHANGE_MACHACC
, "CHANGE_MACHACC",
614 winbindd_change_machine_acct_send
, winbindd_change_machine_acct_recv
},
615 { WINBINDD_PAM_AUTH_CRAP
, "PAM_AUTH_CRAP",
616 winbindd_pam_auth_crap_send
, winbindd_pam_auth_crap_recv
},
618 { 0, NULL
, NULL
, NULL
}
621 static void wb_request_done(struct tevent_req
*req
);
623 static void process_request(struct winbindd_cli_state
*state
)
625 struct winbindd_dispatch_table
*table
= dispatch_table
;
626 struct winbindd_async_dispatch_table
*atable
;
628 state
->mem_ctx
= talloc_named(state
, 0, "winbind request");
629 if (state
->mem_ctx
== NULL
)
632 /* Remember who asked us. */
633 state
->pid
= state
->request
->pid
;
635 state
->cmd_name
= "unknown request";
636 state
->recv_fn
= NULL
;
637 state
->last_access
= time(NULL
);
639 /* Process command */
641 for (atable
= async_nonpriv_table
; atable
->send_req
; atable
+= 1) {
642 if (state
->request
->cmd
== atable
->cmd
) {
647 if ((atable
->send_req
== NULL
) && state
->privileged
) {
648 for (atable
= async_priv_table
; atable
->send_req
;
650 if (state
->request
->cmd
== atable
->cmd
) {
656 if (atable
->send_req
!= NULL
) {
657 struct tevent_req
*req
;
659 state
->cmd_name
= atable
->cmd_name
;
660 state
->recv_fn
= atable
->recv_req
;
662 DEBUG(10, ("process_request: Handling async request %d:%s\n",
663 (int)state
->pid
, state
->cmd_name
));
665 req
= atable
->send_req(state
->mem_ctx
, winbind_event_context(),
666 state
, state
->request
);
668 DEBUG(0, ("process_request: atable->send failed for "
669 "%s\n", atable
->cmd_name
));
670 request_error(state
);
673 tevent_req_set_callback(req
, wb_request_done
, state
);
677 state
->response
= talloc_zero(state
->mem_ctx
,
678 struct winbindd_response
);
679 if (state
->response
== NULL
) {
680 DEBUG(10, ("talloc failed\n"));
681 remove_client(state
);
684 state
->response
->result
= WINBINDD_PENDING
;
685 state
->response
->length
= sizeof(struct winbindd_response
);
687 for (table
= dispatch_table
; table
->fn
; table
++) {
688 if (state
->request
->cmd
== table
->cmd
) {
689 DEBUG(10,("process_request: request fn %s\n",
690 table
->winbindd_cmd_name
));
691 state
->cmd_name
= table
->winbindd_cmd_name
;
698 DEBUG(10,("process_request: unknown request fn number %d\n",
699 (int)state
->request
->cmd
));
700 request_error(state
);
704 static void wb_request_done(struct tevent_req
*req
)
706 struct winbindd_cli_state
*state
= tevent_req_callback_data(
707 req
, struct winbindd_cli_state
);
710 state
->response
= talloc_zero(state
->mem_ctx
,
711 struct winbindd_response
);
712 if (state
->response
== NULL
) {
713 DEBUG(0, ("wb_request_done[%d:%s]: talloc_zero failed - removing client\n",
714 (int)state
->pid
, state
->cmd_name
));
715 remove_client(state
);
718 state
->response
->result
= WINBINDD_PENDING
;
719 state
->response
->length
= sizeof(struct winbindd_response
);
721 status
= state
->recv_fn(req
, state
->response
);
724 DEBUG(10,("wb_request_done[%d:%s]: %s\n",
725 (int)state
->pid
, state
->cmd_name
, nt_errstr(status
)));
727 if (!NT_STATUS_IS_OK(status
)) {
728 request_error(state
);
735 * This is the main event loop of winbind requests. It goes through a
736 * state-machine of 3 read/write requests, 4 if you have extra data to send.
738 * An idle winbind client has a read request of 4 bytes outstanding,
739 * finalizing function is request_len_recv, checking the length. request_recv
740 * then processes the packet. The processing function then at some point has
741 * to call request_finished which schedules sending the response.
744 static void request_finished(struct winbindd_cli_state
*state
);
746 static void winbind_client_request_read(struct tevent_req
*req
);
747 static void winbind_client_response_written(struct tevent_req
*req
);
749 static void request_finished(struct winbindd_cli_state
*state
)
751 struct tevent_req
*req
;
753 TALLOC_FREE(state
->request
);
755 req
= wb_resp_write_send(state
, winbind_event_context(),
756 state
->out_queue
, state
->sock
,
759 DEBUG(10,("request_finished[%d:%s]: wb_resp_write_send() failed\n",
760 (int)state
->pid
, state
->cmd_name
));
761 remove_client(state
);
764 tevent_req_set_callback(req
, winbind_client_response_written
, state
);
767 static void winbind_client_response_written(struct tevent_req
*req
)
769 struct winbindd_cli_state
*state
= tevent_req_callback_data(
770 req
, struct winbindd_cli_state
);
774 ret
= wb_resp_write_recv(req
, &err
);
779 DEBUG(2, ("Could not write response[%d:%s] to client: %s\n",
780 (int)state
->pid
, state
->cmd_name
, strerror(err
)));
781 remove_client(state
);
785 DEBUG(10,("winbind_client_response_written[%d:%s]: delivered response "
786 "to client\n", (int)state
->pid
, state
->cmd_name
));
788 TALLOC_FREE(state
->mem_ctx
);
789 state
->response
= NULL
;
790 state
->cmd_name
= "no request";
791 state
->recv_fn
= NULL
;
793 req
= wb_req_read_send(state
, winbind_event_context(), state
->sock
,
794 WINBINDD_MAX_EXTRA_DATA
);
796 remove_client(state
);
799 tevent_req_set_callback(req
, winbind_client_request_read
, state
);
802 void request_error(struct winbindd_cli_state
*state
)
804 SMB_ASSERT(state
->response
->result
== WINBINDD_PENDING
);
805 state
->response
->result
= WINBINDD_ERROR
;
806 request_finished(state
);
809 void request_ok(struct winbindd_cli_state
*state
)
811 SMB_ASSERT(state
->response
->result
== WINBINDD_PENDING
);
812 state
->response
->result
= WINBINDD_OK
;
813 request_finished(state
);
816 /* Process a new connection by adding it to the client connection list */
818 static void new_connection(int listen_sock
, bool privileged
)
820 struct sockaddr_un sunaddr
;
821 struct winbindd_cli_state
*state
;
822 struct tevent_req
*req
;
826 /* Accept connection */
828 len
= sizeof(sunaddr
);
830 sock
= accept(listen_sock
, (struct sockaddr
*)(void *)&sunaddr
, &len
);
833 if (errno
!= EINTR
) {
834 DEBUG(0, ("Faild to accept socket - %s\n",
840 DEBUG(6,("accepted socket %d\n", sock
));
842 /* Create new connection structure */
844 if ((state
= talloc_zero(NULL
, struct winbindd_cli_state
)) == NULL
) {
851 state
->out_queue
= tevent_queue_create(state
, "winbind client reply");
852 if (state
->out_queue
== NULL
) {
858 state
->last_access
= time(NULL
);
860 state
->privileged
= privileged
;
862 req
= wb_req_read_send(state
, winbind_event_context(), state
->sock
,
863 WINBINDD_MAX_EXTRA_DATA
);
869 tevent_req_set_callback(req
, winbind_client_request_read
, state
);
871 /* Add to connection list */
873 winbindd_add_client(state
);
876 static void winbind_client_request_read(struct tevent_req
*req
)
878 struct winbindd_cli_state
*state
= tevent_req_callback_data(
879 req
, struct winbindd_cli_state
);
883 ret
= wb_req_read_recv(req
, state
, &state
->request
, &err
);
887 DEBUG(6, ("closing socket %d, client exited\n",
890 DEBUG(2, ("Could not read client request from fd %d: "
891 "%s\n", state
->sock
, strerror(err
)));
895 remove_client(state
);
898 process_request(state
);
901 /* Remove a client connection from client connection list */
903 static void remove_client(struct winbindd_cli_state
*state
)
908 /* It's a dead client - hold a funeral */
914 if (state
->sock
!= -1) {
915 /* tell client, we are closing ... */
916 nwritten
= write(state
->sock
, &c
, sizeof(c
));
917 if (nwritten
== -1) {
918 DEBUG(2, ("final write to client failed: %s\n",
928 TALLOC_FREE(state
->mem_ctx
);
930 /* Remove from list and free */
932 winbindd_remove_client(state
);
936 /* Is a client idle? */
938 static bool client_is_idle(struct winbindd_cli_state
*state
) {
939 return (state
->request
== NULL
&&
940 state
->response
== NULL
&&
941 !state
->pwent_state
&& !state
->grent_state
);
944 /* Shutdown client connection which has been idle for the longest time */
946 static bool remove_idle_client(void)
948 struct winbindd_cli_state
*state
, *remove_state
= NULL
;
949 time_t last_access
= 0;
952 for (state
= winbindd_client_list(); state
; state
= state
->next
) {
953 if (client_is_idle(state
)) {
955 if (!last_access
|| state
->last_access
< last_access
) {
956 last_access
= state
->last_access
;
957 remove_state
= state
;
963 DEBUG(5,("Found %d idle client connections, shutting down sock %d, pid %u\n",
964 nidle
, remove_state
->sock
, (unsigned int)remove_state
->pid
));
965 remove_client(remove_state
);
972 struct winbindd_listen_state
{
977 static void winbindd_listen_fde_handler(struct tevent_context
*ev
,
978 struct tevent_fd
*fde
,
982 struct winbindd_listen_state
*s
= talloc_get_type_abort(private_data
,
983 struct winbindd_listen_state
);
985 while (winbindd_num_clients() > lp_winbind_max_clients() - 1) {
986 DEBUG(5,("winbindd: Exceeding %d client "
987 "connections, removing idle "
988 "connection.\n", lp_winbind_max_clients()));
989 if (!remove_idle_client()) {
990 DEBUG(0,("winbindd: Exceeding %d "
991 "client connections, no idle "
992 "connection found\n",
993 lp_winbind_max_clients()));
997 new_connection(s
->fd
, s
->privileged
);
1001 * Winbindd socket accessor functions
1004 const char *get_winbind_pipe_dir(void)
1006 return lp_parm_const_string(-1, "winbindd", "socket dir", get_dyn_WINBINDD_SOCKET_DIR());
1009 char *get_winbind_priv_pipe_dir(void)
1011 return state_path(WINBINDD_PRIV_SOCKET_SUBDIR
);
1014 static bool winbindd_setup_listeners(void)
1016 struct winbindd_listen_state
*pub_state
= NULL
;
1017 struct winbindd_listen_state
*priv_state
= NULL
;
1018 struct tevent_fd
*fde
;
1021 pub_state
= talloc(winbind_event_context(),
1022 struct winbindd_listen_state
);
1027 pub_state
->privileged
= false;
1028 pub_state
->fd
= create_pipe_sock(
1029 get_winbind_pipe_dir(), WINBINDD_SOCKET_NAME
, 0755);
1030 if (pub_state
->fd
== -1) {
1033 rc
= listen(pub_state
->fd
, 5);
1038 fde
= tevent_add_fd(winbind_event_context(), pub_state
, pub_state
->fd
,
1039 TEVENT_FD_READ
, winbindd_listen_fde_handler
,
1042 close(pub_state
->fd
);
1045 tevent_fd_set_auto_close(fde
);
1047 priv_state
= talloc(winbind_event_context(),
1048 struct winbindd_listen_state
);
1053 priv_state
->privileged
= true;
1054 priv_state
->fd
= create_pipe_sock(
1055 get_winbind_priv_pipe_dir(), WINBINDD_SOCKET_NAME
, 0750);
1056 if (priv_state
->fd
== -1) {
1059 rc
= listen(priv_state
->fd
, 5);
1064 fde
= tevent_add_fd(winbind_event_context(), priv_state
,
1065 priv_state
->fd
, TEVENT_FD_READ
,
1066 winbindd_listen_fde_handler
, priv_state
);
1068 close(priv_state
->fd
);
1071 tevent_fd_set_auto_close(fde
);
1075 TALLOC_FREE(pub_state
);
1076 TALLOC_FREE(priv_state
);
1080 bool winbindd_use_idmap_cache(void)
1082 return !opt_nocache
;
1085 bool winbindd_use_cache(void)
1087 return !opt_nocache
;
1090 void winbindd_register_handlers(bool foreground
)
1092 /* Setup signal handlers */
1094 if (!winbindd_setup_sig_term_handler(true))
1096 if (!winbindd_setup_stdin_handler(true, foreground
))
1098 if (!winbindd_setup_sig_hup_handler(NULL
))
1100 if (!winbindd_setup_sig_chld_handler())
1102 if (!winbindd_setup_sig_usr2_handler())
1105 CatchSignal(SIGPIPE
, SIG_IGN
); /* Ignore sigpipe */
1108 * Ensure all cache and idmap caches are consistent
1109 * and initialized before we startup.
1111 if (!winbindd_cache_validate_and_initialize()) {
1115 /* get broadcast messages */
1117 if (!serverid_register(procid_self(),
1121 DEBUG(1, ("Could not register myself in serverid.tdb\n"));
1125 /* React on 'smbcontrol winbindd reload-config' in the same way
1126 as to SIGHUP signal */
1127 messaging_register(winbind_messaging_context(), NULL
,
1128 MSG_SMB_CONF_UPDATED
, msg_reload_services
);
1129 messaging_register(winbind_messaging_context(), NULL
,
1130 MSG_SHUTDOWN
, msg_shutdown
);
1132 /* Handle online/offline messages. */
1133 messaging_register(winbind_messaging_context(), NULL
,
1134 MSG_WINBIND_OFFLINE
, winbind_msg_offline
);
1135 messaging_register(winbind_messaging_context(), NULL
,
1136 MSG_WINBIND_ONLINE
, winbind_msg_online
);
1137 messaging_register(winbind_messaging_context(), NULL
,
1138 MSG_WINBIND_ONLINESTATUS
, winbind_msg_onlinestatus
);
1140 /* Handle domain online/offline messages for domains */
1141 messaging_register(winbind_messaging_context(), NULL
,
1142 MSG_WINBIND_DOMAIN_OFFLINE
, winbind_msg_domain_offline
);
1143 messaging_register(winbind_messaging_context(), NULL
,
1144 MSG_WINBIND_DOMAIN_ONLINE
, winbind_msg_domain_online
);
1146 messaging_register(winbind_messaging_context(), NULL
,
1147 MSG_DUMP_EVENT_LIST
, winbind_msg_dump_event_list
);
1149 messaging_register(winbind_messaging_context(), NULL
,
1150 MSG_WINBIND_VALIDATE_CACHE
,
1151 winbind_msg_validate_cache
);
1153 messaging_register(winbind_messaging_context(), NULL
,
1154 MSG_WINBIND_DUMP_DOMAIN_LIST
,
1155 winbind_msg_dump_domain_list
);
1157 messaging_register(winbind_messaging_context(), NULL
,
1158 MSG_WINBIND_IP_DROPPED
,
1159 winbind_msg_ip_dropped_parent
);
1161 /* Register handler for MSG_DEBUG. */
1162 messaging_register(winbind_messaging_context(), NULL
,
1166 netsamlogon_cache_init(); /* Non-critical */
1168 /* clear the cached list of trusted domains */
1172 if (!init_domain_list()) {
1173 DEBUG(0,("unable to initialize domain list\n"));
1178 init_locator_child();
1180 smb_nscd_flush_user_cache();
1181 smb_nscd_flush_group_cache();
1183 if (lp_allow_trusted_domains()) {
1184 if (tevent_add_timer(winbind_event_context(), NULL
, timeval_zero(),
1185 rescan_trusted_domains
, NULL
) == NULL
) {
1186 DEBUG(0, ("Could not trigger rescan_trusted_domains()\n"));
1193 struct winbindd_addrchanged_state
{
1194 struct addrchange_context
*ctx
;
1195 struct tevent_context
*ev
;
1196 struct messaging_context
*msg_ctx
;
1199 static void winbindd_addr_changed(struct tevent_req
*req
);
1201 static void winbindd_init_addrchange(TALLOC_CTX
*mem_ctx
,
1202 struct tevent_context
*ev
,
1203 struct messaging_context
*msg_ctx
)
1205 struct winbindd_addrchanged_state
*state
;
1206 struct tevent_req
*req
;
1209 state
= talloc(mem_ctx
, struct winbindd_addrchanged_state
);
1210 if (state
== NULL
) {
1211 DEBUG(10, ("talloc failed\n"));
1215 state
->msg_ctx
= msg_ctx
;
1217 status
= addrchange_context_create(state
, &state
->ctx
);
1218 if (!NT_STATUS_IS_OK(status
)) {
1219 DEBUG(10, ("addrchange_context_create failed: %s\n",
1220 nt_errstr(status
)));
1224 req
= addrchange_send(state
, ev
, state
->ctx
);
1226 DEBUG(0, ("addrchange_send failed\n"));
1230 tevent_req_set_callback(req
, winbindd_addr_changed
, state
);
1233 static void winbindd_addr_changed(struct tevent_req
*req
)
1235 struct winbindd_addrchanged_state
*state
= tevent_req_callback_data(
1236 req
, struct winbindd_addrchanged_state
);
1237 enum addrchange_type type
;
1238 struct sockaddr_storage addr
;
1241 status
= addrchange_recv(req
, &type
, &addr
);
1243 if (!NT_STATUS_IS_OK(status
)) {
1244 DEBUG(10, ("addrchange_recv failed: %s, stop listening\n",
1245 nt_errstr(status
)));
1249 if (type
== ADDRCHANGE_DEL
) {
1250 char addrstr
[INET6_ADDRSTRLEN
];
1253 print_sockaddr(addrstr
, sizeof(addrstr
), &addr
);
1255 DEBUG(3, ("winbindd: kernel (AF_NETLINK) dropped ip %s\n",
1258 blob
= data_blob_const(addrstr
, strlen(addrstr
)+1);
1260 status
= messaging_send(state
->msg_ctx
,
1261 messaging_server_id(state
->msg_ctx
),
1262 MSG_WINBIND_IP_DROPPED
, &blob
);
1263 if (!NT_STATUS_IS_OK(status
)) {
1264 DEBUG(10, ("messaging_send failed: %s - ignoring\n",
1265 nt_errstr(status
)));
1268 req
= addrchange_send(state
, state
->ev
, state
->ctx
);
1270 DEBUG(0, ("addrchange_send failed\n"));
1274 tevent_req_set_callback(req
, winbindd_addr_changed
, state
);
1279 int main(int argc
, char **argv
, char **envp
)
1281 static bool is_daemon
= False
;
1282 static bool Fork
= True
;
1283 static bool log_stdout
= False
;
1284 static bool no_process_group
= False
;
1288 OPT_NO_PROCESS_GROUP
,
1291 struct poptOption long_options
[] = {
1293 { "stdout", 'S', POPT_ARG_NONE
, NULL
, OPT_LOG_STDOUT
, "Log to stdout" },
1294 { "foreground", 'F', POPT_ARG_NONE
, NULL
, OPT_FORK
, "Daemon in foreground mode" },
1295 { "no-process-group", 0, POPT_ARG_NONE
, NULL
, OPT_NO_PROCESS_GROUP
, "Don't create a new process group" },
1296 { "daemon", 'D', POPT_ARG_NONE
, NULL
, OPT_DAEMON
, "Become a daemon (default)" },
1297 { "interactive", 'i', POPT_ARG_NONE
, NULL
, 'i', "Interactive mode" },
1298 { "no-caching", 'n', POPT_ARG_NONE
, NULL
, 'n', "Disable caching" },
1308 * Do this before any other talloc operation
1310 talloc_enable_null_tracking();
1311 frame
= talloc_stackframe();
1313 setup_logging("winbindd", DEBUG_DEFAULT_STDOUT
);
1315 /* glibc (?) likes to print "User defined signal 1" and exit if a
1316 SIGUSR[12] is received before a handler is installed */
1318 CatchSignal(SIGUSR1
, SIG_IGN
);
1319 CatchSignal(SIGUSR2
, SIG_IGN
);
1322 dump_core_setup("winbindd", lp_logfile(talloc_tos()));
1326 /* Initialise for running in non-root mode */
1330 set_remote_machine_name("winbindd", False
);
1332 /* Set environment variable so we don't recursively call ourselves.
1333 This may also be useful interactively. */
1335 if ( !winbind_off() ) {
1336 DEBUG(0,("Failed to disable recusive winbindd calls. Exiting.\n"));
1340 /* Initialise samba/rpc client stuff */
1342 pc
= poptGetContext("winbindd", argc
, (const char **)argv
, long_options
, 0);
1344 while ((opt
= poptGetNextOpt(pc
)) != -1) {
1346 /* Don't become a daemon */
1358 case OPT_NO_PROCESS_GROUP
:
1359 no_process_group
= true;
1361 case OPT_LOG_STDOUT
:
1368 d_fprintf(stderr
, "\nInvalid option %s: %s\n\n",
1369 poptBadOption(pc
, 0), poptStrerror(opt
));
1370 poptPrintUsage(pc
, stderr
, 0);
1375 /* We call dump_core_setup one more time because the command line can
1376 * set the log file or the log-basename and this will influence where
1377 * cores are stored. Without this call get_dyn_LOGFILEBASE will be
1378 * the default value derived from build's prefix. For EOM this value
1379 * is often not related to the path where winbindd is actually run
1382 dump_core_setup("winbindd", lp_logfile(talloc_tos()));
1383 if (is_daemon
&& interactive
) {
1384 d_fprintf(stderr
,"\nERROR: "
1385 "Option -i|--interactive is not allowed together with -D|--daemon\n\n");
1386 poptPrintUsage(pc
, stderr
, 0);
1390 if (log_stdout
&& Fork
) {
1391 d_fprintf(stderr
, "\nERROR: "
1392 "Can't log to stdout (-S) unless daemon is in foreground +(-F) or interactive (-i)\n\n");
1393 poptPrintUsage(pc
, stderr
, 0);
1397 poptFreeContext(pc
);
1399 if (!override_logfile
) {
1401 if (asprintf(&lfile
,"%s/log.winbindd",
1402 get_dyn_LOGFILEBASE()) > 0) {
1403 lp_set_logfile(lfile
);
1409 setup_logging("winbindd", DEBUG_STDOUT
);
1411 setup_logging("winbindd", DEBUG_FILE
);
1415 DEBUG(0,("winbindd version %s started.\n", samba_version_string()));
1416 DEBUGADD(0,("%s\n", COPYRIGHT_STARTUP_MESSAGE
));
1418 if (!lp_load_initial_only(get_dyn_CONFIGFILE())) {
1419 DEBUG(0, ("error opening config file '%s'\n", get_dyn_CONFIGFILE()));
1422 /* After parsing the configuration file we setup the core path one more time
1423 * as the log file might have been set in the configuration and cores's
1424 * path is by default basename(lp_logfile()).
1426 dump_core_setup("winbindd", lp_logfile(talloc_tos()));
1428 if (lp_server_role() == ROLE_ACTIVE_DIRECTORY_DC
) {
1429 DEBUG(0, ("server role = 'active directory domain controller' not compatible with running the winbindd binary. \n"));
1430 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"));
1434 /* Initialise messaging system */
1436 if (winbind_messaging_context() == NULL
) {
1440 if (!reload_services_file(NULL
)) {
1441 DEBUG(0, ("error opening config file\n"));
1445 if (!directory_exist(lp_lockdir())) {
1446 mkdir(lp_lockdir(), 0755);
1449 if (!directory_exist(lp_piddir())) {
1450 mkdir(lp_piddir(), 0755);
1460 if (!secrets_init()) {
1462 DEBUG(0,("Could not initialize domain trust account secrets. Giving up\n"));
1466 /* Unblock all signals we are interested in as they may have been
1467 blocked by the parent process. */
1469 BlockSignals(False
, SIGINT
);
1470 BlockSignals(False
, SIGQUIT
);
1471 BlockSignals(False
, SIGTERM
);
1472 BlockSignals(False
, SIGUSR1
);
1473 BlockSignals(False
, SIGUSR2
);
1474 BlockSignals(False
, SIGHUP
);
1475 BlockSignals(False
, SIGCHLD
);
1478 become_daemon(Fork
, no_process_group
, log_stdout
);
1480 pidfile_create(lp_piddir(), "winbindd");
1484 * If we're interactive we want to set our own process group for
1485 * signal management.
1487 if (interactive
&& !no_process_group
)
1488 setpgid( (pid_t
)0, (pid_t
)0);
1493 /* Don't use winbindd_reinit_after_fork here as
1494 * we're just starting up and haven't created any
1495 * winbindd-specific resources we must free yet. JRA.
1498 status
= reinit_after_fork(winbind_messaging_context(),
1499 winbind_event_context(),
1501 if (!NT_STATUS_IS_OK(status
)) {
1502 DEBUG(0,("reinit_after_fork() failed\n"));
1507 * Do not initialize the parent-child-pipe before becoming
1508 * a daemon: this is used to detect a died parent in the child
1511 status
= init_before_fork();
1512 if (!NT_STATUS_IS_OK(status
)) {
1513 DEBUG(0, ("init_before_fork failed: %s\n", nt_errstr(status
)));
1517 winbindd_register_handlers(!Fork
);
1519 status
= init_system_session_info();
1520 if (!NT_STATUS_IS_OK(status
)) {
1521 DEBUG(1, ("ERROR: failed to setup system user info: %s.\n",
1522 nt_errstr(status
)));
1526 rpc_lsarpc_init(NULL
);
1527 rpc_samr_init(NULL
);
1529 winbindd_init_addrchange(NULL
, winbind_event_context(),
1530 winbind_messaging_context());
1532 /* setup listen sockets */
1534 if (!winbindd_setup_listeners()) {
1535 DEBUG(0,("winbindd_setup_listeners() failed\n"));
1540 /* Loop waiting for requests */
1542 frame
= talloc_stackframe();
1544 if (tevent_loop_once(winbind_event_context()) == -1) {
1545 DEBUG(1, ("tevent_loop_once() failed: %s\n",