2 Unix SMB/Netbios implementation.
3 Generic infrstructure for RPC Daemons
4 Copyright (C) Simo Sorce 2010
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program. If not, see <http://www.gnu.org/licenses/>.
21 #include "rpc_server/rpc_server.h"
23 #include "librpc/gen_ndr/netlogon.h"
24 #include "registry/reg_parse_prs.h"
25 #include "lib/tsocket/tsocket.h"
27 /* Creates a pipes_struct and initializes it with the information
28 * sent from the client */
29 static int make_server_pipes_struct(TALLOC_CTX *mem_ctx,
30 const char *pipe_name,
31 const struct ndr_syntax_id id,
32 const char *client_address,
33 struct netr_SamInfo3 *info3,
34 struct pipes_struct **_p,
37 struct pipes_struct *p;
41 p = talloc_zero(mem_ctx, struct pipes_struct);
48 p->mem_ctx = talloc_named(p, 0, "pipe %s %p", pipe_name, p);
55 ok = init_pipe_handles(p, &id);
57 DEBUG(1, ("Failed to init handles\n"));
64 * Initialize the incoming RPC data buffer with one PDU worth of
65 * memory. We cheat here and say we're marshalling, as we intend
66 * to add incoming data directly into the prs_struct and we want
67 * it to auto grow. We will change the type to UNMARSALLING before
68 * processing the stream.
70 if (!prs_init(&p->in_data.data, 128, p->mem_ctx, MARSHALL)) {
71 DEBUG(0, ("malloc fail for in_data struct.\n"));
78 * Initialize the outgoing RPC data buffer with no memory.
80 prs_init_empty(&p->out_data.rdata, p->mem_ctx, MARSHALL);
82 p->endian = RPC_LITTLE_ENDIAN;
84 status = make_server_info_info3(p,
85 info3->base.account_name.string,
86 info3->base.domain.string,
87 &p->server_info, info3);
88 if (!NT_STATUS_IS_OK(status)) {
89 DEBUG(1, ("Failed to init server info\n"));
96 * Some internal functions need a local token to determine access to
99 status = create_local_token(p->server_info);
100 if (!NT_STATUS_IS_OK(status)) {
101 DEBUG(1, ("Failed to init local auth token\n"));
107 p->client_id = talloc_zero(p, struct client_address);
113 strlcpy(p->client_id->addr,
114 client_address, sizeof(p->client_id->addr));
116 talloc_set_destructor(p, close_internal_rpc_pipe_hnd);
122 /* Add some helper functions to wrap the common ncacn packet reading functions
123 * until we can share more dcerpc code */
124 struct named_pipe_read_packet_state {
125 struct ncacn_packet *pkt;
129 static void named_pipe_read_packet_done(struct tevent_req *subreq);
131 static struct tevent_req *named_pipe_read_packet_send(TALLOC_CTX *mem_ctx,
132 struct tevent_context *ev,
133 struct tstream_context *tstream)
135 struct named_pipe_read_packet_state *state;
136 struct tevent_req *req, *subreq;
138 req = tevent_req_create(mem_ctx, &state,
139 struct named_pipe_read_packet_state);
145 subreq = dcerpc_read_ncacn_packet_send(state, ev, tstream);
147 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
148 tevent_req_post(req, ev);
151 tevent_req_set_callback(subreq, named_pipe_read_packet_done, req);
156 static void named_pipe_read_packet_done(struct tevent_req *subreq)
158 struct tevent_req *req =
159 tevent_req_callback_data(subreq, struct tevent_req);
160 struct named_pipe_read_packet_state *state =
161 tevent_req_data(req, struct named_pipe_read_packet_state);
164 status = dcerpc_read_ncacn_packet_recv(subreq, state,
168 if (!NT_STATUS_IS_OK(status)) {
169 DEBUG(3, ("Failed to receive dceprc packet!\n"));
170 tevent_req_nterror(req, status);
174 tevent_req_done(req);
177 static NTSTATUS named_pipe_read_packet_recv(struct tevent_req *req,
181 struct named_pipe_read_packet_state *state =
182 tevent_req_data(req, struct named_pipe_read_packet_state);
185 if (tevent_req_is_nterror(req, &status)) {
186 tevent_req_received(req);
190 buffer->data = talloc_move(mem_ctx, &state->buffer.data);
191 buffer->length = state->buffer.length;
193 tevent_req_received(req);
199 /* Start listening on the appropriate unix socket and setup all is needed to
200 * dispatch requests to the pipes rpc implementation */
202 struct named_pipe_listen_state {
207 static void named_pipe_listener(struct tevent_context *ev,
208 struct tevent_fd *fde,
212 bool setup_named_pipe_socket(const char *pipe_name,
213 struct tevent_context *ev_ctx)
215 struct named_pipe_listen_state *state;
216 struct tevent_fd *fde;
219 state = talloc(ev_ctx, struct named_pipe_listen_state);
221 DEBUG(0, ("Out of memory\n"));
224 state->name = talloc_strdup(state, pipe_name);
226 DEBUG(0, ("Out of memory\n"));
231 np_dir = talloc_asprintf(state, "%s/np", lp_ncalrpc_dir());
233 DEBUG(0, ("Out of memory\n"));
237 if (!directory_create_or_exist(np_dir, geteuid(), 0700)) {
238 DEBUG(0, ("Failed to create pipe directory %s - %s\n",
239 np_dir, strerror(errno)));
243 state->fd = create_pipe_sock(np_dir, pipe_name, 0700);
244 if (state->fd == -1) {
245 DEBUG(0, ("Failed to create pipe socket! [%s/%s]\n",
250 DEBUG(10, ("Openened pipe socket fd %d for %s\n",
251 state->fd, pipe_name));
253 fde = tevent_add_fd(ev_ctx,
254 state, state->fd, TEVENT_FD_READ,
255 named_pipe_listener, state);
257 DEBUG(0, ("Failed to add event handler!\n"));
261 tevent_fd_set_auto_close(fde);
265 if (state->fd != -1) {
272 static void named_pipe_accept_function(const char *pipe_name, int fd);
274 static void named_pipe_listener(struct tevent_context *ev,
275 struct tevent_fd *fde,
279 struct named_pipe_listen_state *state =
280 talloc_get_type_abort(private_data,
281 struct named_pipe_listen_state);
282 struct sockaddr_un sunaddr;
286 /* TODO: should we have a limit to the number of clients ? */
288 len = sizeof(sunaddr);
291 sd = accept(state->fd,
292 (struct sockaddr *)(void *)&sunaddr, &len);
293 if (errno != EINTR) break;
297 DEBUG(6, ("Failed to get a valid socket [%s]\n",
302 DEBUG(6, ("Accepted socket %d\n", sd));
304 named_pipe_accept_function(state->name, sd);
307 static void named_pipe_accept_function(const char *pipe_name, int fd)