2
Unix SMB/CIFS implementation.
6
Copyright (C) Andrew Tridgell 2002
7
Copyright (C) Volker Lendecke 2004,2005
9
This program is free software; you can redistribute it and/or modify
10
it under the terms of the GNU General Public License as published by
11
the Free Software Foundation; either version 3 of the License, or
12
(at your option) any later version.
14
This program is distributed in the hope that it will be useful,
15
but WITHOUT ANY WARRANTY; without even the implied warranty of
16
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17
GNU General Public License for more details.
19
You should have received a copy of the GNU General Public License
20
along with this program. If not, see <http://www.gnu.org/licenses/>.
24
* We fork a child per domain to be able to act non-blocking in the main
25
* winbind daemon. A domain controller thousands of miles away being being
26
* slow replying with a 10.000 user list should not hold up netlogon calls
27
* that can be handled locally.
32
#include "../../nsswitch/libwbclient/wbc_async.h"
35
#define DBGC_CLASS DBGC_WINBIND
37
extern bool override_logfile;
38
extern struct winbindd_methods cache_methods;
40
/* Read some data from a client connection */
42
static NTSTATUS child_read_request(struct winbindd_cli_state *state)
48
status = read_data(state->sock, (char *)state->request,
49
sizeof(*state->request));
51
if (!NT_STATUS_IS_OK(status)) {
52
DEBUG(3, ("child_read_request: read_data failed: %s\n",
57
if (state->request->extra_len == 0) {
58
state->request->extra_data.data = NULL;
62
DEBUG(10, ("Need to read %d extra bytes\n", (int)state->request->extra_len));
64
state->request->extra_data.data =
65
SMB_MALLOC_ARRAY(char, state->request->extra_len + 1);
67
if (state->request->extra_data.data == NULL) {
68
DEBUG(0, ("malloc failed\n"));
69
return NT_STATUS_NO_MEMORY;
72
/* Ensure null termination */
73
state->request->extra_data.data[state->request->extra_len] = '\0';
75
status= read_data(state->sock, state->request->extra_data.data,
76
state->request->extra_len);
78
if (!NT_STATUS_IS_OK(status)) {
79
DEBUG(0, ("Could not read extra data: %s\n",
86
* Do winbind child async request. This is not simply wb_simple_trans. We have
87
* to do the queueing ourselves because while a request is queued, the child
88
* might have crashed, and we have to re-fork it in the _trigger function.
91
struct wb_child_request_state {
92
struct tevent_context *ev;
93
struct winbindd_child *child;
94
struct winbindd_request *request;
95
struct winbindd_response *response;
98
static bool fork_domain_child(struct winbindd_child *child);
100
static void wb_child_request_trigger(struct tevent_req *req,
102
static void wb_child_request_done(struct tevent_req *subreq);
104
struct tevent_req *wb_child_request_send(TALLOC_CTX *mem_ctx,
105
struct tevent_context *ev,
106
struct winbindd_child *child,
107
struct winbindd_request *request)
109
struct tevent_req *req;
110
struct wb_child_request_state *state;
112
req = tevent_req_create(mem_ctx, &state,
113
struct wb_child_request_state);
119
state->child = child;
120
state->request = request;
122
if (!tevent_queue_add(child->queue, ev, req,
123
wb_child_request_trigger, NULL)) {
124
tevent_req_nomem(NULL, req);
125
return tevent_req_post(req, ev);
130
static void wb_child_request_trigger(struct tevent_req *req,
133
struct wb_child_request_state *state = tevent_req_data(
134
req, struct wb_child_request_state);
135
struct tevent_req *subreq;
137
if ((state->child->pid == 0) && (!fork_domain_child(state->child))) {
138
tevent_req_error(req, errno);
142
subreq = wb_simple_trans_send(state, winbind_event_context(), NULL,
143
state->child->sock, state->request);
144
if (tevent_req_nomem(subreq, req)) {
147
tevent_req_set_callback(subreq, wb_child_request_done, req);
149
if (!tevent_req_set_endtime(req, state->ev,
150
timeval_current_ofs(300, 0))) {
151
tevent_req_nomem(NULL, req);
156
static void wb_child_request_done(struct tevent_req *subreq)
158
struct tevent_req *req = tevent_req_callback_data(
159
subreq, struct tevent_req);
160
struct wb_child_request_state *state = tevent_req_data(
161
req, struct wb_child_request_state);
164
ret = wb_simple_trans_recv(subreq, state, &state->response, &err);
167
tevent_req_error(req, err);
170
tevent_req_done(req);
173
int wb_child_request_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
174
struct winbindd_response **presponse, int *err)
176
struct wb_child_request_state *state = tevent_req_data(
177
req, struct wb_child_request_state);
179
if (tevent_req_is_unix_error(req, err)) {
182
*presponse = talloc_move(mem_ctx, &state->response);
186
struct wb_domain_request_state {
187
struct tevent_context *ev;
188
struct winbindd_domain *domain;
189
struct winbindd_request *request;
190
struct winbindd_request *init_req;
191
struct winbindd_response *response;
194
static void wb_domain_request_gotdc(struct tevent_req *subreq);
195
static void wb_domain_request_initialized(struct tevent_req *subreq);
196
static void wb_domain_request_done(struct tevent_req *subreq);
198
struct tevent_req *wb_domain_request_send(TALLOC_CTX *mem_ctx,
199
struct tevent_context *ev,
200
struct winbindd_domain *domain,
201
struct winbindd_request *request)
203
struct tevent_req *req, *subreq;
204
struct wb_domain_request_state *state;
206
req = tevent_req_create(mem_ctx, &state,
207
struct wb_domain_request_state);
212
if (domain->initialized) {
213
subreq = wb_child_request_send(state, ev, &domain->child,
215
if (tevent_req_nomem(subreq, req)) {
216
return tevent_req_post(req, ev);
218
tevent_req_set_callback(subreq, wb_domain_request_done, req);
222
state->domain = domain;
224
state->request = request;
226
state->init_req = talloc_zero(state, struct winbindd_request);
227
if (tevent_req_nomem(state->init_req, req)) {
228
return tevent_req_post(req, ev);
231
if (IS_DC || domain->primary || domain->internal) {
232
/* The primary domain has to find the DC name itself */
233
state->init_req->cmd = WINBINDD_INIT_CONNECTION;
234
fstrcpy(state->init_req->domain_name, domain->name);
235
state->init_req->data.init_conn.is_primary =
236
domain->primary ? true : false;
237
fstrcpy(state->init_req->data.init_conn.dcname, "");
239
subreq = wb_child_request_send(state, ev, &domain->child,
241
if (tevent_req_nomem(subreq, req)) {
242
return tevent_req_post(req, ev);
244
tevent_req_set_callback(subreq, wb_domain_request_initialized,
250
* Ask our DC for a DC name
252
domain = find_our_domain();
254
/* This is *not* the primary domain, let's ask our DC about a DC
257
state->init_req->cmd = WINBINDD_GETDCNAME;
258
fstrcpy(state->init_req->domain_name, domain->name);
260
subreq = wb_child_request_send(state, ev, &domain->child, request);
261
if (tevent_req_nomem(subreq, req)) {
262
return tevent_req_post(req, ev);
264
tevent_req_set_callback(subreq, wb_domain_request_gotdc, req);
268
static void wb_domain_request_gotdc(struct tevent_req *subreq)
270
struct tevent_req *req = tevent_req_callback_data(
271
subreq, struct tevent_req);
272
struct wb_domain_request_state *state = tevent_req_data(
273
req, struct wb_domain_request_state);
274
struct winbindd_response *response;
277
ret = wb_child_request_recv(subreq, talloc_tos(), &response, &err);
280
tevent_req_error(req, err);
283
state->init_req->cmd = WINBINDD_INIT_CONNECTION;
284
fstrcpy(state->init_req->domain_name, state->domain->name);
285
state->init_req->data.init_conn.is_primary = False;
286
fstrcpy(state->init_req->data.init_conn.dcname,
287
response->data.dc_name);
289
TALLOC_FREE(response);
291
subreq = wb_child_request_send(state, state->ev, &state->domain->child,
293
if (tevent_req_nomem(subreq, req)) {
296
tevent_req_set_callback(subreq, wb_domain_request_initialized, req);
299
static void wb_domain_request_initialized(struct tevent_req *subreq)
301
struct tevent_req *req = tevent_req_callback_data(
302
subreq, struct tevent_req);
303
struct wb_domain_request_state *state = tevent_req_data(
304
req, struct wb_domain_request_state);
305
struct winbindd_response *response;
308
ret = wb_child_request_recv(subreq, talloc_tos(), &response, &err);
311
tevent_req_error(req, err);
315
if (!string_to_sid(&state->domain->sid,
316
response->data.domain_info.sid)) {
317
DEBUG(1,("init_child_recv: Could not convert sid %s "
318
"from string\n", response->data.domain_info.sid));
319
tevent_req_error(req, EINVAL);
322
fstrcpy(state->domain->name, response->data.domain_info.name);
323
fstrcpy(state->domain->alt_name, response->data.domain_info.alt_name);
324
state->domain->native_mode = response->data.domain_info.native_mode;
325
state->domain->active_directory =
326
response->data.domain_info.active_directory;
327
state->domain->initialized = true;
329
TALLOC_FREE(response);
331
subreq = wb_child_request_send(state, state->ev, &state->domain->child,
333
if (tevent_req_nomem(subreq, req)) {
336
tevent_req_set_callback(subreq, wb_domain_request_done, req);
339
static void wb_domain_request_done(struct tevent_req *subreq)
341
struct tevent_req *req = tevent_req_callback_data(
342
subreq, struct tevent_req);
343
struct wb_domain_request_state *state = tevent_req_data(
344
req, struct wb_domain_request_state);
347
ret = wb_child_request_recv(subreq, talloc_tos(), &state->response,
351
tevent_req_error(req, err);
354
tevent_req_done(req);
357
int wb_domain_request_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
358
struct winbindd_response **presponse, int *err)
360
struct wb_domain_request_state *state = tevent_req_data(
361
req, struct wb_domain_request_state);
363
if (tevent_req_is_unix_error(req, err)) {
366
*presponse = talloc_move(mem_ctx, &state->response);
370
struct domain_request_state {
371
struct winbindd_domain *domain;
372
struct winbindd_request *request;
373
struct winbindd_response *response;
374
void (*continuation)(void *private_data_data, bool success);
375
void *private_data_data;
378
static void async_domain_request_done(struct tevent_req *req);
380
void async_domain_request(TALLOC_CTX *mem_ctx,
381
struct winbindd_domain *domain,
382
struct winbindd_request *request,
383
struct winbindd_response *response,
384
void (*continuation)(void *private_data_data, bool success),
385
void *private_data_data)
387
struct tevent_req *subreq;
388
struct domain_request_state *state;
390
state = TALLOC_P(mem_ctx, struct domain_request_state);
392
DEBUG(0, ("talloc failed\n"));
393
continuation(private_data_data, False);
397
state->domain = domain;
398
state->request = request;
399
state->response = response;
400
state->continuation = continuation;
401
state->private_data_data = private_data_data;
403
subreq = wb_domain_request_send(state, winbind_event_context(),
405
if (subreq == NULL) {
406
DEBUG(5, ("wb_domain_request_send failed\n"));
407
continuation(private_data_data, false);
410
tevent_req_set_callback(subreq, async_domain_request_done, state);
413
static void async_domain_request_done(struct tevent_req *req)
415
struct domain_request_state *state = tevent_req_callback_data(
416
req, struct domain_request_state);
417
struct winbindd_response *response;
420
ret = wb_domain_request_recv(req, state, &response, &err);
423
DEBUG(5, ("wb_domain_request returned %s\n", strerror(err)));
424
state->continuation(state->private_data_data, false);
427
*(state->response) = *response;
428
state->continuation(state->private_data_data, true);
431
static void recvfrom_child(void *private_data_data, bool success)
433
struct winbindd_cli_state *state =
434
talloc_get_type_abort(private_data_data, struct winbindd_cli_state);
435
enum winbindd_result result = state->response->result;
437
/* This is an optimization: The child has written directly to the
438
* response buffer. The request itself is still in pending state,
439
* state that in the result code. */
441
state->response->result = WINBINDD_PENDING;
443
if ((!success) || (result != WINBINDD_OK)) {
444
request_error(state);
451
void sendto_domain(struct winbindd_cli_state *state,
452
struct winbindd_domain *domain)
454
async_domain_request(state->mem_ctx, domain,
455
state->request, state->response,
456
recvfrom_child, state);
459
static void child_process_request(struct winbindd_child *child,
460
struct winbindd_cli_state *state)
462
struct winbindd_domain *domain = child->domain;
463
const struct winbindd_child_dispatch_table *table = child->table;
465
/* Free response data - we may be interrupted and receive another
466
command before being able to send this data off. */
468
state->response->result = WINBINDD_ERROR;
469
state->response->length = sizeof(struct winbindd_response);
471
/* as all requests in the child are sync, we can use talloc_tos() */
472
state->mem_ctx = talloc_tos();
474
/* Process command */
476
for (; table->name; table++) {
477
if (state->request->cmd == table->struct_cmd) {
478
DEBUG(10,("child_process_request: request fn %s\n",
480
state->response->result = table->struct_fn(domain, state);
485
DEBUG(1 ,("child_process_request: unknown request fn number %d\n",
486
(int)state->request->cmd));
487
state->response->result = WINBINDD_ERROR;
490
void setup_child(struct winbindd_domain *domain, struct winbindd_child *child,
491
const struct winbindd_child_dispatch_table *table,
492
const char *logprefix,
495
if (logprefix && logname) {
496
if (asprintf(&child->logfilename, "%s/%s-%s",
497
get_dyn_LOGFILEBASE(), logprefix, logname) < 0) {
498
smb_panic("Internal error: asprintf failed");
501
smb_panic("Internal error: logprefix == NULL && "
505
child->domain = domain;
506
child->table = table;
507
child->queue = tevent_queue_create(NULL, "winbind_child");
508
SMB_ASSERT(child->queue != NULL);
509
child->rpccli = wbint_rpccli_create(NULL, domain, child);
510
SMB_ASSERT(child->rpccli != NULL);
513
struct winbindd_child *children = NULL;
515
void winbind_child_died(pid_t pid)
517
struct winbindd_child *child;
519
for (child = children; child != NULL; child = child->next) {
520
if (child->pid == pid) {
526
DEBUG(5, ("Already reaped child %u died\n", (unsigned int)pid));
530
/* This will be re-added in fork_domain_child() */
532
DLIST_REMOVE(children, child);
539
/* Ensure any negative cache entries with the netbios or realm names are removed. */
541
void winbindd_flush_negative_conn_cache(struct winbindd_domain *domain)
543
flush_negative_conn_cache_for_domain(domain->name);
544
if (*domain->alt_name) {
545
flush_negative_conn_cache_for_domain(domain->alt_name);
550
* Parent winbindd process sets its own debug level first and then
551
* sends a message to all the winbindd children to adjust their debug
552
* level to that of parents.
555
void winbind_msg_debug(struct messaging_context *msg_ctx,
558
struct server_id server_id,
561
struct winbindd_child *child;
563
DEBUG(10,("winbind_msg_debug: got debug message.\n"));
565
debug_message(msg_ctx, private_data, MSG_DEBUG, server_id, data);
567
for (child = children; child != NULL; child = child->next) {
569
DEBUG(10,("winbind_msg_debug: sending message to pid %u.\n",
570
(unsigned int)child->pid));
572
messaging_send_buf(msg_ctx, pid_to_procid(child->pid),
575
strlen((char *) data->data) + 1);
579
/* Set our domains as offline and forward the offline message to our children. */
581
void winbind_msg_offline(struct messaging_context *msg_ctx,
584
struct server_id server_id,
587
struct winbindd_child *child;
588
struct winbindd_domain *domain;
590
DEBUG(10,("winbind_msg_offline: got offline message.\n"));
592
if (!lp_winbind_offline_logon()) {
593
DEBUG(10,("winbind_msg_offline: rejecting offline message.\n"));
597
/* Set our global state as offline. */
598
if (!set_global_winbindd_state_offline()) {
599
DEBUG(10,("winbind_msg_offline: offline request failed.\n"));
603
/* Set all our domains as offline. */
604
for (domain = domain_list(); domain; domain = domain->next) {
605
if (domain->internal) {
608
DEBUG(5,("winbind_msg_offline: marking %s offline.\n", domain->name));
609
set_domain_offline(domain);
612
for (child = children; child != NULL; child = child->next) {
613
/* Don't send message to internal childs. We've already
615
if (!child->domain || winbindd_internal_child(child)) {
619
/* Or internal domains (this should not be possible....) */
620
if (child->domain->internal) {
624
/* Each winbindd child should only process requests for one domain - make sure
625
we only set it online / offline for that domain. */
627
DEBUG(10,("winbind_msg_offline: sending message to pid %u for domain %s.\n",
628
(unsigned int)child->pid, domain->name ));
630
messaging_send_buf(msg_ctx, pid_to_procid(child->pid),
632
(uint8 *)child->domain->name,
633
strlen(child->domain->name)+1);
637
/* Set our domains as online and forward the online message to our children. */
639
void winbind_msg_online(struct messaging_context *msg_ctx,
642
struct server_id server_id,
645
struct winbindd_child *child;
646
struct winbindd_domain *domain;
648
DEBUG(10,("winbind_msg_online: got online message.\n"));
650
if (!lp_winbind_offline_logon()) {
651
DEBUG(10,("winbind_msg_online: rejecting online message.\n"));
655
/* Set our global state as online. */
656
set_global_winbindd_state_online();
658
smb_nscd_flush_user_cache();
659
smb_nscd_flush_group_cache();
661
/* Set all our domains as online. */
662
for (domain = domain_list(); domain; domain = domain->next) {
663
if (domain->internal) {
666
DEBUG(5,("winbind_msg_online: requesting %s to go online.\n", domain->name));
668
winbindd_flush_negative_conn_cache(domain);
669
set_domain_online_request(domain);
671
/* Send an online message to the idmap child when our
672
primary domain comes back online */
674
if ( domain->primary ) {
675
struct winbindd_child *idmap = idmap_child();
677
if ( idmap->pid != 0 ) {
678
messaging_send_buf(msg_ctx,
679
pid_to_procid(idmap->pid),
681
(uint8 *)domain->name,
682
strlen(domain->name)+1);
687
for (child = children; child != NULL; child = child->next) {
688
/* Don't send message to internal childs. */
689
if (!child->domain || winbindd_internal_child(child)) {
693
/* Or internal domains (this should not be possible....) */
694
if (child->domain->internal) {
698
/* Each winbindd child should only process requests for one domain - make sure
699
we only set it online / offline for that domain. */
701
DEBUG(10,("winbind_msg_online: sending message to pid %u for domain %s.\n",
702
(unsigned int)child->pid, child->domain->name ));
704
messaging_send_buf(msg_ctx, pid_to_procid(child->pid),
706
(uint8 *)child->domain->name,
707
strlen(child->domain->name)+1);
711
static const char *collect_onlinestatus(TALLOC_CTX *mem_ctx)
713
struct winbindd_domain *domain;
716
if ((buf = talloc_asprintf(mem_ctx, "global:%s ",
717
get_global_winbindd_state_offline() ?
718
"Offline":"Online")) == NULL) {
722
for (domain = domain_list(); domain; domain = domain->next) {
723
if ((buf = talloc_asprintf_append_buffer(buf, "%s:%s ",
726
"Online":"Offline")) == NULL) {
731
buf = talloc_asprintf_append_buffer(buf, "\n");
733
DEBUG(5,("collect_onlinestatus: %s", buf));
738
void winbind_msg_onlinestatus(struct messaging_context *msg_ctx,
741
struct server_id server_id,
746
struct server_id *sender;
748
DEBUG(5,("winbind_msg_onlinestatus received.\n"));
754
sender = (struct server_id *)data->data;
756
mem_ctx = talloc_init("winbind_msg_onlinestatus");
757
if (mem_ctx == NULL) {
761
message = collect_onlinestatus(mem_ctx);
762
if (message == NULL) {
763
talloc_destroy(mem_ctx);
767
messaging_send_buf(msg_ctx, *sender, MSG_WINBIND_ONLINESTATUS,
768
(uint8 *)message, strlen(message) + 1);
770
talloc_destroy(mem_ctx);
773
void winbind_msg_dump_event_list(struct messaging_context *msg_ctx,
776
struct server_id server_id,
779
struct winbindd_child *child;
781
DEBUG(10,("winbind_msg_dump_event_list received\n"));
783
dump_event_list(winbind_event_context());
785
for (child = children; child != NULL; child = child->next) {
787
DEBUG(10,("winbind_msg_dump_event_list: sending message to pid %u\n",
788
(unsigned int)child->pid));
790
messaging_send_buf(msg_ctx, pid_to_procid(child->pid),
797
void winbind_msg_dump_domain_list(struct messaging_context *msg_ctx,
800
struct server_id server_id,
804
const char *message = NULL;
805
struct server_id *sender = NULL;
806
const char *domain = NULL;
809
struct winbindd_domain *dom = NULL;
811
DEBUG(5,("winbind_msg_dump_domain_list received.\n"));
813
if (!data || !data->data) {
817
if (data->length < sizeof(struct server_id)) {
821
mem_ctx = talloc_init("winbind_msg_dump_domain_list");
826
sender = (struct server_id *)data->data;
827
if (data->length > sizeof(struct server_id)) {
828
domain = (const char *)data->data+sizeof(struct server_id);
833
DEBUG(5,("winbind_msg_dump_domain_list for domain: %s\n",
836
message = NDR_PRINT_STRUCT_STRING(mem_ctx, winbindd_domain,
837
find_domain_from_name_noinit(domain));
839
talloc_destroy(mem_ctx);
843
messaging_send_buf(msg_ctx, *sender,
844
MSG_WINBIND_DUMP_DOMAIN_LIST,
845
(uint8_t *)message, strlen(message) + 1);
847
talloc_destroy(mem_ctx);
852
DEBUG(5,("winbind_msg_dump_domain_list all domains\n"));
854
for (dom = domain_list(); dom; dom=dom->next) {
855
message = NDR_PRINT_STRUCT_STRING(mem_ctx, winbindd_domain, dom);
857
talloc_destroy(mem_ctx);
861
s = talloc_asprintf_append(s, "%s\n", message);
863
talloc_destroy(mem_ctx);
868
status = messaging_send_buf(msg_ctx, *sender,
869
MSG_WINBIND_DUMP_DOMAIN_LIST,
870
(uint8_t *)s, strlen(s) + 1);
871
if (!NT_STATUS_IS_OK(status)) {
872
DEBUG(0,("failed to send message: %s\n",
876
talloc_destroy(mem_ctx);
879
static void account_lockout_policy_handler(struct event_context *ctx,
880
struct timed_event *te,
884
struct winbindd_child *child =
885
(struct winbindd_child *)private_data;
886
TALLOC_CTX *mem_ctx = NULL;
887
struct winbindd_methods *methods;
888
struct samr_DomInfo12 lockout_policy;
891
DEBUG(10,("account_lockout_policy_handler called\n"));
893
TALLOC_FREE(child->lockout_policy_event);
895
if ( !winbindd_can_contact_domain( child->domain ) ) {
896
DEBUG(10,("account_lockout_policy_handler: Removing myself since I "
897
"do not have an incoming trust to domain %s\n",
898
child->domain->name));
903
methods = child->domain->methods;
905
mem_ctx = talloc_init("account_lockout_policy_handler ctx");
907
result = NT_STATUS_NO_MEMORY;
909
result = methods->lockout_policy(child->domain, mem_ctx, &lockout_policy);
911
TALLOC_FREE(mem_ctx);
913
if (!NT_STATUS_IS_OK(result)) {
914
DEBUG(10,("account_lockout_policy_handler: lockout_policy failed error %s\n",
918
child->lockout_policy_event = event_add_timed(winbind_event_context(), NULL,
919
timeval_current_ofs(3600, 0),
920
account_lockout_policy_handler,
924
static time_t get_machine_password_timeout(void)
926
/* until we have gpo support use lp setting */
927
return lp_machine_password_timeout();
930
static bool calculate_next_machine_pwd_change(const char *domain,
933
time_t pass_last_set_time;
939
pw = secrets_fetch_machine_password(domain,
944
DEBUG(0,("cannot fetch own machine password ????"));
950
timeout = get_machine_password_timeout();
952
DEBUG(10,("machine password never expires\n"));
956
tv.tv_sec = pass_last_set_time;
957
DEBUG(10, ("password last changed %s\n",
958
timeval_string(talloc_tos(), &tv, false)));
959
tv.tv_sec += timeout;
960
DEBUGADD(10, ("password valid until %s\n",
961
timeval_string(talloc_tos(), &tv, false)));
963
if (time(NULL) < (pass_last_set_time + timeout)) {
964
next_change = pass_last_set_time + timeout;
965
DEBUG(10,("machine password still valid until: %s\n",
966
http_timestring(talloc_tos(), next_change)));
967
*t = timeval_set(next_change, 0);
969
if (lp_clustering()) {
972
* When having a cluster, we have several
973
* winbinds racing for the password change. In
974
* the machine_password_change_handler()
975
* function we check if someone else was
976
* faster when the event triggers. We add a
977
* 255-second random delay here, so that we
978
* don't run to change the password at the
981
generate_random_buffer(&randbuf, sizeof(randbuf));
982
DEBUG(10, ("adding %d seconds randomness\n",
984
t->tv_sec += randbuf;
989
DEBUG(10,("machine password expired, needs immediate change\n"));
996
static void machine_password_change_handler(struct event_context *ctx,
997
struct timed_event *te,
1001
struct winbindd_child *child =
1002
(struct winbindd_child *)private_data;
1003
struct rpc_pipe_client *netlogon_pipe = NULL;
1006
struct timeval next_change;
1008
DEBUG(10,("machine_password_change_handler called\n"));
1010
TALLOC_FREE(child->machine_password_change_event);
1012
if (!calculate_next_machine_pwd_change(child->domain->name,
1014
DEBUG(10, ("calculate_next_machine_pwd_change failed\n"));
1018
DEBUG(10, ("calculate_next_machine_pwd_change returned %s\n",
1019
timeval_string(talloc_tos(), &next_change, false)));
1021
if (!timeval_expired(&next_change)) {
1022
DEBUG(10, ("Someone else has already changed the pw\n"));
1026
if (!winbindd_can_contact_domain(child->domain)) {
1027
DEBUG(10,("machine_password_change_handler: Removing myself since I "
1028
"do not have an incoming trust to domain %s\n",
1029
child->domain->name));
1033
result = cm_connect_netlogon(child->domain, &netlogon_pipe);
1034
if (!NT_STATUS_IS_OK(result)) {
1035
DEBUG(10,("machine_password_change_handler: "
1036
"failed to connect netlogon pipe: %s\n",
1037
nt_errstr(result)));
1041
frame = talloc_stackframe();
1043
result = trust_pw_find_change_and_store_it(netlogon_pipe,
1045
child->domain->name);
1048
DEBUG(10, ("machine_password_change_handler: "
1049
"trust_pw_find_change_and_store_it returned %s\n",
1050
nt_errstr(result)));
1052
if (NT_STATUS_EQUAL(result, NT_STATUS_ACCESS_DENIED) ) {
1053
DEBUG(3,("machine_password_change_handler: password set returned "
1054
"ACCESS_DENIED. Maybe the trust account "
1055
"password was changed and we didn't know it. "
1056
"Killing connections to domain %s\n",
1057
child->domain->name));
1058
TALLOC_FREE(child->domain->conn.netlogon_pipe);
1061
if (!calculate_next_machine_pwd_change(child->domain->name,
1063
DEBUG(10, ("calculate_next_machine_pwd_change failed\n"));
1067
DEBUG(10, ("calculate_next_machine_pwd_change returned %s\n",
1068
timeval_string(talloc_tos(), &next_change, false)));
1070
if (!NT_STATUS_IS_OK(result)) {
1073
* In case of failure, give the DC a minute to recover
1075
tmp = timeval_current_ofs(60, 0);
1076
next_change = timeval_max(&next_change, &tmp);
1080
child->machine_password_change_event = event_add_timed(winbind_event_context(), NULL,
1082
machine_password_change_handler,
1086
/* Deal with a request to go offline. */
1088
static void child_msg_offline(struct messaging_context *msg,
1091
struct server_id server_id,
1094
struct winbindd_domain *domain;
1095
struct winbindd_domain *primary_domain = NULL;
1096
const char *domainname = (const char *)data->data;
1098
if (data->data == NULL || data->length == 0) {
1102
DEBUG(5,("child_msg_offline received for domain %s.\n", domainname));
1104
if (!lp_winbind_offline_logon()) {
1105
DEBUG(10,("child_msg_offline: rejecting offline message.\n"));
1109
primary_domain = find_our_domain();
1111
/* Mark the requested domain offline. */
1113
for (domain = domain_list(); domain; domain = domain->next) {
1114
if (domain->internal) {
1117
if (strequal(domain->name, domainname)) {
1118
DEBUG(5,("child_msg_offline: marking %s offline.\n", domain->name));
1119
set_domain_offline(domain);
1120
/* we are in the trusted domain, set the primary domain
1122
if (domain != primary_domain) {
1123
set_domain_offline(primary_domain);
1129
/* Deal with a request to go online. */
1131
static void child_msg_online(struct messaging_context *msg,
1134
struct server_id server_id,
1137
struct winbindd_domain *domain;
1138
struct winbindd_domain *primary_domain = NULL;
1139
const char *domainname = (const char *)data->data;
1141
if (data->data == NULL || data->length == 0) {
1145
DEBUG(5,("child_msg_online received for domain %s.\n", domainname));
1147
if (!lp_winbind_offline_logon()) {
1148
DEBUG(10,("child_msg_online: rejecting online message.\n"));
1152
primary_domain = find_our_domain();
1154
/* Set our global state as online. */
1155
set_global_winbindd_state_online();
1157
/* Try and mark everything online - delete any negative cache entries
1158
to force a reconnect now. */
1160
for (domain = domain_list(); domain; domain = domain->next) {
1161
if (domain->internal) {
1164
if (strequal(domain->name, domainname)) {
1165
DEBUG(5,("child_msg_online: requesting %s to go online.\n", domain->name));
1166
winbindd_flush_negative_conn_cache(domain);
1167
set_domain_online_request(domain);
1169
/* we can be in trusted domain, which will contact primary domain
1170
* we have to bring primary domain online in trusted domain process
1171
* see, winbindd_dual_pam_auth() --> winbindd_dual_pam_auth_samlogon()
1172
* --> contact_domain = find_our_domain()
1174
if (domain != primary_domain) {
1175
winbindd_flush_negative_conn_cache(primary_domain);
1176
set_domain_online_request(primary_domain);
1182
static void child_msg_dump_event_list(struct messaging_context *msg,
1185
struct server_id server_id,
1188
DEBUG(5,("child_msg_dump_event_list received\n"));
1190
dump_event_list(winbind_event_context());
1193
bool winbindd_reinit_after_fork(const char *logfilename)
1195
struct winbindd_domain *domain;
1196
struct winbindd_child *cl;
1198
if (!NT_STATUS_IS_OK(reinit_after_fork(winbind_messaging_context(),
1199
winbind_event_context(),
1201
DEBUG(0,("reinit_after_fork() failed\n"));
1205
close_conns_after_fork();
1207
if (!override_logfile && logfilename) {
1208
lp_set_logfile(logfilename);
1212
if (!winbindd_setup_sig_term_handler(false))
1214
if (!winbindd_setup_sig_hup_handler(override_logfile ? NULL :
1218
/* Stop zombies in children */
1221
/* Don't handle the same messages as our parent. */
1222
messaging_deregister(winbind_messaging_context(),
1223
MSG_SMB_CONF_UPDATED, NULL);
1224
messaging_deregister(winbind_messaging_context(),
1225
MSG_SHUTDOWN, NULL);
1226
messaging_deregister(winbind_messaging_context(),
1227
MSG_WINBIND_OFFLINE, NULL);
1228
messaging_deregister(winbind_messaging_context(),
1229
MSG_WINBIND_ONLINE, NULL);
1230
messaging_deregister(winbind_messaging_context(),
1231
MSG_WINBIND_ONLINESTATUS, NULL);
1232
messaging_deregister(winbind_messaging_context(),
1233
MSG_DUMP_EVENT_LIST, NULL);
1234
messaging_deregister(winbind_messaging_context(),
1235
MSG_WINBIND_DUMP_DOMAIN_LIST, NULL);
1236
messaging_deregister(winbind_messaging_context(),
1239
/* We have destroyed all events in the winbindd_event_context
1240
* in reinit_after_fork(), so clean out all possible pending
1241
* event pointers. */
1243
/* Deal with check_online_events. */
1245
for (domain = domain_list(); domain; domain = domain->next) {
1246
TALLOC_FREE(domain->check_online_event);
1249
/* Ensure we're not handling a credential cache event inherited
1250
* from our parent. */
1252
ccache_remove_all_after_fork();
1254
/* Destroy all possible events in child list. */
1255
for (cl = children; cl != NULL; cl = cl->next) {
1256
TALLOC_FREE(cl->lockout_policy_event);
1257
TALLOC_FREE(cl->machine_password_change_event);
1259
/* Children should never be able to send
1260
* each other messages, all messages must
1261
* go through the parent.
1266
* This is a little tricky, children must not
1267
* send an MSG_WINBIND_ONLINE message to idmap_child().
1268
* If we are in a child of our primary domain or
1269
* in the process created by fork_child_dc_connect(),
1270
* and the primary domain cannot go online,
1271
* fork_child_dc_connection() sends MSG_WINBIND_ONLINE
1272
* periodically to idmap_child().
1274
* The sequence is, fork_child_dc_connect() ---> getdcs() --->
1275
* get_dc_name_via_netlogon() ---> cm_connect_netlogon()
1276
* ---> init_dc_connection() ---> cm_open_connection --->
1277
* set_domain_online(), sends MSG_WINBIND_ONLINE to
1278
* idmap_child(). Disallow children sending messages
1279
* to each other, all messages must go through the parent.
1288
* In a child there will be only one domain, reference that here.
1290
static struct winbindd_domain *child_domain;
1292
struct winbindd_domain *wb_child_domain(void)
1294
return child_domain;
1297
static bool fork_domain_child(struct winbindd_child *child)
1300
struct winbindd_cli_state state;
1301
struct winbindd_request request;
1302
struct winbindd_response response;
1303
struct winbindd_domain *primary_domain = NULL;
1305
if (child->domain) {
1306
DEBUG(10, ("fork_domain_child called for domain '%s'\n",
1307
child->domain->name));
1309
DEBUG(10, ("fork_domain_child called without domain.\n"));
1311
child_domain = child->domain;
1313
if (socketpair(AF_UNIX, SOCK_STREAM, 0, fdpair) != 0) {
1314
DEBUG(0, ("Could not open child pipe: %s\n",
1320
state.pid = sys_getpid();
1321
state.request = &request;
1322
state.response = &response;
1324
child->pid = sys_fork();
1326
if (child->pid == -1) {
1327
DEBUG(0, ("Could not fork: %s\n", strerror(errno)));
1331
if (child->pid != 0) {
1334
child->next = child->prev = NULL;
1335
DLIST_ADD(children, child);
1336
child->sock = fdpair[1];
1342
DEBUG(10, ("Child process %d\n", (int)sys_getpid()));
1344
state.sock = fdpair[0];
1347
if (!winbindd_reinit_after_fork(child->logfilename)) {
1351
/* Handle online/offline messages. */
1352
messaging_register(winbind_messaging_context(), NULL,
1353
MSG_WINBIND_OFFLINE, child_msg_offline);
1354
messaging_register(winbind_messaging_context(), NULL,
1355
MSG_WINBIND_ONLINE, child_msg_online);
1356
messaging_register(winbind_messaging_context(), NULL,
1357
MSG_DUMP_EVENT_LIST, child_msg_dump_event_list);
1358
messaging_register(winbind_messaging_context(), NULL,
1359
MSG_DEBUG, debug_message);
1361
primary_domain = find_our_domain();
1363
if (primary_domain == NULL) {
1364
smb_panic("no primary domain found");
1367
/* It doesn't matter if we allow cache login,
1368
* try to bring domain online after fork. */
1369
if ( child->domain ) {
1370
child->domain->startup = True;
1371
child->domain->startup_time = time(NULL);
1372
/* we can be in primary domain or in trusted domain
1373
* If we are in trusted domain, set the primary domain
1374
* in start-up mode */
1375
if (!(child->domain->internal)) {
1376
set_domain_online_request(child->domain);
1377
if (!(child->domain->primary)) {
1378
primary_domain->startup = True;
1379
primary_domain->startup_time = time(NULL);
1380
set_domain_online_request(primary_domain);
1386
* We are in idmap child, make sure that we set the
1387
* check_online_event to bring primary domain online.
1389
if (child == idmap_child()) {
1390
set_domain_online_request(primary_domain);
1393
/* We might be in the idmap child...*/
1394
if (child->domain && !(child->domain->internal) &&
1395
lp_winbind_offline_logon()) {
1397
set_domain_online_request(child->domain);
1399
if (primary_domain && (primary_domain != child->domain)) {
1400
/* We need to talk to the primary
1401
* domain as well as the trusted
1402
* domain inside a trusted domain
1405
* set_dc_type_and_flags_trustinfo()
1408
set_domain_online_request(primary_domain);
1411
child->lockout_policy_event = event_add_timed(
1412
winbind_event_context(), NULL, timeval_zero(),
1413
account_lockout_policy_handler,
1417
if (child->domain && child->domain->primary &&
1418
!USE_KERBEROS_KEYTAB &&
1419
lp_server_role() == ROLE_DOMAIN_MEMBER) {
1421
struct timeval next_change;
1423
if (calculate_next_machine_pwd_change(child->domain->name,
1425
child->machine_password_change_event = event_add_timed(
1426
winbind_event_context(), NULL, next_change,
1427
machine_password_change_handler,
1441
TALLOC_CTX *frame = talloc_stackframe();
1442
struct iovec iov[2];
1446
if (run_events(winbind_event_context(), 0, NULL, NULL)) {
1453
if (child->domain && child->domain->startup &&
1454
(now.tv_sec > child->domain->startup_time + 30)) {
1455
/* No longer in "startup" mode. */
1456
DEBUG(10,("fork_domain_child: domain %s no longer in 'startup' mode.\n",
1457
child->domain->name ));
1458
child->domain->startup = False;
1463
FD_SET(state.sock, &r_fds);
1467
* Initialize this high as event_add_to_select_args()
1468
* uses a timeval_min() on this and next_event. Fix
1469
* from Roel van Meer <rolek@alt001.com>.
1474
event_add_to_select_args(winbind_event_context(), &now,
1475
&r_fds, &w_fds, &t, &maxfd);
1476
tp = get_timed_events_timeout(winbind_event_context(), &t);
1478
DEBUG(11,("select will use timeout of %u.%u seconds\n",
1479
(unsigned int)tp->tv_sec, (unsigned int)tp->tv_usec ));
1482
ret = sys_select(maxfd + 1, &r_fds, &w_fds, NULL, tp);
1484
if (run_events(winbind_event_context(), ret, &r_fds, &w_fds)) {
1485
/* We got a signal - continue. */
1491
DEBUG(11,("nothing is ready yet, continue\n"));
1496
if (ret == -1 && errno == EINTR) {
1497
/* We got a signal - continue. */
1502
if (ret == -1 && errno != EINTR) {
1503
DEBUG(0,("select error occured\n"));
1509
/* fetch a request from the main daemon */
1510
status = child_read_request(&state);
1512
if (!NT_STATUS_IS_OK(status)) {
1513
/* we lost contact with our parent */
1517
DEBUG(4,("child daemon request %d\n", (int)state.request->cmd));
1519
ZERO_STRUCTP(state.response);
1520
state.request->null_term = '\0';
1521
state.mem_ctx = frame;
1522
child_process_request(child, &state);
1524
DEBUG(4, ("Finished processing child request %d\n",
1525
(int)state.request->cmd));
1527
SAFE_FREE(state.request->extra_data.data);
1529
iov[0].iov_base = (void *)state.response;
1530
iov[0].iov_len = sizeof(struct winbindd_response);
1533
if (state.response->length > sizeof(struct winbindd_response)) {
1535
(void *)state.response->extra_data.data;
1536
iov[1].iov_len = state.response->length-iov[0].iov_len;
1540
DEBUG(10, ("Writing %d bytes to parent\n",
1541
(int)state.response->length));
1543
if (write_data_iov(state.sock, iov, iov_count) !=
1544
state.response->length) {
1545
DEBUG(0, ("Could not write result\n"));