2 * Unix SMB/CIFS implementation.
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 3 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, see <http://www.gnu.org/licenses/>.
18 #include "source3/include/includes.h"
19 #include "lib/cmdline/cmdline.h"
20 #include "rpc_worker.h"
21 #include "rpc_config.h"
22 #include "librpc/rpc/dcesrv_core.h"
23 #include "librpc/rpc/dcerpc_util.h"
24 #include "source3/librpc/gen_ndr/ndr_rpc_host.h"
25 #include "lib/util/debug.h"
26 #include "lib/util/fault.h"
27 #include "rpc_server.h"
28 #include "rpc_pipes.h"
29 #include "source3/smbd/proto.h"
30 #include "source3/lib/smbd_shim.h"
31 #include "source3/lib/global_contexts.h"
32 #include "source3/lib/util_procid.h"
33 #include "lib/tsocket/tsocket.h"
34 #include "libcli/named_pipe_auth/npa_tstream.h"
35 #include "libcli/smb/smb_constants.h"
36 #include "lib/param/param.h"
37 #include "lib/util/idtree_random.h"
38 #include "lib/util/tevent_unix.h"
39 #include "lib/async_req/async_sock.h"
40 #include "lib/util/dlinklist.h"
41 #include "source3/include/auth.h"
42 #include "nsswitch/winbind_client.h"
43 #include "source3/include/messages.h"
44 #include "libcli/security/security_token.h"
45 #include "libcli/security/dom_sid.h"
46 #include "source3/include/proto.h"
49 * This is the generic code that becomes the
50 * template that all rpcd_* instances that
51 * serve DCERPC can use to provide services to samba-dcerpcd.
53 * The external entry point is:
54 * rpc_worker_main() which takes an argc/argv list
57 * get_interfaces() - List all interfaces that this server provides
58 * get_servers() - Provide the RPC server implementations
60 * Each rpcd_* service needs only to provide
61 * the implementations of get_interfaces() and get_servers()
62 * and call rpc_worker_main() from their main() function
63 * to provide services that can be connected to from samba-dcerpcd.
67 struct dcerpc_ncacn_conn *conns;
68 struct server_id rpc_host_pid;
69 struct messaging_context *msg_ctx;
70 struct dcesrv_context *dce_ctx;
72 struct dcesrv_context_callbacks cb;
74 struct rpc_worker_status status;
79 static void rpc_worker_print_interface(
80 FILE *f, const struct ndr_interface_table *t)
82 const struct ndr_interface_string_array *endpoints = t->endpoints;
84 struct ndr_syntax_id_buf id_buf;
88 ndr_syntax_id_buf_string(&t->syntax_id, &id_buf),
91 for (i=0; i<endpoints->count; i++) {
92 fprintf(f, " %s\n", endpoints->names[i]);
96 static NTSTATUS rpc_worker_report_status(struct rpc_worker *worker)
99 DATA_BLOB blob = { .data = buf, .length = sizeof(buf), };
100 enum ndr_err_code ndr_err;
103 worker->status.num_association_groups = worker->dce_ctx->assoc_groups_num;
105 if (DEBUGLEVEL >= 10) {
106 NDR_PRINT_DEBUG(rpc_worker_status, &worker->status);
109 ndr_err = ndr_push_struct_into_fixed_blob(
112 (ndr_push_flags_fn_t)ndr_push_rpc_worker_status);
113 SMB_ASSERT(NDR_ERR_CODE_IS_SUCCESS(ndr_err));
115 status = messaging_send(
117 worker->rpc_host_pid,
118 MSG_RPC_WORKER_STATUS,
123 static void rpc_worker_connection_terminated(
124 struct dcesrv_connection *conn, void *private_data)
126 struct rpc_worker *worker = talloc_get_type_abort(
127 private_data, struct rpc_worker);
128 struct dcerpc_ncacn_conn *ncacn_conn = talloc_get_type_abort(
129 conn->transport.private_data, struct dcerpc_ncacn_conn);
130 struct dcerpc_ncacn_conn *w = NULL;
135 * We need to drop the association group reference
136 * explicitly here in order to avoid the order given
137 * by the destructors. rpc_worker_report_status() below,
138 * expects worker->dce_ctx->assoc_groups_num to be updated
141 if (conn->assoc_group != NULL) {
142 talloc_unlink(conn, conn->assoc_group);
143 conn->assoc_group = NULL;
146 SMB_ASSERT(worker->status.num_connections > 0);
148 for (w = worker->conns; w != NULL; w = w->next) {
149 if (w == ncacn_conn) {
156 DLIST_REMOVE(worker->conns, ncacn_conn);
158 worker->status.num_connections -= 1;
160 status = rpc_worker_report_status(worker);
161 if (!NT_STATUS_IS_OK(status)) {
162 DBG_DEBUG("rpc_worker_report_status returned %s\n",
167 static int dcesrv_connection_destructor(struct dcesrv_connection *conn)
169 struct dcerpc_ncacn_conn *ncacn_conn = talloc_get_type_abort(
170 conn->transport.private_data,
171 struct dcerpc_ncacn_conn);
173 if (ncacn_conn->termination_fn != NULL) {
174 ncacn_conn->termination_fn(conn, ncacn_conn->termination_data);
181 * A new client has been passed to us from samba-dcerpcd.
183 static void rpc_worker_new_client(
184 struct rpc_worker *worker,
185 struct rpc_host_client *client,
188 struct dcesrv_context *dce_ctx = worker->dce_ctx;
189 struct named_pipe_auth_req_info8 *info8 = client->npa_info8;
190 struct tsocket_address *remote_client_addr = NULL;
191 struct tsocket_address *local_server_addr = NULL;
192 struct dcerpc_binding *b = NULL;
193 enum dcerpc_transport_t transport;
194 struct dcesrv_endpoint *ep = NULL;
195 struct tstream_context *tstream = NULL;
196 struct dcerpc_ncacn_conn *ncacn_conn = NULL;
197 struct dcesrv_connection *dcesrv_conn = NULL;
198 DATA_BLOB buffer = { .data = NULL };
199 struct ncacn_packet *pkt = NULL;
200 struct security_token *token = NULL;
201 uint32_t npa_flags, state_flags;
202 bool found_npa_flags;
206 DBG_DEBUG("Got new conn sock %d for binding %s\n",
210 status = dcerpc_parse_binding(client, client->binding, &b);
211 if (!NT_STATUS_IS_OK(status)) {
212 DBG_DEBUG("dcerpc_parse_binding(%s) failed: %s\n",
217 transport = dcerpc_binding_get_transport(b);
219 status = dcesrv_find_endpoint(dce_ctx, b, &ep);
221 if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND) &&
222 ((transport == NCACN_IP_TCP) || (transport == NCALRPC)) &&
223 (dcerpc_binding_get_string_option(b, "endpoint") != NULL)) {
225 * We have two kinds of servers: Those who explicitly
226 * bind to a port (e.g. 135 for epmapper) and those
227 * who just specify a transport. The client specified
228 * a port (or socket name), but we did not find this
229 * in the list of servers having specified a
230 * port. Retry just matching for the transport,
231 * catching the servers that did not explicitly
234 * This is not fully correct, what we should do is
235 * that once the port the server listens on has been
236 * finalized we should mark this in the server list,
237 * but for now it works. We don't have the same RPC
238 * interface listening twice on different ports.
240 struct dcerpc_binding *b_without_port = dcerpc_binding_dup(
242 if (b_without_port == NULL) {
243 status = NT_STATUS_NO_MEMORY;
247 status = dcerpc_binding_set_string_option(
248 b_without_port, "endpoint", NULL);
249 if (!NT_STATUS_IS_OK(status)) {
250 DBG_DEBUG("Could not delete endpoint: %s\n",
252 TALLOC_FREE(b_without_port);
256 status = dcesrv_find_endpoint(dce_ctx, b_without_port, &ep);
258 TALLOC_FREE(b_without_port);
261 if (!NT_STATUS_IS_OK(status)) {
262 DBG_DEBUG("Could not find endpoint for %s: %s\n",
268 ncacn_conn = talloc(dce_ctx, struct dcerpc_ncacn_conn);
269 if (ncacn_conn == NULL) {
270 DBG_DEBUG("talloc failed\n");
273 *ncacn_conn = (struct dcerpc_ncacn_conn) {
276 .termination_fn = rpc_worker_connection_terminated,
277 .termination_data = worker,
280 if (transport == NCALRPC) {
281 ret = tsocket_address_unix_from_path(ncacn_conn,
282 info8->remote_client_addr,
283 &remote_client_addr);
285 DBG_DEBUG("tsocket_address_unix_from_path"
287 info8->remote_client_addr,
292 ncacn_conn->remote_client_name =
293 talloc_strdup(ncacn_conn, info8->remote_client_name);
294 if (ncacn_conn->remote_client_name == NULL) {
295 DBG_DEBUG("talloc_strdup(%s) failed\n",
296 info8->remote_client_name);
300 ret = tsocket_address_unix_from_path(ncacn_conn,
301 info8->local_server_addr,
304 DBG_DEBUG("tsocket_address_unix_from_path"
306 info8->local_server_addr,
311 ncacn_conn->local_server_name =
312 talloc_strdup(ncacn_conn, info8->local_server_name);
313 if (ncacn_conn->local_server_name == NULL) {
314 DBG_DEBUG("talloc_strdup(%s) failed\n",
315 info8->local_server_name);
319 ret = tsocket_address_inet_from_strings(
322 info8->remote_client_addr,
323 info8->remote_client_port,
324 &remote_client_addr);
326 DBG_DEBUG("tsocket_address_inet_from_strings"
327 "(%s, %" PRIu16 ") failed: %s\n",
328 info8->remote_client_addr,
329 info8->remote_client_port,
333 ncacn_conn->remote_client_name =
334 talloc_strdup(ncacn_conn, info8->remote_client_name);
335 if (ncacn_conn->remote_client_name == NULL) {
336 DBG_DEBUG("talloc_strdup(%s) failed\n",
337 info8->remote_client_name);
341 ret = tsocket_address_inet_from_strings(
344 info8->local_server_addr,
345 info8->local_server_port,
348 DBG_DEBUG("tsocket_address_inet_from_strings"
349 "(%s, %" PRIu16 ") failed: %s\n",
350 info8->local_server_addr,
351 info8->local_server_port,
355 ncacn_conn->local_server_name =
356 talloc_strdup(ncacn_conn, info8->local_server_name);
357 if (ncacn_conn->local_server_name == NULL) {
358 DBG_DEBUG("talloc_strdup(%s) failed\n",
359 info8->local_server_name);
364 if (transport == NCACN_NP) {
365 ret = tstream_npa_existing_socket(
368 FILE_TYPE_MESSAGE_MODE_PIPE,
371 DBG_DEBUG("tstream_npa_existing_socket failed: %s\n",
377 * "transport" so far is implicitly assigned by the
378 * socket that the client connected to, passed in from
379 * samba-dcerpcd via the binding. For NCACN_NP (root
380 * only by unix permissions) we got a
381 * named_pipe_auth_req_info8 where the transport can
384 transport = info8->transport;
386 ret = tstream_bsd_existing_socket(
387 ncacn_conn, sock, &tstream);
389 DBG_DEBUG("tstream_bsd_existing_socket failed: %s\n",
393 /* as server we want to fail early */
394 tstream_bsd_fail_readv_first_error(tstream, true);
398 token = info8->session_info->session_info->security_token;
400 if (security_token_is_system(token) && (transport != NCALRPC)) {
401 DBG_DEBUG("System token only allowed on NCALRPC\n");
405 state_flags = DCESRV_CALL_STATE_FLAG_MAY_ASYNC;
407 found_npa_flags = security_token_find_npa_flags(token, &npa_flags);
408 if (found_npa_flags) {
409 if (npa_flags & SAMBA_NPA_FLAGS_WINBIND_OFF) {
411 DCESRV_CALL_STATE_FLAG_WINBIND_OFF;
415 * Delete the flags so that we don't bail in
416 * local_np_connect_send() on subsequent
417 * connects. Once we connect to another RPC service, a
418 * new flags sid will be added if required.
420 security_token_del_npa_flags(token);
423 ncacn_conn->p.msg_ctx = global_messaging_context();
424 ncacn_conn->p.transport = transport;
426 status = dcesrv_endpoint_connect(dce_ctx,
429 info8->session_info->session_info,
430 global_event_context(),
433 if (!NT_STATUS_IS_OK(status)) {
434 DBG_DEBUG("Failed to connect to endpoint: %s\n",
439 talloc_set_destructor(dcesrv_conn, dcesrv_connection_destructor);
441 dcesrv_conn->transport.private_data = ncacn_conn;
442 dcesrv_conn->transport.report_output_data =
443 dcesrv_sock_report_output_data;
444 dcesrv_conn->transport.terminate_connection =
445 dcesrv_transport_terminate_connection;
447 dcesrv_conn->send_queue = tevent_queue_create(
448 dcesrv_conn, "dcesrv send queue");
449 if (dcesrv_conn->send_queue == NULL) {
450 DBG_DEBUG("tevent_queue_create failed\n");
454 dcesrv_conn->stream = talloc_move(dcesrv_conn, &tstream);
455 dcesrv_conn->local_address =
456 talloc_move(dcesrv_conn, &local_server_addr);
457 dcesrv_conn->remote_address =
458 talloc_move(dcesrv_conn, &remote_client_addr);
460 if (client->bind_packet.length == 0) {
461 DBG_DEBUG("Expected bind packet\n");
465 buffer = (DATA_BLOB) {
466 .data = talloc_move(dcesrv_conn, &client->bind_packet.data),
467 .length = client->bind_packet.length,
470 pkt = talloc(dcesrv_conn, struct ncacn_packet);
472 DBG_DEBUG("talloc failed\n");
476 status = dcerpc_pull_ncacn_packet(pkt, &buffer, pkt);
477 if (!NT_STATUS_IS_OK(status)) {
478 DBG_DEBUG("dcerpc_pull_ncacn_packet failed: %s\n",
485 DLIST_ADD(worker->conns, ncacn_conn);
486 worker->status.num_connections += 1;
488 dcesrv_loop_next_packet(dcesrv_conn, pkt, buffer);
492 TALLOC_FREE(ncacn_conn);
493 TALLOC_FREE(dcesrv_conn);
500 * Parent thinks it successfully sent us a client. Tell it
503 status = rpc_worker_report_status(worker);
504 if (!NT_STATUS_IS_OK(status)) {
505 DBG_DEBUG("rpc_worker_report_status returned %s\n",
511 * New client message processing.
513 static bool rpc_worker_new_client_filter(
514 struct messaging_rec *rec, void *private_data)
516 struct rpc_worker *worker = talloc_get_type_abort(
517 private_data, struct rpc_worker);
518 struct dcesrv_context *dce_ctx = worker->dce_ctx;
519 struct rpc_host_client *client = NULL;
520 enum ndr_err_code ndr_err;
523 if (rec->msg_type != MSG_RPC_HOST_NEW_CLIENT) {
527 if (rec->num_fds != 1) {
528 DBG_DEBUG("Got %"PRIu8" fds\n", rec->num_fds);
532 client = talloc(dce_ctx, struct rpc_host_client);
533 if (client == NULL) {
534 DBG_DEBUG("talloc failed\n");
538 ndr_err = ndr_pull_struct_blob_all(
542 (ndr_pull_flags_fn_t)ndr_pull_rpc_host_client);
543 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
544 DBG_DEBUG("ndr_pull_rpc_host_client failed: %s\n",
545 ndr_errstr(ndr_err));
550 if (DEBUGLEVEL >= 10) {
551 NDR_PRINT_DEBUG(rpc_host_client, client);
557 rpc_worker_new_client(worker, client, sock);
563 * Return your status message processing.
565 static bool rpc_worker_status_filter(
566 struct messaging_rec *rec, void *private_data)
568 struct rpc_worker *worker = talloc_get_type_abort(
569 private_data, struct rpc_worker);
570 struct dcerpc_ncacn_conn *conn = NULL;
574 if (rec->msg_type != MSG_RPC_DUMP_STATUS) {
578 if (rec->num_fds != 1) {
579 DBG_DEBUG("Got %"PRIu8" fds\n", rec->num_fds);
583 fd = dup(rec->fds[0]);
585 DBG_DEBUG("dup(%"PRIi64") failed: %s\n",
593 DBG_DEBUG("fdopen failed: %s\n", strerror(errno));
598 for (conn = worker->conns; conn != NULL; conn = conn->next) {
599 char *endpoint = NULL;
601 endpoint = dcerpc_binding_string(
602 conn, conn->endpoint->ep_description);
605 "endpoint=%s client=%s server=%s\n",
606 endpoint ? endpoint : "UNKNOWN",
607 conn->remote_client_name,
608 conn->local_server_name);
609 TALLOC_FREE(endpoint);
618 take a reference to an existing association group
620 static struct dcesrv_assoc_group *rpc_worker_assoc_group_reference(
621 struct dcesrv_connection *conn,
624 const struct dcesrv_endpoint *endpoint = conn->endpoint;
625 enum dcerpc_transport_t transport = dcerpc_binding_get_transport(
626 endpoint->ep_description);
627 struct dcesrv_assoc_group *assoc_group = NULL;
630 /* find an association group given a assoc_group_id */
631 id_ptr = idr_find(conn->dce_ctx->assoc_groups_idr, id & UINT16_MAX);
632 if (id_ptr == NULL) {
633 DBG_NOTICE("Failed to find assoc_group 0x%08x\n", id);
636 assoc_group = talloc_get_type_abort(id_ptr, struct dcesrv_assoc_group);
638 if (assoc_group->transport != transport) {
639 const char *at = derpc_transport_string_by_transport(
640 assoc_group->transport);
641 const char *ct = derpc_transport_string_by_transport(
644 DBG_NOTICE("assoc_group 0x%08x (transport %s) "
645 "is not available on transport %s\n",
651 * Yes, this is a talloc_reference: The assoc group must be
652 * removed when all connections go. This should be replaced by
653 * adding a linked list of dcesrv_connection structs to the
656 return talloc_reference(conn, assoc_group);
659 static int rpc_worker_assoc_group_destructor(
660 struct dcesrv_assoc_group *assoc_group)
665 assoc_group->dce_ctx->assoc_groups_idr,
666 assoc_group->id & UINT16_MAX);
668 DBG_WARNING("Failed to remove assoc_group 0x%08x\n",
672 SMB_ASSERT(assoc_group->dce_ctx->assoc_groups_num > 0);
673 assoc_group->dce_ctx->assoc_groups_num -= 1;
678 allocate a new association group
680 static struct dcesrv_assoc_group *rpc_worker_assoc_group_new(
681 struct dcesrv_connection *conn, uint16_t worker_index)
683 struct dcesrv_context *dce_ctx = conn->dce_ctx;
684 const struct dcesrv_endpoint *endpoint = conn->endpoint;
685 enum dcerpc_transport_t transport = dcerpc_binding_get_transport(
686 endpoint->ep_description);
687 struct dcesrv_assoc_group *assoc_group = NULL;
690 assoc_group = talloc_zero(conn, struct dcesrv_assoc_group);
691 if (assoc_group == NULL) {
696 * We use 16-bit to encode the worker index,
697 * have 16-bits left within the worker to form a
698 * 32-bit association group id.
700 id = idr_get_new_random(
701 dce_ctx->assoc_groups_idr, assoc_group, 1, UINT16_MAX);
703 talloc_free(assoc_group);
704 DBG_WARNING("Out of association groups!\n");
707 assoc_group->id = (((uint32_t)worker_index) << 16) | id;
708 assoc_group->transport = transport;
709 assoc_group->dce_ctx = dce_ctx;
711 talloc_set_destructor(assoc_group, rpc_worker_assoc_group_destructor);
713 SMB_ASSERT(dce_ctx->assoc_groups_num < UINT16_MAX);
714 dce_ctx->assoc_groups_num += 1;
719 static NTSTATUS rpc_worker_assoc_group_find(
720 struct dcesrv_call_state *call,
723 struct rpc_worker *w = talloc_get_type_abort(
724 private_data, struct rpc_worker);
725 uint32_t assoc_group_id = call->pkt.u.bind.assoc_group_id;
727 if (assoc_group_id != 0) {
728 uint16_t worker_index = (assoc_group_id & 0xffff0000) >> 16;
729 if (worker_index != w->status.worker_index) {
730 DBG_DEBUG("Wrong worker id %"PRIu16", "
731 "expected %"PRIu32"\n",
733 w->status.worker_index);
734 return NT_STATUS_NOT_FOUND;
736 call->conn->assoc_group = rpc_worker_assoc_group_reference(
737 call->conn, assoc_group_id);
739 call->conn->assoc_group = rpc_worker_assoc_group_new(
740 call->conn, w->status.worker_index);
743 if (call->conn->assoc_group == NULL) {
744 /* TODO Return correct status */
745 return NT_STATUS_UNSUCCESSFUL;
751 static struct rpc_worker *rpc_worker_new(
753 struct messaging_context *msg_ctx)
755 struct rpc_worker *worker = NULL;
757 worker = talloc_zero(mem_ctx, struct rpc_worker);
758 if (worker == NULL) {
762 worker->rpc_host_pid = (struct server_id) { .pid = 0 };
763 worker->msg_ctx = msg_ctx;
765 worker->cb = (struct dcesrv_context_callbacks) {
766 .log.successful_authz = dcesrv_log_successful_authz,
767 .auth.gensec_prepare = dcesrv_auth_gensec_prepare,
768 .auth.become_root = become_root,
769 .auth.unbecome_root = unbecome_root,
770 .assoc_group.find = rpc_worker_assoc_group_find,
771 .assoc_group.private_data = worker,
774 worker->dce_ctx = global_dcesrv_context();
775 if (worker->dce_ctx == NULL) {
778 dcesrv_context_set_callbacks(worker->dce_ctx, &worker->cb);
786 static struct dcesrv_context *rpc_worker_dce_ctx(struct rpc_worker *w)
791 struct rpc_worker_state {
792 struct tevent_context *ev;
793 struct rpc_worker *w;
794 struct tevent_req *new_client_req;
795 struct tevent_req *status_req;
796 struct tevent_req *finish_req;
799 static void rpc_worker_done(struct tevent_req *subreq);
800 static void rpc_worker_shutdown(
801 struct messaging_context *msg,
804 struct server_id server_id,
807 static struct tevent_req *rpc_worker_send(
809 struct tevent_context *ev,
810 struct rpc_worker *w,
815 struct tevent_req *req = NULL;
816 struct rpc_worker_state *state = NULL;
819 req = tevent_req_create(mem_ctx, &state, struct rpc_worker_state);
826 if ((server_index < 0) || ((unsigned)server_index > UINT32_MAX)) {
827 DBG_ERR("Invalid server index %d\n", server_index);
828 tevent_req_error(req, EINVAL);
829 return tevent_req_post(req, ev);
831 if ((worker_index < 0) || ((unsigned)worker_index > UINT16_MAX)) {
832 DBG_ERR("Invalid worker index %d\n", worker_index);
833 tevent_req_error(req, EINVAL);
834 return tevent_req_post(req, ev);
836 w->rpc_host_pid = pid_to_procid(rpc_host_pid);
838 w->status = (struct rpc_worker_status) {
839 .server_index = server_index,
840 .worker_index = worker_index,
843 /* Wait for new client messages. */
844 state->new_client_req = messaging_filtered_read_send(
846 messaging_tevent_context(w->msg_ctx),
848 rpc_worker_new_client_filter,
850 if (tevent_req_nomem(state->new_client_req, req)) {
851 return tevent_req_post(req, ev);
854 /* Wait for report your status messages. */
855 state->status_req = messaging_filtered_read_send(
857 messaging_tevent_context(w->msg_ctx),
859 rpc_worker_status_filter,
861 if (tevent_req_nomem(state->status_req, req)) {
862 return tevent_req_post(req, ev);
865 /* Wait for shutdown messages. */
866 status = messaging_register(
867 w->msg_ctx, req, MSG_SHUTDOWN, rpc_worker_shutdown);
868 if (!NT_STATUS_IS_OK(status)) {
869 DBG_DEBUG("messaging_register failed: %s\n",
871 tevent_req_error(req, map_errno_from_nt_status(status));
872 return tevent_req_post(req, ev);
875 state->finish_req = wait_for_read_send(state, ev, 0, false);
876 if (tevent_req_nomem(state->finish_req, req)) {
877 return tevent_req_post(req, ev);
879 tevent_req_set_callback(state->finish_req, rpc_worker_done, req);
881 rpc_worker_report_status(w);
886 static void rpc_worker_done(struct tevent_req *subreq)
888 struct tevent_req *req = tevent_req_callback_data(
889 subreq, struct tevent_req);
893 ok = wait_for_read_recv(subreq, &err);
896 tevent_req_error(req, err);
899 tevent_req_done(req);
902 static void rpc_worker_shutdown(
903 struct messaging_context *msg,
906 struct server_id server_id,
909 struct tevent_req *req = talloc_get_type_abort(
910 private_data, struct tevent_req);
911 tevent_req_done(req);
914 static int rpc_worker_recv(struct tevent_req *req)
916 return tevent_req_simple_recv_unix(req);
919 static void sig_term_handler(
920 struct tevent_context *ev,
921 struct tevent_signal *se,
930 static void sig_hup_handler(
931 struct tevent_context *ev,
932 struct tevent_signal *se,
938 change_to_root_user();
939 lp_load_with_shares(get_dyn_CONFIGFILE());
942 static NTSTATUS register_ep_server(
943 struct dcesrv_context *dce_ctx,
944 const struct dcesrv_endpoint_server *ep_server)
948 DBG_DEBUG("Registering server %s\n", ep_server->name);
950 status = dcerpc_register_ep_server(ep_server);
951 if (!NT_STATUS_IS_OK(status) &&
952 !NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_COLLISION)) {
953 DBG_ERR("Failed to register '%s' endpoint server: %s\n",
959 status = dcesrv_init_ep_server(dce_ctx, ep_server->name);
960 if (!NT_STATUS_IS_OK(status)) {
961 DBG_ERR("dcesrv_init_ep_server(%s) failed: %s\n",
971 * @brief Main function for RPC server implementations
973 * This function provides all that is necessary to run a RPC server
974 * inside the samba-dcerpcd framework. Just pass argv and argc on to
977 * The get_interfaces() callback provides the information that is
978 * passed to samba-dcerpcd via --list-interfaces, it should not do any
979 * real RPC server initialization work. Quickly after this function is
980 * called by rpc_worker_main, the process exits again. It should
981 * return the number of interfaces provided.
983 * get_servers() is called when the process is about to do the real
984 * work. So more heavy-weight initialization should happen here. It
985 * should return NT_STATUS_OK and the number of server implementations provided.
987 * @param[in] argc argc from main()
988 * @param[in] argv argv from main()
989 * @param[in] get_interfaces List all interfaces that this server provides
990 * @param[in] get_servers Provide the RPC server implementations
991 * @param[in] private_data Passed to the callback functions
992 * @return 0 It should never return except on successful process exit
998 const char *daemon_config_name,
1001 size_t (*get_interfaces)(
1002 const struct ndr_interface_table ***ifaces,
1003 void *private_data),
1004 NTSTATUS (*get_servers)(
1005 struct dcesrv_context *dce_ctx,
1006 const struct dcesrv_endpoint_server ***ep_servers,
1007 size_t *num_ep_servers,
1008 void *private_data),
1011 const struct loadparm_substitution *lp_sub =
1012 loadparm_s3_global_substitution();
1013 const char *progname = getprogname();
1014 TALLOC_CTX *frame = NULL;
1015 struct tevent_context *ev_ctx = NULL;
1016 struct tevent_req *req = NULL;
1017 struct messaging_context *msg_ctx = NULL;
1018 struct dcesrv_context *dce_ctx = NULL;
1019 struct tevent_signal *se = NULL;
1024 int worker_group = -1;
1025 int worker_index = -1;
1027 int list_interfaces = 0;
1028 struct rpc_worker *worker = NULL;
1029 const struct dcesrv_endpoint_server **ep_servers;
1030 size_t i, num_servers;
1033 struct poptOption long_options[] = {
1036 .longName = "list-interfaces",
1037 .argInfo = POPT_ARG_NONE,
1038 .arg = &list_interfaces,
1039 .descrip = "List the interfaces provided",
1042 .longName = "worker-group",
1043 .argInfo = POPT_ARG_INT,
1044 .arg = &worker_group,
1045 .descrip = "Group index in status message",
1048 .longName = "worker-index",
1049 .argInfo = POPT_ARG_INT,
1050 .arg = &worker_index,
1051 .descrip = "Worker index in status message",
1056 static const struct smbd_shim smbd_shim_fns = {
1057 .become_authenticated_pipe_user =
1058 smbd_become_authenticated_pipe_user,
1059 .unbecome_authenticated_pipe_user =
1060 smbd_unbecome_authenticated_pipe_user,
1061 .become_root = smbd_become_root,
1062 .unbecome_root = smbd_unbecome_root,
1066 talloc_enable_null_tracking();
1067 frame = talloc_stackframe();
1071 ok = samba_cmdline_init(frame,
1072 SAMBA_CMDLINE_CONFIG_SERVER,
1073 true /* require_smbconf */);
1075 DBG_ERR("Failed to init cmdline parser!\n");
1080 pc = samba_popt_get_context(progname, argc, argv, long_options, 0);
1082 DBG_ERR("Failed to setup popt context!\n");
1087 while ((opt = poptGetNextOpt(pc)) != -1) {
1089 "\nInvalid option %s: %s\n\n",
1090 poptBadOption(pc, 0),
1092 poptPrintUsage(pc, stderr, 0);
1096 poptFreeContext(pc);
1098 if (list_interfaces != 0) {
1099 const struct ndr_interface_table **ifaces = NULL;
1102 num_workers = lp_parm_int(
1103 -1, daemon_config_name, "num_workers", num_workers);
1104 idle_seconds = lp_parm_int(
1105 -1, daemon_config_name, "idle_seconds", idle_seconds);
1107 DBG_DEBUG("daemon=%s, num_workers=%d, idle_seconds=%d\n",
1112 fprintf(stdout, "%d\n%d\n", num_workers, idle_seconds);
1114 num_ifaces = get_interfaces(&ifaces, private_data);
1116 for (i=0; i<num_ifaces; i++) {
1117 rpc_worker_print_interface(stdout, ifaces[i]);
1124 log_stdout = (debug_get_log_type() == DEBUG_STDOUT);
1125 if (log_stdout != 0) {
1126 setup_logging(argv[0], DEBUG_STDOUT);
1128 setup_logging(argv[0], DEBUG_FILE);
1131 set_smbd_shim(&smbd_shim_fns);
1133 dump_core_setup(progname, lp_logfile(talloc_tos(), lp_sub));
1135 /* POSIX demands that signals are inherited. If the invoking
1136 * process has these signals masked, we will have problems, as
1137 * we won't receive them. */
1138 BlockSignals(False, SIGHUP);
1139 BlockSignals(False, SIGUSR1);
1140 BlockSignals(False, SIGTERM);
1143 /* we are never interested in SIGFPE */
1144 BlockSignals(True,SIGFPE);
1146 /* We no longer use USR2... */
1147 #if defined(SIGUSR2)
1148 BlockSignals(True, SIGUSR2);
1150 /* Ignore children - no zombies. */
1155 DBG_STARTUP_NOTICE("%s version %s started.\n%s\n",
1157 samba_version_string(),
1158 samba_copyright_string());
1160 msg_ctx = global_messaging_context();
1161 if (msg_ctx == NULL) {
1162 DBG_ERR("global_messaging_context() failed\n");
1166 ev_ctx = messaging_tevent_context(msg_ctx);
1168 worker = rpc_worker_new(ev_ctx, msg_ctx);
1169 if (worker == NULL) {
1170 DBG_ERR("rpc_worker_new failed\n");
1171 global_messaging_context_free();
1175 dce_ctx = rpc_worker_dce_ctx(worker);
1177 se = tevent_add_signal(
1178 ev_ctx, ev_ctx, SIGTERM, 0, sig_term_handler, NULL);
1180 DBG_ERR("tevent_add_signal failed\n");
1181 global_messaging_context_free();
1185 BlockSignals(false, SIGTERM);
1187 se = tevent_add_signal(
1188 ev_ctx, ev_ctx, SIGHUP, 0, sig_hup_handler, NULL);
1190 DBG_ERR("tevent_add_signal failed\n");
1191 global_messaging_context_free();
1195 BlockSignals(false, SIGHUP);
1197 (void)winbind_off();
1198 ok = init_guest_session_info(NULL);
1201 DBG_WARNING("init_guest_session_info failed\n");
1202 global_messaging_context_free();
1207 status = init_system_session_info(NULL);
1208 if (!NT_STATUS_IS_OK(status)) {
1209 DBG_WARNING("init_system_session_info failed: %s\n",
1211 global_messaging_context_free();
1216 DBG_INFO("Initializing DCE/RPC registered endpoint servers\n");
1218 status = get_servers(dce_ctx,
1222 if (!NT_STATUS_IS_OK(status)) {
1223 DBG_ERR("get_servers failed: %s\n", nt_errstr(status));
1224 global_messaging_context_free();
1229 DBG_DEBUG("get_servers() returned %zu servers\n", num_servers);
1231 for (i=0; i<num_servers; i++) {
1232 status = register_ep_server(dce_ctx, ep_servers[i]);
1233 if (!NT_STATUS_IS_OK(status)) {
1234 DBG_ERR("register_ep_server failed: %s\n",
1236 global_messaging_context_free();
1242 req = rpc_worker_send(
1243 ev_ctx, ev_ctx, worker, getppid(), worker_group, worker_index);
1245 DBG_ERR("rpc_worker_send failed\n");
1246 global_messaging_context_free();
1251 DBG_DEBUG("%s worker running\n", progname);
1253 while (tevent_req_is_in_progress(req)) {
1254 TALLOC_CTX *loop_frame = NULL;
1256 loop_frame = talloc_stackframe();
1258 ret = tevent_loop_once(ev_ctx);
1260 TALLOC_FREE(loop_frame);
1263 DBG_WARNING("tevent_req_once() failed: %s\n",
1265 global_messaging_context_free();
1271 status = dcesrv_shutdown_registered_ep_servers(dce_ctx);
1272 if (!NT_STATUS_IS_OK(status)) {
1273 DBG_DEBUG("Shutdown failed with: %s\n",
1277 ret = rpc_worker_recv(req);
1279 DBG_DEBUG("rpc_worker_recv returned %s\n", strerror(ret));
1280 global_messaging_context_free();