auth/credentials: don't ignore "client use kerberos" and --use-kerberos for machine...
[Samba.git] / source3 / rpc_server / srv_pipe_hnd.c
blobc73a4c7685cefd1ff270485bec04adab4de91960
1 /*
2 * Unix SMB/CIFS implementation.
3 * RPC Pipe client / server routines
4 * Copyright (C) Andrew Tridgell 1992-1998,
5 * Largely re-written : 2005
6 * Copyright (C) Jeremy Allison 1998 - 2005
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 3 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, see <http://www.gnu.org/licenses/>.
22 #include "includes.h"
23 #include "fake_file.h"
24 #include "rpc_dce.h"
25 #include "ntdomain.h"
26 #include "rpc_server/rpc_ncacn_np.h"
27 #include "rpc_server/srv_pipe_hnd.h"
28 #include "rpc_client/local_np.h"
29 #include "rpc_server/rpc_server.h"
30 #include "rpc_server/rpc_config.h"
31 #include "../lib/tsocket/tsocket.h"
32 #include "../lib/util/tevent_ntstatus.h"
33 #include "librpc/ndr/ndr_table.h"
35 #undef DBGC_CLASS
36 #define DBGC_CLASS DBGC_RPC_SRV
38 bool fsp_is_np(struct files_struct *fsp)
40 enum FAKE_FILE_TYPE type;
42 if ((fsp == NULL) || (fsp->fake_file_handle == NULL)) {
43 return false;
46 type = fsp->fake_file_handle->type;
48 return (type == FAKE_FILE_TYPE_NAMED_PIPE_PROXY);
51 NTSTATUS np_open(TALLOC_CTX *mem_ctx, const char *name,
52 const struct tsocket_address *remote_client_address,
53 const struct tsocket_address *local_server_address,
54 struct auth_session_info *session_info,
55 struct tevent_context *ev_ctx,
56 struct messaging_context *msg_ctx,
57 struct dcesrv_context *dce_ctx,
58 struct fake_file_handle **phandle)
60 struct fake_file_handle *handle;
61 struct npa_state *npa = NULL;
62 int ret;
64 handle = talloc(mem_ctx, struct fake_file_handle);
65 if (handle == NULL) {
66 return NT_STATUS_NO_MEMORY;
69 npa = npa_state_init(handle);
70 if (npa == NULL) {
71 TALLOC_FREE(handle);
72 return NT_STATUS_NO_MEMORY;
74 *handle = (struct fake_file_handle) {
75 .type = FAKE_FILE_TYPE_NAMED_PIPE_PROXY,
76 .private_data = npa,
79 ret = local_np_connect(
80 name,
81 NCACN_NP,
82 NULL,
83 remote_client_address,
84 NULL,
85 local_server_address,
86 session_info,
87 false,
88 npa,
89 &npa->stream);
90 if (ret != 0) {
91 DBG_DEBUG("local_np_connect failed: %s\n",
92 strerror(ret));
93 TALLOC_FREE(handle);
94 return map_nt_error_from_unix(ret);
97 *phandle = handle;
99 return NT_STATUS_OK;
102 bool np_read_in_progress(struct fake_file_handle *handle)
104 if (handle->type == FAKE_FILE_TYPE_NAMED_PIPE_PROXY) {
105 struct npa_state *p =
106 talloc_get_type_abort(handle->private_data,
107 struct npa_state);
108 size_t read_count;
110 read_count = tevent_queue_length(p->read_queue);
111 if (read_count > 0) {
112 return true;
115 return false;
118 return false;
121 struct np_write_state {
122 struct tevent_context *ev;
123 struct npa_state *p;
124 struct iovec iov;
125 ssize_t nwritten;
128 static void np_write_done(struct tevent_req *subreq);
130 struct tevent_req *np_write_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev,
131 struct fake_file_handle *handle,
132 const uint8_t *data, size_t len)
134 struct tevent_req *req;
135 struct np_write_state *state;
136 struct npa_state *p = NULL;
137 struct tevent_req *subreq = NULL;
139 DBG_INFO("len: %zu\n", len);
140 dump_data(50, data, len);
142 req = tevent_req_create(mem_ctx, &state, struct np_write_state);
143 if (req == NULL) {
144 return NULL;
147 if (handle->type != FAKE_FILE_TYPE_NAMED_PIPE_PROXY) {
148 tevent_req_nterror(req, NT_STATUS_INVALID_HANDLE);
149 return tevent_req_post(req, ev);
152 if (len == 0) {
153 state->nwritten = 0;
154 tevent_req_done(req);
155 return tevent_req_post(req, ev);
158 p = talloc_get_type_abort(handle->private_data, struct npa_state);
160 state->ev = ev;
161 state->p = p;
162 state->iov.iov_base = discard_const_p(void, data);
163 state->iov.iov_len = len;
165 subreq = tstream_writev_queue_send(
166 state, ev, p->stream, p->write_queue, &state->iov, 1);
167 if (tevent_req_nomem(subreq, req)) {
168 return tevent_req_post(req, ev);
170 tevent_req_set_callback(subreq, np_write_done, req);
171 return req;
174 static void np_write_done(struct tevent_req *subreq)
176 struct tevent_req *req = tevent_req_callback_data(
177 subreq, struct tevent_req);
178 struct np_write_state *state = tevent_req_data(
179 req, struct np_write_state);
180 ssize_t received;
181 int err;
183 received = tstream_writev_queue_recv(subreq, &err);
184 if (received < 0) {
185 tevent_req_nterror(req, map_nt_error_from_unix(err));
186 return;
188 state->nwritten = received;
189 tevent_req_done(req);
192 NTSTATUS np_write_recv(struct tevent_req *req, ssize_t *pnwritten)
194 struct np_write_state *state = tevent_req_data(
195 req, struct np_write_state);
196 NTSTATUS status;
198 if (tevent_req_is_nterror(req, &status)) {
199 return status;
201 *pnwritten = state->nwritten;
202 return NT_STATUS_OK;
205 struct np_ipc_readv_next_vector_state {
206 uint8_t *buf;
207 size_t len;
208 off_t ofs;
209 size_t remaining;
212 static void np_ipc_readv_next_vector_init(struct np_ipc_readv_next_vector_state *s,
213 uint8_t *buf, size_t len)
215 ZERO_STRUCTP(s);
217 s->buf = buf;
218 s->len = MIN(len, UINT16_MAX);
221 static int np_ipc_readv_next_vector(struct tstream_context *stream,
222 void *private_data,
223 TALLOC_CTX *mem_ctx,
224 struct iovec **_vector,
225 size_t *count)
227 struct np_ipc_readv_next_vector_state *state =
228 (struct np_ipc_readv_next_vector_state *)private_data;
229 struct iovec *vector;
230 ssize_t pending;
231 size_t wanted;
233 if (state->ofs == state->len) {
234 *_vector = NULL;
235 *count = 0;
236 return 0;
239 pending = tstream_pending_bytes(stream);
240 if (pending == -1) {
241 return -1;
244 if (pending == 0 && state->ofs != 0) {
245 /* return a short read */
246 *_vector = NULL;
247 *count = 0;
248 return 0;
251 if (pending == 0) {
252 /* we want at least one byte and recheck again */
253 wanted = 1;
254 } else {
255 size_t missing = state->len - state->ofs;
256 if (pending > missing) {
257 /* there's more available */
258 state->remaining = pending - missing;
259 wanted = missing;
260 } else {
261 /* read what we can get and recheck in the next cycle */
262 wanted = pending;
266 vector = talloc_array(mem_ctx, struct iovec, 1);
267 if (!vector) {
268 return -1;
271 vector[0].iov_base = state->buf + state->ofs;
272 vector[0].iov_len = wanted;
274 state->ofs += wanted;
276 *_vector = vector;
277 *count = 1;
278 return 0;
281 struct np_read_state {
282 struct npa_state *p;
283 struct np_ipc_readv_next_vector_state next_vector;
285 ssize_t nread;
286 bool is_data_outstanding;
289 static void np_read_done(struct tevent_req *subreq);
291 struct tevent_req *np_read_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev,
292 struct fake_file_handle *handle,
293 uint8_t *data, size_t len)
295 struct tevent_req *req;
296 struct np_read_state *state;
297 struct npa_state *p = NULL;
298 struct tevent_req *subreq = NULL;
300 req = tevent_req_create(mem_ctx, &state, struct np_read_state);
301 if (req == NULL) {
302 return NULL;
305 if (handle->type != FAKE_FILE_TYPE_NAMED_PIPE_PROXY) {
306 tevent_req_nterror(req, NT_STATUS_INVALID_HANDLE);
307 return tevent_req_post(req, ev);
310 p = talloc_get_type_abort(handle->private_data, struct npa_state);
312 np_ipc_readv_next_vector_init(&state->next_vector, data, len);
314 subreq = tstream_readv_pdu_queue_send(
315 state,
317 p->stream,
318 p->read_queue,
319 np_ipc_readv_next_vector,
320 &state->next_vector);
321 if (tevent_req_nomem(subreq, req)) {
322 return tevent_req_post(req, ev);
324 tevent_req_set_callback(subreq, np_read_done, req);
325 return req;
328 static void np_read_done(struct tevent_req *subreq)
330 struct tevent_req *req = tevent_req_callback_data(
331 subreq, struct tevent_req);
332 struct np_read_state *state = tevent_req_data(
333 req, struct np_read_state);
334 ssize_t ret;
335 int err;
337 ret = tstream_readv_pdu_queue_recv(subreq, &err);
338 TALLOC_FREE(subreq);
339 if (ret == -1) {
340 tevent_req_nterror(req, map_nt_error_from_unix(err));
341 return;
344 state->nread = ret;
345 state->is_data_outstanding = (state->next_vector.remaining > 0);
347 tevent_req_done(req);
348 return;
351 NTSTATUS np_read_recv(struct tevent_req *req, ssize_t *nread,
352 bool *is_data_outstanding)
354 struct np_read_state *state = tevent_req_data(
355 req, struct np_read_state);
356 NTSTATUS status;
358 if (tevent_req_is_nterror(req, &status)) {
359 return status;
362 DEBUG(10, ("Received %d bytes. There is %smore data outstanding\n",
363 (int)state->nread, state->is_data_outstanding?"":"no "));
365 *nread = state->nread;
366 *is_data_outstanding = state->is_data_outstanding;
367 return NT_STATUS_OK;