00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031 #include "includes.h"
00032 #include "winbindd.h"
00033
00034 #undef DBGC_CLASS
00035 #define DBGC_CLASS DBGC_WINBIND
00036
00037 extern BOOL override_logfile;
00038
00039
00040
00041 static void child_read_request(struct winbindd_cli_state *state)
00042 {
00043 ssize_t len;
00044
00045
00046
00047 len = read_data(state->sock, (char *)&state->request,
00048 sizeof(state->request));
00049
00050 if (len != sizeof(state->request)) {
00051 DEBUG(len > 0 ? 0 : 3, ("Got invalid request length: %d\n", (int)len));
00052 state->finished = True;
00053 return;
00054 }
00055
00056 if (state->request.extra_len == 0) {
00057 state->request.extra_data.data = NULL;
00058 return;
00059 }
00060
00061 DEBUG(10, ("Need to read %d extra bytes\n", (int)state->request.extra_len));
00062
00063 state->request.extra_data.data =
00064 SMB_MALLOC_ARRAY(char, state->request.extra_len + 1);
00065
00066 if (state->request.extra_data.data == NULL) {
00067 DEBUG(0, ("malloc failed\n"));
00068 state->finished = True;
00069 return;
00070 }
00071
00072
00073 state->request.extra_data.data[state->request.extra_len] = '\0';
00074
00075 len = read_data(state->sock, state->request.extra_data.data,
00076 state->request.extra_len);
00077
00078 if (len != state->request.extra_len) {
00079 DEBUG(0, ("Could not read extra data\n"));
00080 state->finished = True;
00081 return;
00082 }
00083 }
00084
00085
00086
00087
00088
00089
00090
00091
00092 struct winbindd_async_request {
00093 struct winbindd_async_request *next, *prev;
00094 TALLOC_CTX *mem_ctx;
00095 struct winbindd_child *child;
00096 struct winbindd_request *request;
00097 struct winbindd_response *response;
00098 void (*continuation)(void *private_data, BOOL success);
00099 struct timed_event *reply_timeout_event;
00100 pid_t child_pid;
00101
00102 void *private_data;
00103 };
00104
00105 static void async_request_fail(struct winbindd_async_request *state);
00106 static void async_main_request_sent(void *private_data, BOOL success);
00107 static void async_request_sent(void *private_data, BOOL success);
00108 static void async_reply_recv(void *private_data, BOOL success);
00109 static void schedule_async_request(struct winbindd_child *child);
00110
00111 void async_request(TALLOC_CTX *mem_ctx, struct winbindd_child *child,
00112 struct winbindd_request *request,
00113 struct winbindd_response *response,
00114 void (*continuation)(void *private_data, BOOL success),
00115 void *private_data)
00116 {
00117 struct winbindd_async_request *state;
00118
00119 SMB_ASSERT(continuation != NULL);
00120
00121 state = TALLOC_P(mem_ctx, struct winbindd_async_request);
00122
00123 if (state == NULL) {
00124 DEBUG(0, ("talloc failed\n"));
00125 continuation(private_data, False);
00126 return;
00127 }
00128
00129 state->mem_ctx = mem_ctx;
00130 state->child = child;
00131 state->reply_timeout_event = NULL;
00132 state->request = request;
00133 state->response = response;
00134 state->continuation = continuation;
00135 state->private_data = private_data;
00136
00137 DLIST_ADD_END(child->requests, state, struct winbindd_async_request *);
00138
00139 schedule_async_request(child);
00140
00141 return;
00142 }
00143
00144 static void async_main_request_sent(void *private_data, BOOL success)
00145 {
00146 struct winbindd_async_request *state =
00147 talloc_get_type_abort(private_data, struct winbindd_async_request);
00148
00149 if (!success) {
00150 DEBUG(5, ("Could not send async request\n"));
00151 async_request_fail(state);
00152 return;
00153 }
00154
00155 if (state->request->extra_len == 0) {
00156 async_request_sent(private_data, True);
00157 return;
00158 }
00159
00160 setup_async_write(&state->child->event, state->request->extra_data.data,
00161 state->request->extra_len,
00162 async_request_sent, state);
00163 }
00164
00165
00166
00167
00168
00169
00170 static void async_request_timeout_handler(struct event_context *ctx,
00171 struct timed_event *te,
00172 const struct timeval *now,
00173 void *private_data)
00174 {
00175 struct winbindd_async_request *state =
00176 talloc_get_type_abort(private_data, struct winbindd_async_request);
00177
00178 DEBUG(0,("async_request_timeout_handler: child pid %u is not responding. "
00179 "Closing connection to it.\n",
00180 state->child_pid ));
00181
00182
00183 async_reply_recv(private_data, False);
00184 }
00185
00186
00187
00188
00189
00190
00191 static void async_request_fail(struct winbindd_async_request *state)
00192 {
00193 DLIST_REMOVE(state->child->requests, state);
00194
00195 TALLOC_FREE(state->reply_timeout_event);
00196
00197 SMB_ASSERT(state->child_pid != (pid_t)0);
00198
00199
00200 if (state->child->pid == state->child_pid) {
00201 kill(state->child_pid, SIGTERM);
00202
00203
00204
00205
00206 winbind_child_died(state->child_pid);
00207 }
00208
00209 state->response->length = sizeof(struct winbindd_response);
00210 state->response->result = WINBINDD_ERROR;
00211 state->continuation(state->private_data, False);
00212 }
00213
00214 static void async_request_sent(void *private_data_data, BOOL success)
00215 {
00216 struct winbindd_async_request *state =
00217 talloc_get_type_abort(private_data_data, struct winbindd_async_request);
00218
00219 if (!success) {
00220 DEBUG(5, ("Could not send async request to child pid %u\n",
00221 (unsigned int)state->child_pid ));
00222 async_request_fail(state);
00223 return;
00224 }
00225
00226
00227
00228 setup_async_read(&state->child->event,
00229 &state->response->result,
00230 sizeof(state->response->result),
00231 async_reply_recv, state);
00232
00233
00234
00235
00236
00237
00238
00239 state->reply_timeout_event = event_add_timed(winbind_event_context(),
00240 NULL,
00241 timeval_current_ofs(300,0),
00242 "async_request_timeout",
00243 async_request_timeout_handler,
00244 state);
00245 if (!state->reply_timeout_event) {
00246 smb_panic("async_request_sent: failed to add timeout handler.\n");
00247 }
00248 }
00249
00250 static void async_reply_recv(void *private_data, BOOL success)
00251 {
00252 struct winbindd_async_request *state =
00253 talloc_get_type_abort(private_data, struct winbindd_async_request);
00254 struct winbindd_child *child = state->child;
00255
00256 TALLOC_FREE(state->reply_timeout_event);
00257
00258 state->response->length = sizeof(struct winbindd_response);
00259
00260 if (!success) {
00261 DEBUG(5, ("Could not receive async reply from child pid %u\n",
00262 (unsigned int)state->child_pid ));
00263
00264 cache_cleanup_response(state->child_pid);
00265 async_request_fail(state);
00266 return;
00267 }
00268
00269 SMB_ASSERT(cache_retrieve_response(state->child_pid,
00270 state->response));
00271
00272 cache_cleanup_response(state->child_pid);
00273
00274 DLIST_REMOVE(child->requests, state);
00275
00276 schedule_async_request(child);
00277
00278 state->continuation(state->private_data, True);
00279 }
00280
00281 static BOOL fork_domain_child(struct winbindd_child *child);
00282
00283 static void schedule_async_request(struct winbindd_child *child)
00284 {
00285 struct winbindd_async_request *request = child->requests;
00286
00287 if (request == NULL) {
00288 return;
00289 }
00290
00291 if (child->event.flags != 0) {
00292 return;
00293 }
00294
00295 if ((child->pid == 0) && (!fork_domain_child(child))) {
00296
00297
00298 while (request != NULL) {
00299
00300 struct winbindd_async_request *next = request->next;
00301 request->continuation(request->private_data, False);
00302 request = next;
00303 }
00304 return;
00305 }
00306
00307
00308 request->child_pid = child->pid;
00309
00310 setup_async_write(&child->event, request->request,
00311 sizeof(*request->request),
00312 async_main_request_sent, request);
00313
00314 return;
00315 }
00316
00317 struct domain_request_state {
00318 TALLOC_CTX *mem_ctx;
00319 struct winbindd_domain *domain;
00320 struct winbindd_request *request;
00321 struct winbindd_response *response;
00322 void (*continuation)(void *private_data_data, BOOL success);
00323 void *private_data_data;
00324 };
00325
00326 static void domain_init_recv(void *private_data_data, BOOL success);
00327
00328 void async_domain_request(TALLOC_CTX *mem_ctx,
00329 struct winbindd_domain *domain,
00330 struct winbindd_request *request,
00331 struct winbindd_response *response,
00332 void (*continuation)(void *private_data_data, BOOL success),
00333 void *private_data_data)
00334 {
00335 struct domain_request_state *state;
00336
00337 if (domain->initialized) {
00338 async_request(mem_ctx, &domain->child, request, response,
00339 continuation, private_data_data);
00340 return;
00341 }
00342
00343 state = TALLOC_P(mem_ctx, struct domain_request_state);
00344 if (state == NULL) {
00345 DEBUG(0, ("talloc failed\n"));
00346 continuation(private_data_data, False);
00347 return;
00348 }
00349
00350 state->mem_ctx = mem_ctx;
00351 state->domain = domain;
00352 state->request = request;
00353 state->response = response;
00354 state->continuation = continuation;
00355 state->private_data_data = private_data_data;
00356
00357 init_child_connection(domain, domain_init_recv, state);
00358 }
00359
00360 static void recvfrom_child(void *private_data_data, BOOL success)
00361 {
00362 struct winbindd_cli_state *state =
00363 talloc_get_type_abort(private_data_data, struct winbindd_cli_state);
00364 enum winbindd_result result = state->response.result;
00365
00366
00367
00368
00369
00370 state->response.result = WINBINDD_PENDING;
00371
00372 if ((!success) || (result != WINBINDD_OK)) {
00373 request_error(state);
00374 return;
00375 }
00376
00377 request_ok(state);
00378 }
00379
00380 void sendto_child(struct winbindd_cli_state *state,
00381 struct winbindd_child *child)
00382 {
00383 async_request(state->mem_ctx, child, &state->request,
00384 &state->response, recvfrom_child, state);
00385 }
00386
00387 void sendto_domain(struct winbindd_cli_state *state,
00388 struct winbindd_domain *domain)
00389 {
00390 async_domain_request(state->mem_ctx, domain,
00391 &state->request, &state->response,
00392 recvfrom_child, state);
00393 }
00394
00395 static void domain_init_recv(void *private_data_data, BOOL success)
00396 {
00397 struct domain_request_state *state =
00398 talloc_get_type_abort(private_data_data, struct domain_request_state);
00399
00400 if (!success) {
00401 DEBUG(5, ("Domain init returned an error\n"));
00402 state->continuation(state->private_data_data, False);
00403 return;
00404 }
00405
00406 async_request(state->mem_ctx, &state->domain->child,
00407 state->request, state->response,
00408 state->continuation, state->private_data_data);
00409 }
00410
00411 struct winbindd_child_dispatch_table {
00412 enum winbindd_cmd cmd;
00413 enum winbindd_result (*fn)(struct winbindd_domain *domain,
00414 struct winbindd_cli_state *state);
00415 const char *winbindd_cmd_name;
00416 };
00417
00418 static struct winbindd_child_dispatch_table child_dispatch_table[] = {
00419
00420 { WINBINDD_LOOKUPSID, winbindd_dual_lookupsid, "LOOKUPSID" },
00421 { WINBINDD_LOOKUPNAME, winbindd_dual_lookupname, "LOOKUPNAME" },
00422 { WINBINDD_LOOKUPRIDS, winbindd_dual_lookuprids, "LOOKUPRIDS" },
00423 { WINBINDD_LIST_TRUSTDOM, winbindd_dual_list_trusted_domains, "LIST_TRUSTDOM" },
00424 { WINBINDD_INIT_CONNECTION, winbindd_dual_init_connection, "INIT_CONNECTION" },
00425 { WINBINDD_GETDCNAME, winbindd_dual_getdcname, "GETDCNAME" },
00426 { WINBINDD_SHOW_SEQUENCE, winbindd_dual_show_sequence, "SHOW_SEQUENCE" },
00427 { WINBINDD_PAM_AUTH, winbindd_dual_pam_auth, "PAM_AUTH" },
00428 { WINBINDD_PAM_AUTH_CRAP, winbindd_dual_pam_auth_crap, "AUTH_CRAP" },
00429 { WINBINDD_PAM_LOGOFF, winbindd_dual_pam_logoff, "PAM_LOGOFF" },
00430 { WINBINDD_PAM_CHNG_PSWD_AUTH_CRAP,winbindd_dual_pam_chng_pswd_auth_crap,"CHNG_PSWD_AUTH_CRAP" },
00431 { WINBINDD_PAM_CHAUTHTOK, winbindd_dual_pam_chauthtok, "PAM_CHAUTHTOK" },
00432 { WINBINDD_CHECK_MACHACC, winbindd_dual_check_machine_acct, "CHECK_MACHACC" },
00433 { WINBINDD_DUAL_SID2UID, winbindd_dual_sid2uid, "DUAL_SID2UID" },
00434 { WINBINDD_DUAL_SID2GID, winbindd_dual_sid2gid, "DUAL_SID2GID" },
00435 #if 0
00436 { WINBINDD_DUAL_SIDS2XIDS, winbindd_dual_sids2xids, "DUAL_SIDS2XIDS" },
00437 #endif
00438 { WINBINDD_DUAL_UID2SID, winbindd_dual_uid2sid, "DUAL_UID2SID" },
00439 { WINBINDD_DUAL_GID2SID, winbindd_dual_gid2sid, "DUAL_GID2SID" },
00440 { WINBINDD_DUAL_UID2NAME, winbindd_dual_uid2name, "DUAL_UID2NAME" },
00441 { WINBINDD_DUAL_NAME2UID, winbindd_dual_name2uid, "DUAL_NAME2UID" },
00442 { WINBINDD_DUAL_GID2NAME, winbindd_dual_gid2name, "DUAL_GID2NAME" },
00443 { WINBINDD_DUAL_NAME2GID, winbindd_dual_name2gid, "DUAL_NAME2GID" },
00444 { WINBINDD_DUAL_SET_MAPPING, winbindd_dual_set_mapping, "DUAL_SET_MAPPING" },
00445 { WINBINDD_DUAL_SET_HWM, winbindd_dual_set_hwm, "DUAL_SET_HWMS" },
00446 { WINBINDD_DUAL_DUMP_MAPS, winbindd_dual_dump_maps, "DUAL_DUMP_MAPS" },
00447 { WINBINDD_DUAL_USERINFO, winbindd_dual_userinfo, "DUAL_USERINFO" },
00448 { WINBINDD_ALLOCATE_UID, winbindd_dual_allocate_uid, "ALLOCATE_UID" },
00449 { WINBINDD_ALLOCATE_GID, winbindd_dual_allocate_gid, "ALLOCATE_GID" },
00450 { WINBINDD_GETUSERDOMGROUPS, winbindd_dual_getuserdomgroups, "GETUSERDOMGROUPS" },
00451 { WINBINDD_DUAL_GETSIDALIASES, winbindd_dual_getsidaliases, "GETSIDALIASES" },
00452 { WINBINDD_CCACHE_NTLMAUTH, winbindd_dual_ccache_ntlm_auth, "CCACHE_NTLM_AUTH" },
00453
00454
00455 { WINBINDD_NUM_CMDS, NULL, "NONE" }
00456 };
00457
00458 static void child_process_request(struct winbindd_domain *domain,
00459 struct winbindd_cli_state *state)
00460 {
00461 struct winbindd_child_dispatch_table *table;
00462
00463
00464
00465
00466 state->response.result = WINBINDD_ERROR;
00467 state->response.length = sizeof(struct winbindd_response);
00468
00469 state->mem_ctx = talloc_init("winbind request");
00470 if (state->mem_ctx == NULL)
00471 return;
00472
00473
00474
00475 for (table = child_dispatch_table; table->fn; table++) {
00476 if (state->request.cmd == table->cmd) {
00477 DEBUG(10,("process_request: request fn %s\n",
00478 table->winbindd_cmd_name ));
00479 state->response.result = table->fn(domain, state);
00480 break;
00481 }
00482 }
00483
00484 if (!table->fn) {
00485 DEBUG(10,("process_request: unknown request fn number %d\n",
00486 (int)state->request.cmd ));
00487 state->response.result = WINBINDD_ERROR;
00488 }
00489
00490 talloc_destroy(state->mem_ctx);
00491 }
00492
00493 void setup_domain_child(struct winbindd_domain *domain,
00494 struct winbindd_child *child,
00495 const char *explicit_logfile)
00496 {
00497 if (explicit_logfile != NULL) {
00498 pstr_sprintf(child->logfilename, "%s/winbindd-%s.log",
00499 dyn_LOGFILEBASE, explicit_logfile);
00500 } else if (domain != NULL) {
00501 pstr_sprintf(child->logfilename, "%s/wb-%s.log",
00502 dyn_LOGFILEBASE, domain->name);
00503 } else {
00504 smb_panic("Internal error: domain == NULL && "
00505 "explicit_logfile == NULL");
00506 }
00507
00508 child->domain = domain;
00509 }
00510
00511 struct winbindd_child *children = NULL;
00512
00513 void winbind_child_died(pid_t pid)
00514 {
00515 struct winbindd_child *child;
00516
00517 for (child = children; child != NULL; child = child->next) {
00518 if (child->pid == pid) {
00519 break;
00520 }
00521 }
00522
00523 if (child == NULL) {
00524 DEBUG(5, ("Already reaped child %u died\n", (unsigned int)pid));
00525 return;
00526 }
00527
00528
00529
00530 DLIST_REMOVE(children, child);
00531
00532 remove_fd_event(&child->event);
00533 close(child->event.fd);
00534 child->event.fd = 0;
00535 child->event.flags = 0;
00536 child->pid = 0;
00537
00538 schedule_async_request(child);
00539 }
00540
00541
00542
00543 void winbindd_flush_negative_conn_cache(struct winbindd_domain *domain)
00544 {
00545 flush_negative_conn_cache_for_domain(domain->name);
00546 if (*domain->alt_name) {
00547 flush_negative_conn_cache_for_domain(domain->alt_name);
00548 }
00549 }
00550
00551
00552
00553 void winbind_msg_offline(int msg_type, struct process_id src,
00554 void *buf, size_t len, void *private_data)
00555 {
00556 struct winbindd_child *child;
00557 struct winbindd_domain *domain;
00558
00559 DEBUG(10,("winbind_msg_offline: got offline message.\n"));
00560
00561 if (!lp_winbind_offline_logon()) {
00562 DEBUG(10,("winbind_msg_offline: rejecting offline message.\n"));
00563 return;
00564 }
00565
00566
00567 if (!set_global_winbindd_state_offline()) {
00568 DEBUG(10,("winbind_msg_offline: offline request failed.\n"));
00569 return;
00570 }
00571
00572
00573 for (domain = domain_list(); domain; domain = domain->next) {
00574 if (domain->internal) {
00575 continue;
00576 }
00577 DEBUG(5,("winbind_msg_offline: marking %s offline.\n", domain->name));
00578 set_domain_offline(domain);
00579
00580
00581
00582
00583 if ( domain->primary ) {
00584 struct winbindd_child *idmap = idmap_child();
00585
00586 if ( idmap->pid != 0 ) {
00587 message_send_pid(pid_to_procid(idmap->pid),
00588 MSG_WINBIND_OFFLINE,
00589 domain->name,
00590 strlen(domain->name)+1,
00591 False);
00592 }
00593 }
00594 }
00595
00596 for (child = children; child != NULL; child = child->next) {
00597
00598
00599 if (!child->domain || (child == idmap_child())) {
00600 continue;
00601 }
00602
00603
00604 if (child->domain->internal) {
00605 continue;
00606 }
00607
00608
00609
00610
00611 DEBUG(10,("winbind_msg_offline: sending message to pid %u for domain %s.\n",
00612 (unsigned int)child->pid, domain->name ));
00613
00614 message_send_pid(pid_to_procid(child->pid), MSG_WINBIND_OFFLINE, child->domain->name,
00615 strlen(child->domain->name)+1, False);
00616 }
00617 }
00618
00619
00620
00621 void winbind_msg_online(int msg_type, struct process_id src,
00622 void *buf, size_t len, void *private_data)
00623 {
00624 struct winbindd_child *child;
00625 struct winbindd_domain *domain;
00626
00627 DEBUG(10,("winbind_msg_online: got online message.\n"));
00628
00629 if (!lp_winbind_offline_logon()) {
00630 DEBUG(10,("winbind_msg_online: rejecting online message.\n"));
00631 return;
00632 }
00633
00634
00635 set_global_winbindd_state_online();
00636
00637 smb_nscd_flush_user_cache();
00638 smb_nscd_flush_group_cache();
00639
00640
00641 for (domain = domain_list(); domain; domain = domain->next) {
00642 if (domain->internal) {
00643 continue;
00644 }
00645 DEBUG(5,("winbind_msg_online: requesting %s to go online.\n", domain->name));
00646
00647 winbindd_flush_negative_conn_cache(domain);
00648 set_domain_online_request(domain);
00649
00650
00651
00652
00653 if ( domain->primary ) {
00654 struct winbindd_child *idmap = idmap_child();
00655
00656 if ( idmap->pid != 0 ) {
00657 message_send_pid(pid_to_procid(idmap->pid),
00658 MSG_WINBIND_ONLINE,
00659 domain->name,
00660 strlen(domain->name)+1,
00661 False);
00662 }
00663
00664 }
00665 }
00666
00667 for (child = children; child != NULL; child = child->next) {
00668
00669 if (!child->domain || (child == idmap_child())) {
00670 continue;
00671 }
00672
00673
00674 if (child->domain->internal) {
00675 continue;
00676 }
00677
00678
00679
00680
00681 DEBUG(10,("winbind_msg_online: sending message to pid %u for domain %s.\n",
00682 (unsigned int)child->pid, child->domain->name ));
00683
00684 message_send_pid(pid_to_procid(child->pid), MSG_WINBIND_ONLINE, child->domain->name,
00685 strlen(child->domain->name)+1, False);
00686 }
00687 }
00688
00689
00690 void winbind_msg_onlinestatus(int msg_type, struct process_id src,
00691 void *buf, size_t len, void *private_data)
00692 {
00693 struct winbindd_child *child;
00694
00695 DEBUG(10,("winbind_msg_onlinestatus: got onlinestatus message.\n"));
00696
00697 for (child = children; child != NULL; child = child->next) {
00698 if (child->domain && child->domain->primary) {
00699 DEBUG(10,("winbind_msg_onlinestatus: "
00700 "sending message to pid %u of primary domain.\n",
00701 (unsigned int)child->pid));
00702 message_send_pid(pid_to_procid(child->pid),
00703 MSG_WINBIND_ONLINESTATUS, buf, len, False);
00704 break;
00705 }
00706 }
00707 }
00708
00709
00710 static void account_lockout_policy_handler(struct event_context *ctx,
00711 struct timed_event *te,
00712 const struct timeval *now,
00713 void *private_data)
00714 {
00715 struct winbindd_child *child =
00716 (struct winbindd_child *)private_data;
00717 TALLOC_CTX *mem_ctx = NULL;
00718 struct winbindd_methods *methods;
00719 SAM_UNK_INFO_12 lockout_policy;
00720 NTSTATUS result;
00721
00722 DEBUG(10,("account_lockout_policy_handler called\n"));
00723
00724 TALLOC_FREE(child->lockout_policy_event);
00725
00726 methods = child->domain->methods;
00727
00728 mem_ctx = talloc_init("account_lockout_policy_handler ctx");
00729 if (!mem_ctx) {
00730 result = NT_STATUS_NO_MEMORY;
00731 } else {
00732 result = methods->lockout_policy(child->domain, mem_ctx, &lockout_policy);
00733 }
00734
00735 talloc_destroy(mem_ctx);
00736
00737 if (!NT_STATUS_IS_OK(result)) {
00738 DEBUG(10,("account_lockout_policy_handler: lockout_policy failed error %s\n",
00739 nt_errstr(result)));
00740 }
00741
00742 child->lockout_policy_event = event_add_timed(winbind_event_context(), NULL,
00743 timeval_current_ofs(3600, 0),
00744 "account_lockout_policy_handler",
00745 account_lockout_policy_handler,
00746 child);
00747 }
00748
00749
00750
00751 static void child_msg_offline(int msg_type, struct process_id src,
00752 void *buf, size_t len, void *private_data)
00753 {
00754 struct winbindd_domain *domain;
00755 const char *domainname = (const char *)buf;
00756
00757 if (buf == NULL || len == 0) {
00758 return;
00759 }
00760
00761 DEBUG(5,("child_msg_offline received for domain %s.\n", domainname));
00762
00763 if (!lp_winbind_offline_logon()) {
00764 DEBUG(10,("child_msg_offline: rejecting offline message.\n"));
00765 return;
00766 }
00767
00768
00769 if (!set_global_winbindd_state_offline()) {
00770 DEBUG(10,("child_msg_offline: offline request failed.\n"));
00771 return;
00772 }
00773
00774
00775
00776 for (domain = domain_list(); domain; domain = domain->next) {
00777 if (domain->internal) {
00778 continue;
00779 }
00780 if (strequal(domain->name, domainname)) {
00781 DEBUG(5,("child_msg_offline: marking %s offline.\n", domain->name));
00782 set_domain_offline(domain);
00783 }
00784 }
00785 }
00786
00787
00788
00789 static void child_msg_online(int msg_type, struct process_id src,
00790 void *buf, size_t len, void *private_data)
00791 {
00792 struct winbindd_domain *domain;
00793 const char *domainname = (const char *)buf;
00794
00795 if (buf == NULL || len == 0) {
00796 return;
00797 }
00798
00799 DEBUG(5,("child_msg_online received for domain %s.\n", domainname));
00800
00801 if (!lp_winbind_offline_logon()) {
00802 DEBUG(10,("child_msg_online: rejecting online message.\n"));
00803 return;
00804 }
00805
00806
00807 set_global_winbindd_state_online();
00808
00809
00810
00811
00812 for (domain = domain_list(); domain; domain = domain->next) {
00813 if (domain->internal) {
00814 continue;
00815 }
00816 if (strequal(domain->name, domainname)) {
00817 DEBUG(5,("child_msg_online: requesting %s to go online.\n", domain->name));
00818 winbindd_flush_negative_conn_cache(domain);
00819 set_domain_online_request(domain);
00820 }
00821 }
00822 }
00823
00824 static const char *collect_onlinestatus(TALLOC_CTX *mem_ctx)
00825 {
00826 struct winbindd_domain *domain;
00827 char *buf = NULL;
00828
00829 if ((buf = talloc_asprintf(mem_ctx, "global:%s ",
00830 get_global_winbindd_state_offline() ?
00831 "Offline":"Online")) == NULL) {
00832 return NULL;
00833 }
00834
00835 for (domain = domain_list(); domain; domain = domain->next) {
00836 if ((buf = talloc_asprintf_append(buf, "%s:%s ",
00837 domain->name,
00838 domain->online ?
00839 "Online":"Offline")) == NULL) {
00840 return NULL;
00841 }
00842 }
00843
00844 buf = talloc_asprintf_append(buf, "\n");
00845
00846 DEBUG(5,("collect_onlinestatus: %s", buf));
00847
00848 return buf;
00849 }
00850
00851 static void child_msg_onlinestatus(int msg_type, struct process_id src,
00852 void *buf, size_t len, void *private_data)
00853 {
00854 TALLOC_CTX *mem_ctx;
00855 const char *message;
00856 struct process_id *sender;
00857
00858 DEBUG(5,("winbind_msg_onlinestatus received.\n"));
00859
00860 if (!buf) {
00861 return;
00862 }
00863
00864 sender = (struct process_id *)buf;
00865
00866 mem_ctx = talloc_init("winbind_msg_onlinestatus");
00867 if (mem_ctx == NULL) {
00868 return;
00869 }
00870
00871 message = collect_onlinestatus(mem_ctx);
00872 if (message == NULL) {
00873 talloc_destroy(mem_ctx);
00874 return;
00875 }
00876
00877 message_send_pid(*sender, MSG_WINBIND_ONLINESTATUS,
00878 message, strlen(message) + 1, True);
00879
00880 talloc_destroy(mem_ctx);
00881 }
00882
00883 static BOOL fork_domain_child(struct winbindd_child *child)
00884 {
00885 int fdpair[2];
00886 struct winbindd_cli_state state;
00887 struct winbindd_domain *domain;
00888 struct winbindd_domain *primary_domain = NULL;
00889
00890 if (socketpair(AF_UNIX, SOCK_STREAM, 0, fdpair) != 0) {
00891 DEBUG(0, ("Could not open child pipe: %s\n",
00892 strerror(errno)));
00893 return False;
00894 }
00895
00896 ZERO_STRUCT(state);
00897 state.pid = sys_getpid();
00898
00899
00900
00901 message_block();
00902
00903 child->pid = sys_fork();
00904
00905 if (child->pid == -1) {
00906 DEBUG(0, ("Could not fork: %s\n", strerror(errno)));
00907 message_unblock();
00908 return False;
00909 }
00910
00911 if (child->pid != 0) {
00912
00913 close(fdpair[0]);
00914 child->next = child->prev = NULL;
00915 DLIST_ADD(children, child);
00916 child->event.fd = fdpair[1];
00917 child->event.flags = 0;
00918 child->requests = NULL;
00919 add_fd_event(&child->event);
00920
00921 message_unblock();
00922 return True;
00923 }
00924
00925
00926
00927
00928 CatchChild();
00929
00930 state.sock = fdpair[0];
00931 close(fdpair[1]);
00932
00933
00934 if (tdb_reopen_all(1) == -1) {
00935 DEBUG(0,("tdb_reopen_all failed.\n"));
00936 _exit(0);
00937 }
00938
00939 close_conns_after_fork();
00940
00941 if (!override_logfile) {
00942 lp_set_logfile(child->logfilename);
00943 reopen_logs();
00944 }
00945
00946
00947 message_deregister(MSG_SMB_CONF_UPDATED);
00948 message_deregister(MSG_SHUTDOWN);
00949 message_deregister(MSG_WINBIND_OFFLINE);
00950 message_deregister(MSG_WINBIND_ONLINE);
00951 message_deregister(MSG_WINBIND_ONLINESTATUS);
00952
00953
00954 message_unblock();
00955
00956
00957 message_register(MSG_WINBIND_OFFLINE, child_msg_offline, NULL);
00958 message_register(MSG_WINBIND_ONLINE, child_msg_online, NULL);
00959 message_register(MSG_WINBIND_ONLINESTATUS, child_msg_onlinestatus,
00960 NULL);
00961
00962 if ( child->domain ) {
00963 child->domain->startup = True;
00964 child->domain->startup_time = time(NULL);
00965 }
00966
00967
00968
00969
00970 for (domain = domain_list(); domain; domain = domain->next) {
00971 if (domain->primary) {
00972 primary_domain = domain;
00973 }
00974 if ((domain != child->domain) && !domain->primary) {
00975 TALLOC_FREE(domain->check_online_event);
00976 }
00977 }
00978
00979
00980
00981
00982 cancel_named_event(winbind_event_context(),
00983 "krb5_ticket_refresh_handler");
00984
00985
00986 if (child->domain && !(child->domain->internal) &&
00987 lp_winbind_offline_logon()) {
00988
00989 set_domain_online_request(child->domain);
00990
00991 if (primary_domain != child->domain) {
00992
00993
00994
00995
00996
00997
00998
00999
01000
01001
01002 set_domain_online_request(primary_domain);
01003 }
01004
01005 child->lockout_policy_event = event_add_timed(
01006 winbind_event_context(), NULL, timeval_zero(),
01007 "account_lockout_policy_handler",
01008 account_lockout_policy_handler,
01009 child);
01010 }
01011
01012 while (1) {
01013
01014 int ret;
01015 fd_set read_fds;
01016 struct timeval t;
01017 struct timeval *tp;
01018 struct timeval now;
01019
01020
01021 lp_TALLOC_FREE();
01022 main_loop_TALLOC_FREE();
01023
01024
01025 winbind_check_sigterm(false);
01026 winbind_check_sighup(override_logfile ? NULL :
01027 child->logfilename);
01028
01029 run_events(winbind_event_context(), 0, NULL, NULL);
01030
01031 GetTimeOfDay(&now);
01032
01033 if (child->domain && child->domain->startup &&
01034 (now.tv_sec > child->domain->startup_time + 30)) {
01035
01036 DEBUG(10,("fork_domain_child: domain %s no longer in 'startup' mode.\n",
01037 child->domain->name ));
01038 child->domain->startup = False;
01039 }
01040
01041 tp = get_timed_events_timeout(winbind_event_context(), &t);
01042 if (tp) {
01043 DEBUG(11,("select will use timeout of %u.%u seconds\n",
01044 (unsigned int)tp->tv_sec, (unsigned int)tp->tv_usec ));
01045 }
01046
01047
01048
01049 message_dispatch();
01050
01051 FD_ZERO(&read_fds);
01052 FD_SET(state.sock, &read_fds);
01053
01054 ret = sys_select(state.sock + 1, &read_fds, NULL, NULL, tp);
01055
01056 if (ret == 0) {
01057 DEBUG(11,("nothing is ready yet, continue\n"));
01058 continue;
01059 }
01060
01061 if (ret == -1 && errno == EINTR) {
01062
01063 continue;
01064 }
01065
01066 if (ret == -1 && errno != EINTR) {
01067 DEBUG(0,("select error occured\n"));
01068 perror("select");
01069 return False;
01070 }
01071
01072
01073 child_read_request(&state);
01074
01075 if (state.finished) {
01076
01077 exit(0);
01078 }
01079
01080 DEBUG(4,("child daemon request %d\n", (int)state.request.cmd));
01081
01082 ZERO_STRUCT(state.response);
01083 state.request.null_term = '\0';
01084 child_process_request(child->domain, &state);
01085
01086 SAFE_FREE(state.request.extra_data.data);
01087
01088 cache_store_response(sys_getpid(), &state.response);
01089
01090 SAFE_FREE(state.response.extra_data.data);
01091
01092
01093
01094
01095
01096 if (write_data(state.sock,
01097 (const char *)&state.response.result,
01098 sizeof(state.response.result)) !=
01099 sizeof(state.response.result)) {
01100 DEBUG(0, ("Could not write result\n"));
01101 exit(1);
01102 }
01103 }
01104 }