89e224714c4e96d7fbcb40c18f464d492d15978a
[kamenim/samba.git] / source3 / rpc_server / rpc_server.c
1 /*
2    Unix SMB/Netbios implementation.
3    Generic infrstructure for RPC Daemons
4    Copyright (C) Simo Sorce 2010
5
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.
10
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.
15
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/>.
18 */
19
20 #include "includes.h"
21 #include "rpc_server/rpc_server.h"
22 #include "rpc_dce.h"
23 #include "librpc/gen_ndr/netlogon.h"
24 #include "registry/reg_parse_prs.h"
25 #include "lib/tsocket/tsocket.h"
26
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,
35                                     int *perrno)
36 {
37         struct pipes_struct *p;
38         NTSTATUS status;
39         bool ok;
40
41         p = talloc_zero(mem_ctx, struct pipes_struct);
42         if (!p) {
43                 *perrno = ENOMEM;
44                 return -1;
45         }
46         p->syntax = id;
47
48         p->mem_ctx = talloc_named(p, 0, "pipe %s %p", pipe_name, p);
49         if (!p->mem_ctx) {
50                 TALLOC_FREE(p);
51                 *perrno = ENOMEM;
52                 return -1;
53         }
54
55         ok = init_pipe_handles(p, &id);
56         if (!ok) {
57                 DEBUG(1, ("Failed to init handles\n"));
58                 TALLOC_FREE(p);
59                 *perrno = EINVAL;
60                 return -1;
61         }
62
63         /*
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.
69          */
70         if (!prs_init(&p->in_data.data, 128, p->mem_ctx, MARSHALL)) {
71                 DEBUG(0, ("malloc fail for in_data struct.\n"));
72                 TALLOC_FREE(p);
73                 *perrno = ENOMEM;
74                 return -1;
75         }
76
77         /*
78          * Initialize the outgoing RPC data buffer with no memory.
79          */
80         prs_init_empty(&p->out_data.rdata, p->mem_ctx, MARSHALL);
81
82         p->endian = RPC_LITTLE_ENDIAN;
83
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"));
90                 TALLOC_FREE(p);
91                 *perrno = EINVAL;
92                 return -1;
93         }
94
95         /*
96          * Some internal functions need a local token to determine access to
97          * resoutrces.
98          */
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"));
102                 TALLOC_FREE(p);
103                 *perrno = EINVAL;
104                 return -1;
105         }
106
107         p->client_id = talloc_zero(p, struct client_address);
108         if (!p->client_id) {
109                 TALLOC_FREE(p);
110                 *perrno = ENOMEM;
111                 return -1;
112         }
113         strlcpy(p->client_id->addr,
114                 client_address, sizeof(p->client_id->addr));
115
116         talloc_set_destructor(p, close_internal_rpc_pipe_hnd);
117
118         *_p = p;
119         return 0;
120 }
121
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;
126         DATA_BLOB buffer;
127 };
128
129 static void named_pipe_read_packet_done(struct tevent_req *subreq);
130
131 static struct tevent_req *named_pipe_read_packet_send(TALLOC_CTX *mem_ctx,
132                                         struct tevent_context *ev,
133                                         struct tstream_context *tstream)
134 {
135         struct named_pipe_read_packet_state *state;
136         struct tevent_req *req, *subreq;
137
138         req = tevent_req_create(mem_ctx, &state,
139                                 struct named_pipe_read_packet_state);
140         if (!req) {
141                 return NULL;
142         }
143         ZERO_STRUCTP(state);
144
145         subreq = dcerpc_read_ncacn_packet_send(state, ev, tstream);
146         if (!subreq) {
147                 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
148                 tevent_req_post(req, ev);
149                 return req;
150         }
151         tevent_req_set_callback(subreq, named_pipe_read_packet_done, req);
152
153         return req;
154 }
155
156 static void named_pipe_read_packet_done(struct tevent_req *subreq)
157 {
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);
162         NTSTATUS status;
163
164         status = dcerpc_read_ncacn_packet_recv(subreq, state,
165                                                 &state->pkt,
166                                                 &state->buffer);
167         TALLOC_FREE(subreq);
168         if (!NT_STATUS_IS_OK(status)) {
169                 DEBUG(3, ("Failed to receive dceprc packet!\n"));
170                 tevent_req_nterror(req, status);
171                 return;
172         }
173
174         tevent_req_done(req);
175 }
176
177 static NTSTATUS named_pipe_read_packet_recv(struct tevent_req *req,
178                                                 TALLOC_CTX *mem_ctx,
179                                                 DATA_BLOB *buffer)
180 {
181         struct named_pipe_read_packet_state *state =
182                 tevent_req_data(req, struct named_pipe_read_packet_state);
183         NTSTATUS status;
184
185         if (tevent_req_is_nterror(req, &status)) {
186                 tevent_req_received(req);
187                 return status;
188         }
189
190         buffer->data = talloc_move(mem_ctx, &state->buffer.data);
191         buffer->length = state->buffer.length;
192
193         tevent_req_received(req);
194         return NT_STATUS_OK;
195 }
196
197
198
199 /* Start listening on the appropriate unix socket and setup all is needed to
200  * dispatch requests to the pipes rpc implementation */
201
202 struct named_pipe_listen_state {
203         int fd;
204         char *name;
205 };
206
207 static void named_pipe_listener(struct tevent_context *ev,
208                                 struct tevent_fd *fde,
209                                 uint16_t flags,
210                                 void *private_data);
211
212 bool setup_named_pipe_socket(const char *pipe_name,
213                              struct tevent_context *ev_ctx)
214 {
215         struct named_pipe_listen_state *state;
216         struct tevent_fd *fde;
217         char *np_dir;
218
219         state = talloc(ev_ctx, struct named_pipe_listen_state);
220         if (!state) {
221                 DEBUG(0, ("Out of memory\n"));
222                 return false;
223         }
224         state->name = talloc_strdup(state, pipe_name);
225         if (!state->name) {
226                 DEBUG(0, ("Out of memory\n"));
227                 goto out;
228         }
229         state->fd = -1;
230
231         np_dir = talloc_asprintf(state, "%s/np", lp_ncalrpc_dir());
232         if (!np_dir) {
233                 DEBUG(0, ("Out of memory\n"));
234                 goto out;
235         }
236
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)));
240                 goto out;
241         }
242
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",
246                           np_dir, pipe_name));
247                 goto out;
248         }
249
250         DEBUG(10, ("Openened pipe socket fd %d for %s\n",
251                    state->fd, pipe_name));
252
253         fde = tevent_add_fd(ev_ctx,
254                             state, state->fd, TEVENT_FD_READ,
255                             named_pipe_listener, state);
256         if (!fde) {
257                 DEBUG(0, ("Failed to add event handler!\n"));
258                 goto out;
259         }
260
261         tevent_fd_set_auto_close(fde);
262         return true;
263
264 out:
265         if (state->fd != -1) {
266                 close(state->fd);
267         }
268         TALLOC_FREE(state);
269         return false;
270 }
271
272 static void named_pipe_accept_function(const char *pipe_name, int fd);
273
274 static void named_pipe_listener(struct tevent_context *ev,
275                                 struct tevent_fd *fde,
276                                 uint16_t flags,
277                                 void *private_data)
278 {
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;
283         socklen_t len;
284         int sd = -1;
285
286         /* TODO: should we have a limit to the number of clients ? */
287
288         len = sizeof(sunaddr);
289
290         while (sd == -1) {
291                 sd = accept(state->fd,
292                             (struct sockaddr *)(void *)&sunaddr, &len);
293                 if (errno != EINTR) break;
294         }
295
296         if (sd == -1) {
297                 DEBUG(6, ("Failed to get a valid socket [%s]\n",
298                           strerror(errno)));
299                 return;
300         }
301
302         DEBUG(6, ("Accepted socket %d\n", sd));
303
304         named_pipe_accept_function(state->name, sd);
305 }
306
307 static void named_pipe_accept_function(const char *pipe_name, int fd)
308 {
309         return;
310 }