s3-rpc_server: Addded function to create custom pipes_struct.
[Samba.git] / source3 / rpc_server / rpc_server.c
blob63484bb1767f4ac569fb09472baca709098bd1e8
1 /*
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/>.
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"
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)
36 struct pipes_struct *p;
37 NTSTATUS status;
38 bool ok;
40 p = talloc_zero(mem_ctx, struct pipes_struct);
41 if (!p) {
42 *perrno = ENOMEM;
43 return -1;
45 p->syntax = id;
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;
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;
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.
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;
77 * Initialize the outgoing RPC data buffer with no memory.
79 prs_init_empty(&p->out_data.rdata, p->mem_ctx, MARSHALL);
81 p->endian = RPC_LITTLE_ENDIAN;
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;
95 * Some internal functions need a local token to determine access to
96 * resoutrces.
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;
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;
112 strlcpy(p->client_id->addr,
113 client_address, sizeof(p->client_id->addr));
115 talloc_set_destructor(p, close_internal_rpc_pipe_hnd);
117 *_p = p;
118 return 0;
122 struct named_pipe_listen_state {
123 int fd;
124 char *name;
127 static void named_pipe_listener(struct tevent_context *ev,
128 struct tevent_fd *fde,
129 uint16_t flags,
130 void *private_data);
132 bool setup_named_pipe_socket(const char *pipe_name,
133 struct tevent_context *ev_ctx)
135 struct named_pipe_listen_state *state;
136 struct tevent_fd *fde;
137 char *np_dir;
139 state = talloc(ev_ctx, struct named_pipe_listen_state);
140 if (!state) {
141 DEBUG(0, ("Out of memory\n"));
142 return false;
144 state->name = talloc_strdup(state, pipe_name);
145 if (!state->name) {
146 DEBUG(0, ("Out of memory\n"));
147 goto out;
149 state->fd = -1;
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;
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;
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;
170 DEBUG(10, ("Openened pipe socket fd %d for %s\n",
171 state->fd, pipe_name));
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;
181 tevent_fd_set_auto_close(fde);
182 return true;
184 out:
185 if (state->fd != -1) {
186 close(state->fd);
188 TALLOC_FREE(state);
189 return false;
192 static void named_pipe_accept_function(const char *pipe_name, int fd);
194 static void named_pipe_listener(struct tevent_context *ev,
195 struct tevent_fd *fde,
196 uint16_t flags,
197 void *private_data)
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;
206 /* TODO: should we have a limit to the number of clients ? */
208 len = sizeof(sunaddr);
210 while (sd == -1) {
211 sd = accept(state->fd,
212 (struct sockaddr *)(void *)&sunaddr, &len);
213 if (errno != EINTR) break;
216 if (sd == -1) {
217 DEBUG(6, ("Failed to get a valid socket [%s]\n",
218 strerror(errno)));
219 return;
222 DEBUG(6, ("Accepted socket %d\n", sd));
224 named_pipe_accept_function(state->name, sd);
227 static void named_pipe_accept_function(const char *pipe_name, int fd)
229 return;