s3-rpc_server: Addded function to create custom pipes_struct.
[amitay/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
26 /* Creates a pipes_struct and initializes it with the information
27  * sent from the client */
28 static int make_server_pipes_struct(TALLOC_CTX *mem_ctx,
29                                     const char *pipe_name,
30                                     const struct ndr_syntax_id id,
31                                     const char *client_address,
32                                     struct netr_SamInfo3 *info3,
33                                     struct pipes_struct **_p,
34                                     int *perrno)
35 {
36         struct pipes_struct *p;
37         NTSTATUS status;
38         bool ok;
39
40         p = talloc_zero(mem_ctx, struct pipes_struct);
41         if (!p) {
42                 *perrno = ENOMEM;
43                 return -1;
44         }
45         p->syntax = id;
46
47         p->mem_ctx = talloc_named(p, 0, "pipe %s %p", pipe_name, p);
48         if (!p->mem_ctx) {
49                 TALLOC_FREE(p);
50                 *perrno = ENOMEM;
51                 return -1;
52         }
53
54         ok = init_pipe_handles(p, &id);
55         if (!ok) {
56                 DEBUG(1, ("Failed to init handles\n"));
57                 TALLOC_FREE(p);
58                 *perrno = EINVAL;
59                 return -1;
60         }
61
62         /*
63          * Initialize the incoming RPC data buffer with one PDU worth of
64          * memory. We cheat here and say we're marshalling, as we intend
65          * to add incoming data directly into the prs_struct and we want
66          * it to auto grow. We will change the type to UNMARSALLING before
67          * processing the stream.
68          */
69         if (!prs_init(&p->in_data.data, 128, p->mem_ctx, MARSHALL)) {
70                 DEBUG(0, ("malloc fail for in_data struct.\n"));
71                 TALLOC_FREE(p);
72                 *perrno = ENOMEM;
73                 return -1;
74         }
75
76         /*
77          * Initialize the outgoing RPC data buffer with no memory.
78          */
79         prs_init_empty(&p->out_data.rdata, p->mem_ctx, MARSHALL);
80
81         p->endian = RPC_LITTLE_ENDIAN;
82
83         status = make_server_info_info3(p,
84                                         info3->base.account_name.string,
85                                         info3->base.domain.string,
86                                         &p->server_info, info3);
87         if (!NT_STATUS_IS_OK(status)) {
88                 DEBUG(1, ("Failed to init server info\n"));
89                 TALLOC_FREE(p);
90                 *perrno = EINVAL;
91                 return -1;
92         }
93
94         /*
95          * Some internal functions need a local token to determine access to
96          * resoutrces.
97          */
98         status = create_local_token(p->server_info);
99         if (!NT_STATUS_IS_OK(status)) {
100                 DEBUG(1, ("Failed to init local auth token\n"));
101                 TALLOC_FREE(p);
102                 *perrno = EINVAL;
103                 return -1;
104         }
105
106         p->client_id = talloc_zero(p, struct client_address);
107         if (!p->client_id) {
108                 TALLOC_FREE(p);
109                 *perrno = ENOMEM;
110                 return -1;
111         }
112         strlcpy(p->client_id->addr,
113                 client_address, sizeof(p->client_id->addr));
114
115         talloc_set_destructor(p, close_internal_rpc_pipe_hnd);
116
117         *_p = p;
118         return 0;
119 }
120
121
122 struct named_pipe_listen_state {
123         int fd;
124         char *name;
125 };
126
127 static void named_pipe_listener(struct tevent_context *ev,
128                                 struct tevent_fd *fde,
129                                 uint16_t flags,
130                                 void *private_data);
131
132 bool setup_named_pipe_socket(const char *pipe_name,
133                              struct tevent_context *ev_ctx)
134 {
135         struct named_pipe_listen_state *state;
136         struct tevent_fd *fde;
137         char *np_dir;
138
139         state = talloc(ev_ctx, struct named_pipe_listen_state);
140         if (!state) {
141                 DEBUG(0, ("Out of memory\n"));
142                 return false;
143         }
144         state->name = talloc_strdup(state, pipe_name);
145         if (!state->name) {
146                 DEBUG(0, ("Out of memory\n"));
147                 goto out;
148         }
149         state->fd = -1;
150
151         np_dir = talloc_asprintf(state, "%s/np", lp_ncalrpc_dir());
152         if (!np_dir) {
153                 DEBUG(0, ("Out of memory\n"));
154                 goto out;
155         }
156
157         if (!directory_create_or_exist(np_dir, geteuid(), 0700)) {
158                 DEBUG(0, ("Failed to create pipe directory %s - %s\n",
159                           np_dir, strerror(errno)));
160                 goto out;
161         }
162
163         state->fd = create_pipe_sock(np_dir, pipe_name, 0700);
164         if (state->fd == -1) {
165                 DEBUG(0, ("Failed to create pipe socket! [%s/%s]\n",
166                           np_dir, pipe_name));
167                 goto out;
168         }
169
170         DEBUG(10, ("Openened pipe socket fd %d for %s\n",
171                    state->fd, pipe_name));
172
173         fde = tevent_add_fd(ev_ctx,
174                             state, state->fd, TEVENT_FD_READ,
175                             named_pipe_listener, state);
176         if (!fde) {
177                 DEBUG(0, ("Failed to add event handler!\n"));
178                 goto out;
179         }
180
181         tevent_fd_set_auto_close(fde);
182         return true;
183
184 out:
185         if (state->fd != -1) {
186                 close(state->fd);
187         }
188         TALLOC_FREE(state);
189         return false;
190 }
191
192 static void named_pipe_accept_function(const char *pipe_name, int fd);
193
194 static void named_pipe_listener(struct tevent_context *ev,
195                                 struct tevent_fd *fde,
196                                 uint16_t flags,
197                                 void *private_data)
198 {
199         struct named_pipe_listen_state *state =
200                         talloc_get_type_abort(private_data,
201                                               struct named_pipe_listen_state);
202         struct sockaddr_un sunaddr;
203         socklen_t len;
204         int sd = -1;
205
206         /* TODO: should we have a limit to the number of clients ? */
207
208         len = sizeof(sunaddr);
209
210         while (sd == -1) {
211                 sd = accept(state->fd,
212                             (struct sockaddr *)(void *)&sunaddr, &len);
213                 if (errno != EINTR) break;
214         }
215
216         if (sd == -1) {
217                 DEBUG(6, ("Failed to get a valid socket [%s]\n",
218                           strerror(errno)));
219                 return;
220         }
221
222         DEBUG(6, ("Accepted socket %d\n", sd));
223
224         named_pipe_accept_function(state->name, sd);
225 }
226
227 static void named_pipe_accept_function(const char *pipe_name, int fd)
228 {
229         return;
230 }