Line data Source code
1 : /*
2 : Unix SMB/CIFS implementation.
3 : raw dcerpc operations
4 :
5 : Copyright (C) Tim Potter 2003
6 : Copyright (C) Andrew Tridgell 2003-2005
7 : Copyright (C) Jelmer Vernooij 2004-2005
8 :
9 : This program is free software; you can redistribute it and/or modify
10 : it under the terms of the GNU General Public License as published by
11 : the Free Software Foundation; either version 3 of the License, or
12 : (at your option) any later version.
13 :
14 : This program is distributed in the hope that it will be useful,
15 : but WITHOUT ANY WARRANTY; without even the implied warranty of
16 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 : GNU General Public License for more details.
18 :
19 : You should have received a copy of the GNU General Public License
20 : along with this program. If not, see <http://www.gnu.org/licenses/>.
21 : */
22 :
23 : #include "includes.h"
24 : #include "system/filesys.h"
25 : #include "../lib/util/dlinklist.h"
26 : #include "lib/events/events.h"
27 : #include "librpc/rpc/dcerpc.h"
28 : #include "librpc/rpc/dcerpc_proto.h"
29 : #include "librpc/rpc/dcerpc_util.h"
30 : #include "librpc/rpc/dcerpc_pkt_auth.h"
31 : #include "librpc/gen_ndr/ndr_misc.h"
32 : #include "librpc/gen_ndr/ndr_dcerpc.h"
33 : #include "auth/gensec/gensec.h"
34 : #include "param/param.h"
35 : #include "lib/util/tevent_ntstatus.h"
36 : #include "librpc/rpc/rpc_common.h"
37 : #include "lib/tsocket/tsocket.h"
38 : #include "libcli/smb/tstream_smbXcli_np.h"
39 :
40 :
41 : enum rpc_request_state {
42 : RPC_REQUEST_QUEUED,
43 : RPC_REQUEST_PENDING,
44 : RPC_REQUEST_DONE
45 : };
46 :
47 : /*
48 : handle for an async dcerpc request
49 : */
50 : struct rpc_request {
51 : struct rpc_request *next, *prev;
52 : struct dcerpc_pipe *p;
53 : NTSTATUS status;
54 : uint32_t call_id;
55 : enum rpc_request_state state;
56 : DATA_BLOB payload;
57 : uint32_t flags;
58 : uint32_t fault_code;
59 :
60 : /* this is used to distinguish bind and alter_context requests
61 : from normal requests */
62 : void (*recv_handler)(struct rpc_request *conn,
63 : DATA_BLOB *blob, struct ncacn_packet *pkt);
64 :
65 : const struct GUID *object;
66 : uint16_t opnum;
67 : DATA_BLOB request_data;
68 : bool ignore_timeout;
69 : bool wait_for_sync;
70 : bool verify_bitmask1;
71 : bool verify_pcontext;
72 :
73 : struct {
74 : void (*callback)(struct rpc_request *);
75 : void *private_data;
76 : } async;
77 : };
78 :
79 6486 : _PUBLIC_ NTSTATUS dcerpc_init(void)
80 : {
81 6486 : return gensec_init();
82 : }
83 :
84 : static void dcerpc_connection_dead(struct dcecli_connection *conn, NTSTATUS status);
85 : static void dcerpc_schedule_io_trigger(struct dcecli_connection *c);
86 :
87 : static struct rpc_request *dcerpc_request_send(TALLOC_CTX *mem_ctx,
88 : struct dcerpc_pipe *p,
89 : const struct GUID *object,
90 : uint16_t opnum,
91 : DATA_BLOB *stub_data);
92 : static NTSTATUS dcerpc_request_recv(struct rpc_request *req,
93 : TALLOC_CTX *mem_ctx,
94 : DATA_BLOB *stub_data);
95 : static NTSTATUS dcerpc_ndr_validate_in(struct dcecli_connection *c,
96 : TALLOC_CTX *mem_ctx,
97 : DATA_BLOB blob,
98 : size_t struct_size,
99 : ndr_push_flags_fn_t ndr_push,
100 : ndr_pull_flags_fn_t ndr_pull);
101 : static NTSTATUS dcerpc_ndr_validate_out(struct dcecli_connection *c,
102 : struct ndr_pull *pull_in,
103 : void *struct_ptr,
104 : size_t struct_size,
105 : ndr_push_flags_fn_t ndr_push,
106 : ndr_pull_flags_fn_t ndr_pull,
107 : ndr_print_function_t ndr_print);
108 : static NTSTATUS dcerpc_shutdown_pipe(struct dcecli_connection *p, NTSTATUS status);
109 : static NTSTATUS dcerpc_send_request(struct dcecli_connection *p, DATA_BLOB *data,
110 : bool trigger_read);
111 : static NTSTATUS dcerpc_send_read(struct dcecli_connection *p);
112 :
113 : /* destroy a dcerpc connection */
114 24264 : static int dcerpc_connection_destructor(struct dcecli_connection *conn)
115 : {
116 24264 : if (conn->dead) {
117 0 : conn->free_skipped = true;
118 0 : return -1;
119 : }
120 24264 : dcerpc_connection_dead(conn, NT_STATUS_LOCAL_DISCONNECT);
121 24264 : return 0;
122 : }
123 :
124 :
125 : /* initialise a dcerpc connection.
126 : the event context is optional
127 : */
128 24284 : static struct dcecli_connection *dcerpc_connection_init(TALLOC_CTX *mem_ctx,
129 : struct tevent_context *ev)
130 : {
131 : struct dcecli_connection *c;
132 :
133 24284 : c = talloc_zero(mem_ctx, struct dcecli_connection);
134 24284 : if (!c) {
135 0 : return NULL;
136 : }
137 :
138 24284 : c->event_ctx = ev;
139 :
140 24284 : if (c->event_ctx == NULL) {
141 0 : talloc_free(c);
142 0 : return NULL;
143 : }
144 :
145 24284 : c->call_id = 1;
146 24284 : c->security_state.auth_type = DCERPC_AUTH_TYPE_NONE;
147 24284 : c->security_state.auth_level = DCERPC_AUTH_LEVEL_NONE;
148 24284 : c->security_state.auth_context_id = 0;
149 24284 : c->security_state.session_key = dcecli_generic_session_key;
150 24284 : c->security_state.generic_state = NULL;
151 24284 : c->flags = 0;
152 : /*
153 : * Windows uses 5840 for ncacn_ip_tcp,
154 : * so we also use it (for every transport)
155 : * by default. But we give the transport
156 : * the chance to overwrite it.
157 : */
158 24284 : c->srv_max_xmit_frag = 5840;
159 24284 : c->srv_max_recv_frag = 5840;
160 24284 : c->max_total_response_size = DCERPC_NCACN_RESPONSE_DEFAULT_MAX_SIZE;
161 24284 : c->pending = NULL;
162 :
163 24284 : c->io_trigger = tevent_create_immediate(c);
164 24284 : if (c->io_trigger == NULL) {
165 0 : talloc_free(c);
166 0 : return NULL;
167 : }
168 :
169 24284 : talloc_set_destructor(c, dcerpc_connection_destructor);
170 :
171 24284 : return c;
172 : }
173 :
174 : struct dcerpc_bh_state {
175 : struct dcerpc_pipe *p;
176 : };
177 :
178 166641 : static bool dcerpc_bh_is_connected(struct dcerpc_binding_handle *h)
179 : {
180 166641 : struct dcerpc_bh_state *hs = dcerpc_binding_handle_data(h,
181 : struct dcerpc_bh_state);
182 :
183 166641 : if (!hs->p) {
184 0 : return false;
185 : }
186 :
187 166641 : if (!hs->p->conn) {
188 0 : return false;
189 : }
190 :
191 166641 : if (hs->p->conn->dead) {
192 15 : return false;
193 : }
194 :
195 166626 : return true;
196 : }
197 :
198 934 : static uint32_t dcerpc_bh_set_timeout(struct dcerpc_binding_handle *h,
199 : uint32_t timeout)
200 : {
201 934 : struct dcerpc_bh_state *hs = dcerpc_binding_handle_data(h,
202 : struct dcerpc_bh_state);
203 : uint32_t old;
204 :
205 934 : if (!hs->p) {
206 0 : return DCERPC_REQUEST_TIMEOUT;
207 : }
208 :
209 934 : old = hs->p->request_timeout;
210 934 : hs->p->request_timeout = timeout;
211 :
212 934 : return old;
213 : }
214 :
215 719 : static void dcerpc_bh_auth_info(struct dcerpc_binding_handle *h,
216 : enum dcerpc_AuthType *auth_type,
217 : enum dcerpc_AuthLevel *auth_level)
218 : {
219 719 : struct dcerpc_bh_state *hs = dcerpc_binding_handle_data(h,
220 : struct dcerpc_bh_state);
221 :
222 719 : if (hs->p == NULL) {
223 0 : return;
224 : }
225 :
226 719 : if (hs->p->conn == NULL) {
227 0 : return;
228 : }
229 :
230 719 : *auth_type = hs->p->conn->security_state.auth_type;
231 719 : *auth_level = hs->p->conn->security_state.auth_level;
232 : }
233 :
234 : struct dcerpc_bh_raw_call_state {
235 : struct tevent_context *ev;
236 : struct dcerpc_binding_handle *h;
237 : DATA_BLOB in_data;
238 : DATA_BLOB out_data;
239 : uint32_t out_flags;
240 : };
241 :
242 : static void dcerpc_bh_raw_call_done(struct rpc_request *subreq);
243 :
244 161149 : static struct tevent_req *dcerpc_bh_raw_call_send(TALLOC_CTX *mem_ctx,
245 : struct tevent_context *ev,
246 : struct dcerpc_binding_handle *h,
247 : const struct GUID *object,
248 : uint32_t opnum,
249 : uint32_t in_flags,
250 : const uint8_t *in_data,
251 : size_t in_length)
252 : {
253 161149 : struct dcerpc_bh_state *hs = dcerpc_binding_handle_data(h,
254 : struct dcerpc_bh_state);
255 : struct tevent_req *req;
256 : struct dcerpc_bh_raw_call_state *state;
257 : bool ok;
258 : struct rpc_request *subreq;
259 :
260 161149 : req = tevent_req_create(mem_ctx, &state,
261 : struct dcerpc_bh_raw_call_state);
262 161149 : if (req == NULL) {
263 0 : return NULL;
264 : }
265 161149 : state->ev = ev;
266 161149 : state->h = h;
267 161149 : state->in_data.data = discard_const_p(uint8_t, in_data);
268 161149 : state->in_data.length = in_length;
269 :
270 161149 : ok = dcerpc_bh_is_connected(h);
271 161149 : if (!ok) {
272 0 : tevent_req_nterror(req, NT_STATUS_CONNECTION_DISCONNECTED);
273 0 : return tevent_req_post(req, ev);
274 : }
275 :
276 161149 : subreq = dcerpc_request_send(state,
277 : hs->p,
278 : object,
279 : opnum,
280 161149 : &state->in_data);
281 161149 : if (tevent_req_nomem(subreq, req)) {
282 0 : return tevent_req_post(req, ev);
283 : }
284 161149 : subreq->async.callback = dcerpc_bh_raw_call_done;
285 161149 : subreq->async.private_data = req;
286 :
287 161149 : return req;
288 : }
289 :
290 161149 : static void dcerpc_bh_raw_call_done(struct rpc_request *subreq)
291 : {
292 132913 : struct tevent_req *req =
293 161149 : talloc_get_type_abort(subreq->async.private_data,
294 : struct tevent_req);
295 132913 : struct dcerpc_bh_raw_call_state *state =
296 161149 : tevent_req_data(req,
297 : struct dcerpc_bh_raw_call_state);
298 : NTSTATUS status;
299 : uint32_t fault_code;
300 :
301 161149 : state->out_flags = 0;
302 161149 : if (subreq->flags & DCERPC_PULL_BIGENDIAN) {
303 0 : state->out_flags |= LIBNDR_FLAG_BIGENDIAN;
304 : }
305 :
306 161149 : fault_code = subreq->fault_code;
307 :
308 161149 : status = dcerpc_request_recv(subreq, state, &state->out_data);
309 161149 : if (NT_STATUS_EQUAL(status, NT_STATUS_NET_WRITE_FAULT)) {
310 14891 : status = dcerpc_fault_to_nt_status(fault_code);
311 : }
312 :
313 : /*
314 : * We trigger the callback in the next event run
315 : * because the code in this file might trigger
316 : * multiple request callbacks from within a single
317 : * while loop.
318 : *
319 : * In order to avoid segfaults from within
320 : * dcerpc_connection_dead() we call
321 : * tevent_req_defer_callback().
322 : */
323 161149 : tevent_req_defer_callback(req, state->ev);
324 :
325 161149 : if (!NT_STATUS_IS_OK(status)) {
326 14906 : tevent_req_nterror(req, status);
327 14906 : return;
328 : }
329 :
330 146243 : tevent_req_done(req);
331 : }
332 :
333 161149 : static NTSTATUS dcerpc_bh_raw_call_recv(struct tevent_req *req,
334 : TALLOC_CTX *mem_ctx,
335 : uint8_t **out_data,
336 : size_t *out_length,
337 : uint32_t *out_flags)
338 : {
339 132913 : struct dcerpc_bh_raw_call_state *state =
340 161149 : tevent_req_data(req,
341 : struct dcerpc_bh_raw_call_state);
342 : NTSTATUS status;
343 :
344 161149 : if (tevent_req_is_nterror(req, &status)) {
345 14906 : tevent_req_received(req);
346 14906 : return status;
347 : }
348 :
349 146243 : *out_data = talloc_move(mem_ctx, &state->out_data.data);
350 146243 : *out_length = state->out_data.length;
351 146243 : *out_flags = state->out_flags;
352 146243 : tevent_req_received(req);
353 146243 : return NT_STATUS_OK;
354 : }
355 :
356 : struct dcerpc_bh_disconnect_state {
357 : uint8_t _dummy;
358 : };
359 :
360 0 : static struct tevent_req *dcerpc_bh_disconnect_send(TALLOC_CTX *mem_ctx,
361 : struct tevent_context *ev,
362 : struct dcerpc_binding_handle *h)
363 : {
364 0 : struct dcerpc_bh_state *hs = dcerpc_binding_handle_data(h,
365 : struct dcerpc_bh_state);
366 : struct tevent_req *req;
367 : struct dcerpc_bh_disconnect_state *state;
368 : bool ok;
369 :
370 0 : req = tevent_req_create(mem_ctx, &state,
371 : struct dcerpc_bh_disconnect_state);
372 0 : if (req == NULL) {
373 0 : return NULL;
374 : }
375 :
376 0 : ok = dcerpc_bh_is_connected(h);
377 0 : if (!ok) {
378 0 : tevent_req_nterror(req, NT_STATUS_CONNECTION_DISCONNECTED);
379 0 : return tevent_req_post(req, ev);
380 : }
381 :
382 : /* TODO: do a real disconnect ... */
383 0 : hs->p = NULL;
384 :
385 0 : tevent_req_done(req);
386 0 : return tevent_req_post(req, ev);
387 : }
388 :
389 0 : static NTSTATUS dcerpc_bh_disconnect_recv(struct tevent_req *req)
390 : {
391 : NTSTATUS status;
392 :
393 0 : if (tevent_req_is_nterror(req, &status)) {
394 0 : tevent_req_received(req);
395 0 : return status;
396 : }
397 :
398 0 : tevent_req_received(req);
399 0 : return NT_STATUS_OK;
400 : }
401 :
402 161184 : static bool dcerpc_bh_push_bigendian(struct dcerpc_binding_handle *h)
403 : {
404 161184 : struct dcerpc_bh_state *hs = dcerpc_binding_handle_data(h,
405 : struct dcerpc_bh_state);
406 :
407 161184 : if (hs->p->conn->flags & DCERPC_PUSH_BIGENDIAN) {
408 21510 : return true;
409 : }
410 :
411 139674 : return false;
412 : }
413 :
414 161184 : static bool dcerpc_bh_ref_alloc(struct dcerpc_binding_handle *h)
415 : {
416 161184 : struct dcerpc_bh_state *hs = dcerpc_binding_handle_data(h,
417 : struct dcerpc_bh_state);
418 :
419 161184 : if (hs->p->conn->flags & DCERPC_NDR_REF_ALLOC) {
420 17067 : return true;
421 : }
422 :
423 144117 : return false;
424 : }
425 :
426 161184 : static bool dcerpc_bh_use_ndr64(struct dcerpc_binding_handle *h)
427 : {
428 161184 : struct dcerpc_bh_state *hs = dcerpc_binding_handle_data(h,
429 : struct dcerpc_bh_state);
430 :
431 161184 : if (hs->p->conn->flags & DCERPC_NDR64) {
432 0 : return true;
433 : }
434 :
435 161184 : return false;
436 : }
437 :
438 307420 : static void dcerpc_bh_do_ndr_print(struct dcerpc_binding_handle *h,
439 : int ndr_flags,
440 : const void *_struct_ptr,
441 : const struct ndr_interface_call *call)
442 : {
443 307420 : struct dcerpc_bh_state *hs = dcerpc_binding_handle_data(h,
444 : struct dcerpc_bh_state);
445 307420 : void *struct_ptr = discard_const(_struct_ptr);
446 307420 : bool print_in = false;
447 307420 : bool print_out = false;
448 :
449 307420 : if (hs->p->conn->flags & DCERPC_DEBUG_PRINT_IN) {
450 0 : print_in = true;
451 : }
452 :
453 307420 : if (hs->p->conn->flags & DCERPC_DEBUG_PRINT_OUT) {
454 0 : print_out = true;
455 : }
456 :
457 307420 : if (DEBUGLEVEL >= 11) {
458 0 : print_in = true;
459 0 : print_out = true;
460 : }
461 :
462 307420 : if (ndr_flags & NDR_IN) {
463 161184 : if (print_in) {
464 0 : ndr_print_function_debug(call->ndr_print,
465 0 : call->name,
466 : ndr_flags,
467 : struct_ptr);
468 : }
469 : }
470 307420 : if (ndr_flags & NDR_OUT) {
471 146236 : if (print_out) {
472 0 : ndr_print_function_debug(call->ndr_print,
473 0 : call->name,
474 : ndr_flags,
475 : struct_ptr);
476 : }
477 : }
478 307420 : }
479 :
480 42 : static void dcerpc_bh_ndr_push_failed(struct dcerpc_binding_handle *h,
481 : NTSTATUS error,
482 : const void *struct_ptr,
483 : const struct ndr_interface_call *call)
484 : {
485 42 : DEBUG(2,("Unable to ndr_push structure for %s - %s\n",
486 : call->name, nt_errstr(error)));
487 42 : }
488 :
489 0 : static void dcerpc_bh_ndr_pull_failed(struct dcerpc_binding_handle *h,
490 : NTSTATUS error,
491 : const DATA_BLOB *blob,
492 : const struct ndr_interface_call *call)
493 : {
494 0 : struct dcerpc_bh_state *hs = dcerpc_binding_handle_data(h,
495 : struct dcerpc_bh_state);
496 0 : const uint32_t num_examples = 20;
497 : uint32_t i;
498 :
499 0 : DEBUG(2,("Unable to ndr_pull structure for %s - %s\n",
500 : call->name, nt_errstr(error)));
501 :
502 0 : if (hs->p->conn->packet_log_dir == NULL) return;
503 :
504 0 : for (i=0;i<num_examples;i++) {
505 0 : char *name=NULL;
506 : int ret;
507 :
508 0 : ret = asprintf(&name, "%s/rpclog/%s-out.%d",
509 0 : hs->p->conn->packet_log_dir,
510 0 : call->name, i);
511 0 : if (ret == -1) {
512 0 : return;
513 : }
514 0 : if (!file_exist(name)) {
515 0 : if (file_save(name, blob->data, blob->length)) {
516 0 : DEBUG(10,("Logged rpc packet to %s\n", name));
517 : }
518 0 : free(name);
519 0 : break;
520 : }
521 0 : free(name);
522 : }
523 : }
524 :
525 161142 : static NTSTATUS dcerpc_bh_ndr_validate_in(struct dcerpc_binding_handle *h,
526 : TALLOC_CTX *mem_ctx,
527 : const DATA_BLOB *blob,
528 : const struct ndr_interface_call *call)
529 : {
530 161142 : struct dcerpc_bh_state *hs = dcerpc_binding_handle_data(h,
531 : struct dcerpc_bh_state);
532 :
533 161142 : if (hs->p->conn->flags & DCERPC_DEBUG_VALIDATE_IN) {
534 : NTSTATUS status;
535 :
536 18769 : status = dcerpc_ndr_validate_in(hs->p->conn,
537 : mem_ctx,
538 : *blob,
539 252 : call->struct_size,
540 252 : call->ndr_push,
541 252 : call->ndr_pull);
542 18769 : if (!NT_STATUS_IS_OK(status)) {
543 0 : DEBUG(0,("Validation [in] failed for %s - %s\n",
544 : call->name, nt_errstr(status)));
545 0 : return status;
546 : }
547 : }
548 :
549 161142 : DEBUG(10,("rpc request data:\n"));
550 161142 : dump_data(10, blob->data, blob->length);
551 :
552 161142 : return NT_STATUS_OK;
553 : }
554 :
555 146236 : static NTSTATUS dcerpc_bh_ndr_validate_out(struct dcerpc_binding_handle *h,
556 : struct ndr_pull *pull_in,
557 : const void *_struct_ptr,
558 : const struct ndr_interface_call *call)
559 : {
560 146236 : struct dcerpc_bh_state *hs = dcerpc_binding_handle_data(h,
561 : struct dcerpc_bh_state);
562 146236 : void *struct_ptr = discard_const(_struct_ptr);
563 :
564 146236 : DEBUG(10,("rpc reply data:\n"));
565 146236 : dump_data(10, pull_in->data, pull_in->data_size);
566 :
567 146236 : if (pull_in->offset != pull_in->data_size) {
568 0 : DEBUG(0,("Warning! ignoring %u unread bytes at ofs:%u (0x%08X) for %s!\n",
569 : pull_in->data_size - pull_in->offset,
570 : pull_in->offset, pull_in->offset,
571 : call->name));
572 : /* we used to return NT_STATUS_INFO_LENGTH_MISMATCH here,
573 : but it turns out that early versions of NT
574 : (specifically NT3.1) add junk onto the end of rpc
575 : packets, so if we want to interoperate at all with
576 : those versions then we need to ignore this error */
577 : }
578 :
579 146236 : if (hs->p->conn->flags & DCERPC_DEBUG_VALIDATE_OUT) {
580 : NTSTATUS status;
581 :
582 13832 : status = dcerpc_ndr_validate_out(hs->p->conn,
583 : pull_in,
584 : struct_ptr,
585 252 : call->struct_size,
586 252 : call->ndr_push,
587 252 : call->ndr_pull,
588 252 : call->ndr_print);
589 13832 : if (!NT_STATUS_IS_OK(status)) {
590 0 : DEBUG(2,("Validation [out] failed for %s - %s\n",
591 : call->name, nt_errstr(status)));
592 0 : return status;
593 : }
594 : }
595 :
596 146236 : return NT_STATUS_OK;
597 : }
598 :
599 : static const struct dcerpc_binding_handle_ops dcerpc_bh_ops = {
600 : .name = "dcerpc",
601 : .is_connected = dcerpc_bh_is_connected,
602 : .set_timeout = dcerpc_bh_set_timeout,
603 : .auth_info = dcerpc_bh_auth_info,
604 : .raw_call_send = dcerpc_bh_raw_call_send,
605 : .raw_call_recv = dcerpc_bh_raw_call_recv,
606 : .disconnect_send = dcerpc_bh_disconnect_send,
607 : .disconnect_recv = dcerpc_bh_disconnect_recv,
608 :
609 : .push_bigendian = dcerpc_bh_push_bigendian,
610 : .ref_alloc = dcerpc_bh_ref_alloc,
611 : .use_ndr64 = dcerpc_bh_use_ndr64,
612 : .do_ndr_print = dcerpc_bh_do_ndr_print,
613 : .ndr_push_failed = dcerpc_bh_ndr_push_failed,
614 : .ndr_pull_failed = dcerpc_bh_ndr_pull_failed,
615 : .ndr_validate_in = dcerpc_bh_ndr_validate_in,
616 : .ndr_validate_out = dcerpc_bh_ndr_validate_out,
617 : };
618 :
619 : /* initialise a dcerpc pipe. */
620 14508 : struct dcerpc_binding_handle *dcerpc_pipe_binding_handle(struct dcerpc_pipe *p,
621 : const struct GUID *object,
622 : const struct ndr_interface_table *table)
623 : {
624 : struct dcerpc_binding_handle *h;
625 : struct dcerpc_bh_state *hs;
626 :
627 14508 : h = dcerpc_binding_handle_create(p,
628 : &dcerpc_bh_ops,
629 : object,
630 : table,
631 : &hs,
632 : struct dcerpc_bh_state,
633 : __location__);
634 14508 : if (h == NULL) {
635 0 : return NULL;
636 : }
637 14508 : hs->p = p;
638 :
639 14508 : dcerpc_binding_handle_set_sync_ev(h, p->conn->event_ctx);
640 :
641 14508 : return h;
642 : }
643 :
644 : /* initialise a dcerpc pipe. */
645 24284 : _PUBLIC_ struct dcerpc_pipe *dcerpc_pipe_init(TALLOC_CTX *mem_ctx, struct tevent_context *ev)
646 : {
647 : struct dcerpc_pipe *p;
648 :
649 24284 : p = talloc_zero(mem_ctx, struct dcerpc_pipe);
650 24284 : if (!p) {
651 0 : return NULL;
652 : }
653 :
654 24284 : p->conn = dcerpc_connection_init(p, ev);
655 24284 : if (p->conn == NULL) {
656 0 : talloc_free(p);
657 0 : return NULL;
658 : }
659 :
660 24284 : p->request_timeout = DCERPC_REQUEST_TIMEOUT;
661 :
662 24284 : if (DEBUGLVL(100)) {
663 0 : p->conn->flags |= DCERPC_DEBUG_PRINT_BOTH;
664 : }
665 :
666 24284 : return p;
667 : }
668 :
669 :
670 : /*
671 : choose the next call id to use
672 : */
673 161258 : static uint32_t next_call_id(struct dcecli_connection *c)
674 : {
675 161258 : c->call_id++;
676 161258 : if (c->call_id == 0) {
677 0 : c->call_id++;
678 : }
679 161258 : return c->call_id;
680 : }
681 :
682 : /**
683 : setup for a ndr pull, also setting up any flags from the binding string
684 : */
685 32601 : static struct ndr_pull *ndr_pull_init_flags(struct dcecli_connection *c,
686 : DATA_BLOB *blob, TALLOC_CTX *mem_ctx)
687 : {
688 32601 : struct ndr_pull *ndr = ndr_pull_init_blob(blob, mem_ctx);
689 :
690 32601 : if (ndr == NULL) return ndr;
691 :
692 32601 : if (c->flags & DCERPC_DEBUG_PAD_CHECK) {
693 0 : ndr->flags |= LIBNDR_FLAG_PAD_CHECK;
694 : }
695 :
696 32601 : if (c->flags & DCERPC_NDR_REF_ALLOC) {
697 0 : ndr->flags |= LIBNDR_FLAG_REF_ALLOC;
698 : }
699 :
700 32601 : if (c->flags & DCERPC_NDR64) {
701 0 : ndr->flags |= LIBNDR_FLAG_NDR64;
702 : }
703 :
704 32601 : return ndr;
705 : }
706 :
707 : /*
708 : parse the authentication information on a dcerpc response packet
709 : */
710 372941 : static NTSTATUS ncacn_pull_pkt_auth(struct dcecli_connection *c,
711 : TALLOC_CTX *mem_ctx,
712 : enum dcerpc_pkt_type ptype,
713 : uint8_t required_flags,
714 : uint8_t optional_flags,
715 : uint8_t payload_offset,
716 : DATA_BLOB *payload_and_verifier,
717 : DATA_BLOB *raw_packet,
718 : const struct ncacn_packet *pkt)
719 : {
720 1387385 : const struct dcerpc_auth tmp_auth = {
721 372941 : .auth_type = c->security_state.auth_type,
722 372941 : .auth_level = c->security_state.auth_level,
723 372941 : .auth_context_id = c->security_state.auth_context_id,
724 : };
725 : NTSTATUS status;
726 :
727 372941 : status = dcerpc_ncacn_pull_pkt_auth(&tmp_auth,
728 : c->security_state.generic_state,
729 : true, /* check_pkt_auth_fields */
730 : mem_ctx,
731 : ptype,
732 : required_flags,
733 : optional_flags,
734 : payload_offset,
735 : payload_and_verifier,
736 : raw_packet,
737 : pkt);
738 372941 : if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_PROTOCOL_ERROR)) {
739 0 : return NT_STATUS_INVALID_NETWORK_RESPONSE;
740 : }
741 372941 : if (!NT_STATUS_IS_OK(status)) {
742 0 : return status;
743 : }
744 :
745 372941 : return NT_STATUS_OK;
746 : }
747 :
748 :
749 : /*
750 : push a dcerpc request packet into a blob, possibly signing it.
751 : */
752 173928 : static NTSTATUS ncacn_push_request_sign(struct dcecli_connection *c,
753 : DATA_BLOB *blob, TALLOC_CTX *mem_ctx,
754 : size_t sig_size,
755 : struct ncacn_packet *pkt)
756 : {
757 599544 : const struct dcerpc_auth tmp_auth = {
758 173928 : .auth_type = c->security_state.auth_type,
759 173928 : .auth_level = c->security_state.auth_level,
760 173928 : .auth_context_id = c->security_state.auth_context_id,
761 : };
762 : NTSTATUS status;
763 173928 : uint8_t payload_offset = DCERPC_REQUEST_LENGTH;
764 :
765 173928 : if (pkt->pfc_flags & DCERPC_PFC_FLAG_OBJECT_UUID) {
766 6 : payload_offset += 16;
767 : }
768 :
769 173928 : status = dcerpc_ncacn_push_pkt_auth(&tmp_auth,
770 : c->security_state.generic_state,
771 : mem_ctx, blob,
772 : sig_size,
773 : payload_offset,
774 173928 : &pkt->u.request.stub_and_verifier,
775 : pkt);
776 173928 : if (!NT_STATUS_IS_OK(status)) {
777 0 : return status;
778 : }
779 :
780 173928 : return NT_STATUS_OK;
781 : }
782 :
783 :
784 : /*
785 : fill in the fixed values in a dcerpc header
786 : */
787 180823 : static void init_ncacn_hdr(struct dcecli_connection *c, struct ncacn_packet *pkt)
788 : {
789 180823 : pkt->rpc_vers = 5;
790 180823 : pkt->rpc_vers_minor = 0;
791 180823 : if (c->flags & DCERPC_PUSH_BIGENDIAN) {
792 22999 : pkt->drep[0] = 0;
793 : } else {
794 157824 : pkt->drep[0] = DCERPC_DREP_LE;
795 : }
796 180823 : pkt->drep[1] = 0;
797 180823 : pkt->drep[2] = 0;
798 180823 : pkt->drep[3] = 0;
799 180823 : }
800 :
801 : /*
802 : map a bind nak reason to a NTSTATUS
803 : */
804 24 : static NTSTATUS dcerpc_map_nak_reason(enum dcerpc_bind_nak_reason reason)
805 : {
806 24 : switch (reason) {
807 0 : case DCERPC_BIND_NAK_REASON_PROTOCOL_VERSION_NOT_SUPPORTED:
808 0 : return NT_STATUS_REVISION_MISMATCH;
809 0 : case DCERPC_BIND_NAK_REASON_INVALID_AUTH_TYPE:
810 0 : return NT_STATUS_INVALID_PARAMETER;
811 24 : default:
812 24 : break;
813 : }
814 24 : return NT_STATUS_UNSUCCESSFUL;
815 : }
816 :
817 6 : static NTSTATUS dcerpc_map_ack_reason(const struct dcerpc_ack_ctx *ack)
818 : {
819 6 : if (ack == NULL) {
820 0 : return NT_STATUS_RPC_PROTOCOL_ERROR;
821 : }
822 :
823 6 : switch (ack->result) {
824 0 : case DCERPC_BIND_ACK_RESULT_NEGOTIATE_ACK:
825 : /*
826 : * We have not asked for this...
827 : */
828 0 : return NT_STATUS_RPC_PROTOCOL_ERROR;
829 6 : default:
830 6 : break;
831 : }
832 :
833 6 : switch (ack->reason.value) {
834 6 : case DCERPC_BIND_ACK_REASON_ABSTRACT_SYNTAX_NOT_SUPPORTED:
835 6 : return NT_STATUS_RPC_UNSUPPORTED_NAME_SYNTAX;
836 0 : case DCERPC_BIND_ACK_REASON_TRANSFER_SYNTAXES_NOT_SUPPORTED:
837 0 : return NT_STATUS_RPC_UNSUPPORTED_NAME_SYNTAX;
838 0 : default:
839 0 : break;
840 : }
841 0 : return NT_STATUS_UNSUCCESSFUL;
842 : }
843 :
844 : /*
845 : remove requests from the pending or queued queues
846 : */
847 361428 : static int dcerpc_req_dequeue(struct rpc_request *req)
848 : {
849 361428 : switch (req->state) {
850 0 : case RPC_REQUEST_QUEUED:
851 0 : DLIST_REMOVE(req->p->conn->request_queue, req);
852 0 : break;
853 180714 : case RPC_REQUEST_PENDING:
854 180714 : DLIST_REMOVE(req->p->conn->pending, req);
855 180714 : break;
856 180714 : case RPC_REQUEST_DONE:
857 180714 : break;
858 : }
859 361428 : return 0;
860 : }
861 :
862 :
863 : /*
864 : mark the dcerpc connection dead. All outstanding requests get an error
865 : */
866 24279 : static void dcerpc_connection_dead(struct dcecli_connection *conn, NTSTATUS status)
867 : {
868 24279 : if (conn->dead) return;
869 :
870 24279 : conn->dead = true;
871 :
872 24279 : TALLOC_FREE(conn->io_trigger);
873 24279 : conn->io_trigger_pending = false;
874 :
875 24279 : dcerpc_shutdown_pipe(conn, status);
876 :
877 : /* all pending requests get the error */
878 48573 : while (conn->pending) {
879 15 : struct rpc_request *req = conn->pending;
880 15 : dcerpc_req_dequeue(req);
881 15 : req->state = RPC_REQUEST_DONE;
882 15 : req->status = status;
883 15 : if (req->async.callback) {
884 15 : req->async.callback(req);
885 : }
886 : }
887 :
888 : /* all requests, which are not shipped */
889 48558 : while (conn->request_queue) {
890 0 : struct rpc_request *req = conn->request_queue;
891 0 : dcerpc_req_dequeue(req);
892 0 : req->state = RPC_REQUEST_DONE;
893 0 : req->status = status;
894 0 : if (req->async.callback) {
895 0 : req->async.callback(req);
896 : }
897 : }
898 :
899 24279 : talloc_set_destructor(conn, NULL);
900 24279 : if (conn->free_skipped) {
901 0 : talloc_free(conn);
902 : }
903 : }
904 :
905 : /*
906 : forward declarations of the recv_data handlers for the types of
907 : packets we need to handle
908 : */
909 : static void dcerpc_request_recv_data(struct dcecli_connection *c,
910 : DATA_BLOB *raw_packet, struct ncacn_packet *pkt);
911 :
912 : /*
913 : receive a dcerpc reply from the transport. Here we work out what
914 : type of reply it is (normal request, bind or alter context) and
915 : dispatch to the appropriate handler
916 : */
917 407412 : static void dcerpc_recv_data(struct dcecli_connection *conn, DATA_BLOB *blob, NTSTATUS status)
918 : {
919 : struct ncacn_packet pkt;
920 :
921 407412 : if (conn->dead) {
922 15 : return;
923 : }
924 :
925 407412 : if (NT_STATUS_IS_OK(status) && blob->length == 0) {
926 0 : status = NT_STATUS_UNEXPECTED_NETWORK_ERROR;
927 : }
928 :
929 : /* the transport may be telling us of a severe error, such as
930 : a dropped socket */
931 407412 : if (!NT_STATUS_IS_OK(status)) {
932 15 : data_blob_free(blob);
933 15 : dcerpc_connection_dead(conn, status);
934 15 : return;
935 : }
936 :
937 : /* parse the basic packet to work out what type of response this is */
938 407397 : status = dcerpc_pull_ncacn_packet(blob->data, blob, &pkt);
939 407397 : if (!NT_STATUS_IS_OK(status)) {
940 0 : data_blob_free(blob);
941 0 : dcerpc_connection_dead(conn, status);
942 0 : return;
943 : }
944 :
945 407397 : dcerpc_request_recv_data(conn, blob, &pkt);
946 : }
947 :
948 : /*
949 : handle timeouts of individual dcerpc requests
950 : */
951 0 : static void dcerpc_timeout_handler(struct tevent_context *ev, struct tevent_timer *te,
952 : struct timeval t, void *private_data)
953 : {
954 0 : struct rpc_request *req = talloc_get_type(private_data, struct rpc_request);
955 :
956 0 : if (req->ignore_timeout) {
957 0 : dcerpc_req_dequeue(req);
958 0 : req->state = RPC_REQUEST_DONE;
959 0 : req->status = NT_STATUS_IO_TIMEOUT;
960 0 : if (req->async.callback) {
961 0 : req->async.callback(req);
962 : }
963 0 : return;
964 : }
965 :
966 0 : dcerpc_connection_dead(req->p->conn, NT_STATUS_IO_TIMEOUT);
967 : }
968 :
969 : struct dcerpc_bind_state {
970 : struct tevent_context *ev;
971 : struct dcerpc_pipe *p;
972 : };
973 :
974 : static void dcerpc_bind_fail_handler(struct rpc_request *subreq);
975 : static void dcerpc_bind_recv_handler(struct rpc_request *subreq,
976 : DATA_BLOB *raw_packet,
977 : struct ncacn_packet *pkt);
978 :
979 14485 : struct tevent_req *dcerpc_bind_send(TALLOC_CTX *mem_ctx,
980 : struct tevent_context *ev,
981 : struct dcerpc_pipe *p,
982 : const struct ndr_syntax_id *syntax,
983 : const struct ndr_syntax_id *transfer_syntax)
984 : {
985 : struct tevent_req *req;
986 : struct dcerpc_bind_state *state;
987 : struct ncacn_packet pkt;
988 : DATA_BLOB blob;
989 : NTSTATUS status;
990 : struct rpc_request *subreq;
991 : uint32_t flags;
992 : struct ndr_syntax_id bind_time_features;
993 :
994 14485 : bind_time_features = dcerpc_construct_bind_time_features(
995 : DCERPC_BIND_TIME_SECURITY_CONTEXT_MULTIPLEXING |
996 : DCERPC_BIND_TIME_KEEP_CONNECTION_ON_ORPHAN);
997 :
998 14485 : req = tevent_req_create(mem_ctx, &state,
999 : struct dcerpc_bind_state);
1000 14485 : if (req == NULL) {
1001 0 : return NULL;
1002 : }
1003 :
1004 14485 : state->ev = ev;
1005 14485 : state->p = p;
1006 :
1007 14485 : p->syntax = *syntax;
1008 14485 : p->transfer_syntax = *transfer_syntax;
1009 :
1010 14485 : flags = dcerpc_binding_get_flags(p->binding);
1011 :
1012 14485 : init_ncacn_hdr(p->conn, &pkt);
1013 :
1014 14485 : pkt.ptype = DCERPC_PKT_BIND;
1015 14485 : pkt.pfc_flags = DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST;
1016 14485 : pkt.call_id = p->conn->call_id;
1017 14485 : pkt.auth_length = 0;
1018 :
1019 14485 : if (flags & DCERPC_CONCURRENT_MULTIPLEX) {
1020 51 : pkt.pfc_flags |= DCERPC_PFC_FLAG_CONC_MPX;
1021 : }
1022 :
1023 14485 : if (p->conn->flags & DCERPC_PROPOSE_HEADER_SIGNING) {
1024 6083 : pkt.pfc_flags |= DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN;
1025 : }
1026 :
1027 14485 : pkt.u.bind.max_xmit_frag = p->conn->srv_max_xmit_frag;
1028 14485 : pkt.u.bind.max_recv_frag = p->conn->srv_max_recv_frag;
1029 14485 : pkt.u.bind.assoc_group_id = dcerpc_binding_get_assoc_group_id(p->binding);
1030 14485 : pkt.u.bind.num_contexts = 2;
1031 14485 : pkt.u.bind.ctx_list = talloc_zero_array(state, struct dcerpc_ctx_list,
1032 : pkt.u.bind.num_contexts);
1033 14485 : if (tevent_req_nomem(pkt.u.bind.ctx_list, req)) {
1034 0 : return tevent_req_post(req, ev);
1035 : }
1036 14485 : pkt.u.bind.ctx_list[0].context_id = p->context_id;
1037 14485 : pkt.u.bind.ctx_list[0].num_transfer_syntaxes = 1;
1038 14485 : pkt.u.bind.ctx_list[0].abstract_syntax = p->syntax;
1039 14485 : pkt.u.bind.ctx_list[0].transfer_syntaxes = &p->transfer_syntax;
1040 14485 : pkt.u.bind.ctx_list[1].context_id = p->context_id + 1;
1041 14485 : pkt.u.bind.ctx_list[1].num_transfer_syntaxes = 1;
1042 14485 : pkt.u.bind.ctx_list[1].abstract_syntax = p->syntax;
1043 14485 : pkt.u.bind.ctx_list[1].transfer_syntaxes = &bind_time_features;
1044 14485 : pkt.u.bind.auth_info = data_blob(NULL, 0);
1045 :
1046 : /* construct the NDR form of the packet */
1047 14485 : status = dcerpc_ncacn_push_auth(&blob,
1048 : state,
1049 : &pkt,
1050 14485 : p->conn->security_state.tmp_auth_info.out);
1051 14485 : if (tevent_req_nterror(req, status)) {
1052 0 : return tevent_req_post(req, ev);
1053 : }
1054 :
1055 : /*
1056 : * we allocate a dcerpc_request so we can be in the same
1057 : * request queue as normal requests
1058 : */
1059 14485 : subreq = talloc_zero(state, struct rpc_request);
1060 14485 : if (tevent_req_nomem(subreq, req)) {
1061 0 : return tevent_req_post(req, ev);
1062 : }
1063 :
1064 14485 : subreq->state = RPC_REQUEST_PENDING;
1065 14485 : subreq->call_id = pkt.call_id;
1066 14485 : subreq->async.private_data = req;
1067 14485 : subreq->async.callback = dcerpc_bind_fail_handler;
1068 14485 : subreq->p = p;
1069 14485 : subreq->recv_handler = dcerpc_bind_recv_handler;
1070 14485 : DLIST_ADD_END(p->conn->pending, subreq);
1071 14485 : talloc_set_destructor(subreq, dcerpc_req_dequeue);
1072 :
1073 14485 : status = dcerpc_send_request(p->conn, &blob, true);
1074 14485 : if (tevent_req_nterror(req, status)) {
1075 0 : return tevent_req_post(req, ev);
1076 : }
1077 :
1078 14485 : tevent_add_timer(ev, subreq,
1079 : timeval_current_ofs(DCERPC_REQUEST_TIMEOUT, 0),
1080 : dcerpc_timeout_handler, subreq);
1081 :
1082 14485 : return req;
1083 : }
1084 :
1085 0 : static void dcerpc_bind_fail_handler(struct rpc_request *subreq)
1086 : {
1087 0 : struct tevent_req *req =
1088 0 : talloc_get_type_abort(subreq->async.private_data,
1089 : struct tevent_req);
1090 0 : struct dcerpc_bind_state *state =
1091 0 : tevent_req_data(req,
1092 : struct dcerpc_bind_state);
1093 0 : NTSTATUS status = subreq->status;
1094 :
1095 0 : TALLOC_FREE(subreq);
1096 :
1097 : /*
1098 : * We trigger the callback in the next event run
1099 : * because the code in this file might trigger
1100 : * multiple request callbacks from within a single
1101 : * while loop.
1102 : *
1103 : * In order to avoid segfaults from within
1104 : * dcerpc_connection_dead() we call
1105 : * tevent_req_defer_callback().
1106 : */
1107 0 : tevent_req_defer_callback(req, state->ev);
1108 :
1109 0 : tevent_req_nterror(req, status);
1110 0 : }
1111 :
1112 14485 : static void dcerpc_bind_recv_handler(struct rpc_request *subreq,
1113 : DATA_BLOB *raw_packet,
1114 : struct ncacn_packet *pkt)
1115 : {
1116 12611 : struct tevent_req *req =
1117 14485 : talloc_get_type_abort(subreq->async.private_data,
1118 : struct tevent_req);
1119 12611 : struct dcerpc_bind_state *state =
1120 14485 : tevent_req_data(req,
1121 : struct dcerpc_bind_state);
1122 14485 : struct dcecli_connection *conn = state->p->conn;
1123 14485 : struct dcecli_security *sec = &conn->security_state;
1124 14485 : struct dcerpc_binding *b = NULL;
1125 : NTSTATUS status;
1126 : uint32_t flags;
1127 :
1128 : /*
1129 : * Note that pkt is allocated under raw_packet->data,
1130 : * while raw_packet->data is a child of subreq.
1131 : */
1132 14485 : talloc_steal(state, raw_packet->data);
1133 14485 : TALLOC_FREE(subreq);
1134 :
1135 : /*
1136 : * We trigger the callback in the next event run
1137 : * because the code in this file might trigger
1138 : * multiple request callbacks from within a single
1139 : * while loop.
1140 : *
1141 : * In order to avoid segfaults from within
1142 : * dcerpc_connection_dead() we call
1143 : * tevent_req_defer_callback().
1144 : */
1145 14485 : tevent_req_defer_callback(req, state->ev);
1146 :
1147 14485 : if (pkt->ptype == DCERPC_PKT_BIND_NAK) {
1148 24 : status = dcerpc_map_nak_reason(pkt->u.bind_nak.reject_reason);
1149 :
1150 24 : DEBUG(2,("dcerpc: bind_nak reason %d - %s\n",
1151 : pkt->u.bind_nak.reject_reason, nt_errstr(status)));
1152 :
1153 24 : tevent_req_nterror(req, status);
1154 24 : return;
1155 : }
1156 :
1157 14461 : status = dcerpc_verify_ncacn_packet_header(pkt,
1158 : DCERPC_PKT_BIND_ACK,
1159 : pkt->u.bind_ack.auth_info.length,
1160 : DCERPC_PFC_FLAG_FIRST |
1161 : DCERPC_PFC_FLAG_LAST,
1162 : DCERPC_PFC_FLAG_CONC_MPX |
1163 : DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN);
1164 14461 : if (!NT_STATUS_IS_OK(status)) {
1165 0 : state->p->last_fault_code = DCERPC_NCA_S_PROTO_ERROR;
1166 0 : tevent_req_nterror(req, NT_STATUS_NET_WRITE_FAULT);
1167 0 : return;
1168 : }
1169 :
1170 14461 : if (pkt->u.bind_ack.num_results < 1) {
1171 0 : state->p->last_fault_code = DCERPC_NCA_S_PROTO_ERROR;
1172 0 : tevent_req_nterror(req, NT_STATUS_NET_WRITE_FAULT);
1173 0 : return;
1174 : }
1175 :
1176 14461 : if (pkt->u.bind_ack.ctx_list[0].result != 0) {
1177 0 : status = dcerpc_map_ack_reason(&pkt->u.bind_ack.ctx_list[0]);
1178 0 : DEBUG(2,("dcerpc: bind_ack failed - reason %d - %s\n",
1179 : pkt->u.bind_ack.ctx_list[0].reason.value,
1180 : nt_errstr(status)));
1181 0 : tevent_req_nterror(req, status);
1182 0 : return;
1183 : }
1184 :
1185 14461 : if (pkt->u.bind_ack.num_results >= 2) {
1186 14461 : if (pkt->u.bind_ack.ctx_list[1].result == DCERPC_BIND_ACK_RESULT_NEGOTIATE_ACK) {
1187 14461 : conn->bind_time_features = pkt->u.bind_ack.ctx_list[1].reason.negotiate;
1188 : } else {
1189 0 : status = dcerpc_map_ack_reason(&pkt->u.bind_ack.ctx_list[1]);
1190 0 : DEBUG(10,("dcerpc: bind_time_feature failed - reason %d - %s\n",
1191 : pkt->u.bind_ack.ctx_list[1].reason.value,
1192 : nt_errstr(status)));
1193 0 : status = NT_STATUS_OK;
1194 : }
1195 : }
1196 :
1197 : /*
1198 : * DCE-RPC 1.1 (c706) specifies
1199 : * CONST_MUST_RCV_FRAG_SIZE as 1432
1200 : */
1201 14461 : if (pkt->u.bind_ack.max_xmit_frag < 1432) {
1202 0 : state->p->last_fault_code = DCERPC_NCA_S_PROTO_ERROR;
1203 0 : tevent_req_nterror(req, NT_STATUS_NET_WRITE_FAULT);
1204 0 : return;
1205 : }
1206 14461 : if (pkt->u.bind_ack.max_recv_frag < 1432) {
1207 0 : state->p->last_fault_code = DCERPC_NCA_S_PROTO_ERROR;
1208 0 : tevent_req_nterror(req, NT_STATUS_NET_WRITE_FAULT);
1209 0 : return;
1210 : }
1211 14461 : conn->srv_max_xmit_frag = MIN(conn->srv_max_xmit_frag,
1212 : pkt->u.bind_ack.max_xmit_frag);
1213 14461 : conn->srv_max_recv_frag = MIN(conn->srv_max_recv_frag,
1214 : pkt->u.bind_ack.max_recv_frag);
1215 :
1216 14461 : flags = dcerpc_binding_get_flags(state->p->binding);
1217 :
1218 14461 : if (flags & DCERPC_CONCURRENT_MULTIPLEX) {
1219 51 : if (pkt->pfc_flags & DCERPC_PFC_FLAG_CONC_MPX) {
1220 51 : conn->flags |= DCERPC_CONCURRENT_MULTIPLEX;
1221 : } else {
1222 0 : conn->flags &= ~DCERPC_CONCURRENT_MULTIPLEX;
1223 : }
1224 : }
1225 :
1226 14461 : if (!(conn->flags & DCERPC_CONCURRENT_MULTIPLEX)) {
1227 14410 : struct dcerpc_binding *pb =
1228 14410 : discard_const_p(struct dcerpc_binding, state->p->binding);
1229 : /*
1230 : * clear DCERPC_CONCURRENT_MULTIPLEX
1231 : */
1232 14410 : status = dcerpc_binding_set_flags(pb, 0,
1233 : DCERPC_CONCURRENT_MULTIPLEX);
1234 14410 : if (tevent_req_nterror(req, status)) {
1235 0 : return;
1236 : }
1237 : }
1238 19932 : if ((conn->flags & DCERPC_PROPOSE_HEADER_SIGNING) &&
1239 6071 : (pkt->pfc_flags & DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN)) {
1240 5517 : conn->flags |= DCERPC_HEADER_SIGNING;
1241 : }
1242 :
1243 : /* the bind_ack might contain a reply set of credentials */
1244 14461 : if (pkt->auth_length != 0 && sec->tmp_auth_info.in != NULL) {
1245 12182 : status = dcerpc_pull_auth_trailer(pkt, sec->tmp_auth_info.mem,
1246 6481 : &pkt->u.bind_ack.auth_info,
1247 : sec->tmp_auth_info.in,
1248 : NULL, true);
1249 6481 : if (tevent_req_nterror(req, status)) {
1250 0 : return;
1251 : }
1252 : }
1253 :
1254 : /*
1255 : * We're the owner of the binding, so we're allowed to modify it.
1256 : */
1257 14461 : b = discard_const_p(struct dcerpc_binding, state->p->binding);
1258 14461 : status = dcerpc_binding_set_assoc_group_id(b,
1259 : pkt->u.bind_ack.assoc_group_id);
1260 14461 : if (tevent_req_nterror(req, status)) {
1261 0 : return;
1262 : }
1263 :
1264 14461 : tevent_req_done(req);
1265 : }
1266 :
1267 14485 : NTSTATUS dcerpc_bind_recv(struct tevent_req *req)
1268 : {
1269 14485 : return tevent_req_simple_recv_ntstatus(req);
1270 : }
1271 :
1272 : /*
1273 : perform a continued bind (and auth3)
1274 : */
1275 109 : NTSTATUS dcerpc_auth3(struct dcerpc_pipe *p,
1276 : TALLOC_CTX *mem_ctx)
1277 : {
1278 : struct ncacn_packet pkt;
1279 : NTSTATUS status;
1280 : DATA_BLOB blob;
1281 : uint32_t flags;
1282 :
1283 109 : flags = dcerpc_binding_get_flags(p->binding);
1284 :
1285 109 : init_ncacn_hdr(p->conn, &pkt);
1286 :
1287 109 : pkt.ptype = DCERPC_PKT_AUTH3;
1288 109 : pkt.pfc_flags = DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST;
1289 109 : pkt.call_id = next_call_id(p->conn);
1290 109 : pkt.auth_length = 0;
1291 109 : pkt.u.auth3.auth_info = data_blob(NULL, 0);
1292 :
1293 109 : if (flags & DCERPC_CONCURRENT_MULTIPLEX) {
1294 4 : pkt.pfc_flags |= DCERPC_PFC_FLAG_CONC_MPX;
1295 : }
1296 :
1297 : /* construct the NDR form of the packet */
1298 109 : status = dcerpc_ncacn_push_auth(&blob,
1299 : mem_ctx,
1300 : &pkt,
1301 109 : p->conn->security_state.tmp_auth_info.out);
1302 109 : if (!NT_STATUS_IS_OK(status)) {
1303 0 : return status;
1304 : }
1305 :
1306 : /* send it on its way */
1307 109 : status = dcerpc_send_request(p->conn, &blob, false);
1308 109 : if (!NT_STATUS_IS_OK(status)) {
1309 0 : return status;
1310 : }
1311 :
1312 109 : return NT_STATUS_OK;
1313 : }
1314 :
1315 :
1316 : /*
1317 : process a fragment received from the transport layer during a
1318 : request
1319 :
1320 : This function frees the data
1321 : */
1322 407397 : static void dcerpc_request_recv_data(struct dcecli_connection *c,
1323 : DATA_BLOB *raw_packet, struct ncacn_packet *pkt)
1324 : {
1325 : struct rpc_request *req;
1326 : unsigned int length;
1327 407397 : NTSTATUS status = NT_STATUS_OK;
1328 :
1329 : /*
1330 : if this is an authenticated connection then parse and check
1331 : the auth info. We have to do this before finding the
1332 : matching packet, as the request structure might have been
1333 : removed due to a timeout, but if it has been we still need
1334 : to run the auth routines so that we don't get the sign/seal
1335 : info out of step with the server
1336 : */
1337 407397 : switch (pkt->ptype) {
1338 372941 : case DCERPC_PKT_RESPONSE:
1339 372941 : status = ncacn_pull_pkt_auth(c, raw_packet->data,
1340 : DCERPC_PKT_RESPONSE,
1341 : 0, /* required_flags */
1342 : DCERPC_PFC_FLAG_FIRST |
1343 : DCERPC_PFC_FLAG_LAST,
1344 : DCERPC_REQUEST_LENGTH,
1345 : &pkt->u.response.stub_and_verifier,
1346 : raw_packet, pkt);
1347 372941 : break;
1348 34456 : default:
1349 34456 : break;
1350 : }
1351 :
1352 : /* find the matching request */
1353 414747 : for (req=c->pending;req;req=req->next) {
1354 414747 : if (pkt->call_id == req->call_id) break;
1355 : }
1356 :
1357 : #if 0
1358 : /* useful for testing certain vendors RPC servers */
1359 : if (req == NULL && c->pending && pkt->call_id == 0) {
1360 : DEBUG(0,("HACK FOR INCORRECT CALL ID\n"));
1361 : req = c->pending;
1362 : }
1363 : #endif
1364 :
1365 407397 : if (req == NULL) {
1366 0 : DEBUG(2,("dcerpc_request: unmatched call_id %u in response packet\n", pkt->call_id));
1367 0 : data_blob_free(raw_packet);
1368 9024 : return;
1369 : }
1370 :
1371 407397 : talloc_steal(req, raw_packet->data);
1372 :
1373 407397 : if (req->recv_handler != NULL) {
1374 19565 : dcerpc_req_dequeue(req);
1375 19565 : req->state = RPC_REQUEST_DONE;
1376 :
1377 : /*
1378 : * We have to look at shipping further requests before calling
1379 : * the async function, that one might close the pipe
1380 : */
1381 19565 : dcerpc_schedule_io_trigger(c);
1382 :
1383 19565 : req->recv_handler(req, raw_packet, pkt);
1384 19565 : return;
1385 : }
1386 :
1387 387832 : if (pkt->ptype == DCERPC_PKT_FAULT) {
1388 14891 : status = dcerpc_fault_to_nt_status(pkt->u.fault.status);
1389 14891 : DEBUG(5,("rpc fault: %s\n", dcerpc_errstr(c, pkt->u.fault.status)));
1390 14891 : if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_PROTOCOL_ERROR)) {
1391 0 : dcerpc_connection_dead(c, status);
1392 0 : return;
1393 : }
1394 14891 : if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_SEC_PKG_ERROR)) {
1395 0 : dcerpc_connection_dead(c, status);
1396 0 : return;
1397 : }
1398 14891 : req->fault_code = pkt->u.fault.status;
1399 14891 : req->status = NT_STATUS_NET_WRITE_FAULT;
1400 14891 : goto req_done;
1401 : }
1402 :
1403 372941 : if (pkt->ptype != DCERPC_PKT_RESPONSE) {
1404 0 : DEBUG(2,("Unexpected packet type %d in dcerpc response\n",
1405 : (int)pkt->ptype));
1406 0 : dcerpc_connection_dead(c, NT_STATUS_RPC_PROTOCOL_ERROR);
1407 0 : return;
1408 : }
1409 :
1410 : /* now check the status from the auth routines, and if it failed then fail
1411 : this request accordingly */
1412 372941 : if (!NT_STATUS_IS_OK(status)) {
1413 0 : dcerpc_connection_dead(c, status);
1414 0 : return;
1415 : }
1416 :
1417 372941 : length = pkt->u.response.stub_and_verifier.length;
1418 :
1419 372941 : if (req->payload.length + length > c->max_total_response_size) {
1420 0 : DEBUG(2,("Unexpected total payload 0x%X > 0x%X dcerpc response\n",
1421 : (unsigned)req->payload.length + length,
1422 : (unsigned)c->max_total_response_size));
1423 0 : dcerpc_connection_dead(c, NT_STATUS_RPC_PROTOCOL_ERROR);
1424 0 : return;
1425 : }
1426 :
1427 372941 : if (length > 0) {
1428 372682 : req->payload.data = talloc_realloc(req,
1429 : req->payload.data,
1430 : uint8_t,
1431 : req->payload.length + length);
1432 372682 : if (!req->payload.data) {
1433 0 : req->status = NT_STATUS_NO_MEMORY;
1434 0 : goto req_done;
1435 : }
1436 710671 : memcpy(req->payload.data+req->payload.length,
1437 372682 : pkt->u.response.stub_and_verifier.data, length);
1438 372682 : req->payload.length += length;
1439 : }
1440 :
1441 372941 : if (!(pkt->pfc_flags & DCERPC_PFC_FLAG_LAST)) {
1442 226698 : data_blob_free(raw_packet);
1443 226698 : dcerpc_send_read(c);
1444 226698 : return;
1445 : }
1446 :
1447 146243 : if (req->verify_bitmask1) {
1448 5992 : req->p->conn->security_state.verified_bitmask1 = true;
1449 : }
1450 146243 : if (req->verify_pcontext) {
1451 5996 : req->p->verified_pcontext = true;
1452 : }
1453 :
1454 146243 : if (!(pkt->drep[0] & DCERPC_DREP_LE)) {
1455 0 : req->flags |= DCERPC_PULL_BIGENDIAN;
1456 : } else {
1457 146243 : req->flags &= ~DCERPC_PULL_BIGENDIAN;
1458 : }
1459 :
1460 161134 : req_done:
1461 161134 : data_blob_free(raw_packet);
1462 :
1463 : /* we've got the full payload */
1464 161134 : dcerpc_req_dequeue(req);
1465 161134 : req->state = RPC_REQUEST_DONE;
1466 :
1467 : /*
1468 : * We have to look at shipping further requests before calling
1469 : * the async function, that one might close the pipe
1470 : */
1471 161134 : dcerpc_schedule_io_trigger(c);
1472 :
1473 161134 : if (req->async.callback) {
1474 161134 : req->async.callback(req);
1475 : }
1476 : }
1477 :
1478 : static NTSTATUS dcerpc_request_prepare_vt(struct rpc_request *req);
1479 :
1480 : /*
1481 : perform the send side of a async dcerpc request
1482 : */
1483 161149 : static struct rpc_request *dcerpc_request_send(TALLOC_CTX *mem_ctx,
1484 : struct dcerpc_pipe *p,
1485 : const struct GUID *object,
1486 : uint16_t opnum,
1487 : DATA_BLOB *stub_data)
1488 : {
1489 : struct rpc_request *req;
1490 : NTSTATUS status;
1491 :
1492 161149 : req = talloc_zero(mem_ctx, struct rpc_request);
1493 161149 : if (req == NULL) {
1494 0 : return NULL;
1495 : }
1496 :
1497 161149 : req->p = p;
1498 161149 : req->call_id = next_call_id(p->conn);
1499 161149 : req->state = RPC_REQUEST_QUEUED;
1500 :
1501 161149 : if (object != NULL) {
1502 6 : req->object = (struct GUID *)talloc_memdup(req, (const void *)object, sizeof(*object));
1503 6 : if (req->object == NULL) {
1504 0 : talloc_free(req);
1505 0 : return NULL;
1506 : }
1507 : }
1508 :
1509 161149 : req->opnum = opnum;
1510 161149 : req->request_data.length = stub_data->length;
1511 161149 : req->request_data.data = stub_data->data;
1512 :
1513 161149 : status = dcerpc_request_prepare_vt(req);
1514 161149 : if (!NT_STATUS_IS_OK(status)) {
1515 0 : talloc_free(req);
1516 0 : return NULL;
1517 : }
1518 :
1519 161149 : DLIST_ADD_END(p->conn->request_queue, req);
1520 161149 : talloc_set_destructor(req, dcerpc_req_dequeue);
1521 :
1522 161149 : dcerpc_schedule_io_trigger(p->conn);
1523 :
1524 161149 : if (p->request_timeout) {
1525 161149 : tevent_add_timer(p->conn->event_ctx, req,
1526 : timeval_current_ofs(p->request_timeout, 0),
1527 : dcerpc_timeout_handler, req);
1528 : }
1529 :
1530 161149 : return req;
1531 : }
1532 :
1533 161149 : static NTSTATUS dcerpc_request_prepare_vt(struct rpc_request *req)
1534 : {
1535 161149 : struct dcecli_security *sec = &req->p->conn->security_state;
1536 : struct dcerpc_sec_verification_trailer *t;
1537 161149 : struct dcerpc_sec_vt *c = NULL;
1538 161149 : struct ndr_push *ndr = NULL;
1539 : enum ndr_err_code ndr_err;
1540 :
1541 161149 : if (sec->auth_level < DCERPC_AUTH_LEVEL_PACKET) {
1542 90020 : return NT_STATUS_OK;
1543 : }
1544 :
1545 71129 : t = talloc_zero(req, struct dcerpc_sec_verification_trailer);
1546 71129 : if (t == NULL) {
1547 0 : return NT_STATUS_NO_MEMORY;
1548 : }
1549 :
1550 71129 : if (!sec->verified_bitmask1) {
1551 6481 : t->commands = talloc_realloc(t, t->commands,
1552 : struct dcerpc_sec_vt,
1553 : t->count.count + 1);
1554 6481 : if (t->commands == NULL) {
1555 0 : return NT_STATUS_NO_MEMORY;
1556 : }
1557 6481 : c = &t->commands[t->count.count++];
1558 6481 : ZERO_STRUCTP(c);
1559 :
1560 6481 : c->command = DCERPC_SEC_VT_COMMAND_BITMASK1;
1561 6481 : if (req->p->conn->flags & DCERPC_PROPOSE_HEADER_SIGNING) {
1562 6481 : c->u.bitmask1 = DCERPC_SEC_VT_CLIENT_SUPPORTS_HEADER_SIGNING;
1563 : }
1564 6481 : req->verify_bitmask1 = true;
1565 : }
1566 :
1567 71129 : if (!req->p->verified_pcontext) {
1568 6485 : t->commands = talloc_realloc(t, t->commands,
1569 : struct dcerpc_sec_vt,
1570 : t->count.count + 1);
1571 6485 : if (t->commands == NULL) {
1572 0 : return NT_STATUS_NO_MEMORY;
1573 : }
1574 6485 : c = &t->commands[t->count.count++];
1575 6485 : ZERO_STRUCTP(c);
1576 :
1577 6485 : c->command = DCERPC_SEC_VT_COMMAND_PCONTEXT;
1578 6485 : c->u.pcontext.abstract_syntax = req->p->syntax;
1579 6485 : c->u.pcontext.transfer_syntax = req->p->transfer_syntax;
1580 :
1581 6485 : req->verify_pcontext = true;
1582 : }
1583 :
1584 71129 : if (!(req->p->conn->flags & DCERPC_HEADER_SIGNING)) {
1585 7440 : t->commands = talloc_realloc(t, t->commands,
1586 : struct dcerpc_sec_vt,
1587 : t->count.count + 1);
1588 7440 : if (t->commands == NULL) {
1589 0 : return NT_STATUS_NO_MEMORY;
1590 : }
1591 7440 : c = &t->commands[t->count.count++];
1592 7440 : ZERO_STRUCTP(c);
1593 :
1594 7440 : c->command = DCERPC_SEC_VT_COMMAND_HEADER2;
1595 7440 : c->u.header2.ptype = DCERPC_PKT_REQUEST;
1596 7440 : if (req->p->conn->flags & DCERPC_PUSH_BIGENDIAN) {
1597 168 : c->u.header2.drep[0] = 0;
1598 : } else {
1599 7272 : c->u.header2.drep[0] = DCERPC_DREP_LE;
1600 : }
1601 7440 : c->u.header2.drep[1] = 0;
1602 7440 : c->u.header2.drep[2] = 0;
1603 7440 : c->u.header2.drep[3] = 0;
1604 7440 : c->u.header2.call_id = req->call_id;
1605 7440 : c->u.header2.context_id = req->p->context_id;
1606 7440 : c->u.header2.opnum = req->opnum;
1607 : }
1608 :
1609 71129 : if (t->count.count == 0) {
1610 57762 : TALLOC_FREE(t);
1611 57762 : return NT_STATUS_OK;
1612 : }
1613 :
1614 13367 : c = &t->commands[t->count.count - 1];
1615 13367 : c->command |= DCERPC_SEC_VT_COMMAND_END;
1616 :
1617 13367 : if (DEBUGLEVEL >= 10) {
1618 0 : NDR_PRINT_DEBUG(dcerpc_sec_verification_trailer, t);
1619 : }
1620 :
1621 13367 : ndr = ndr_push_init_ctx(req);
1622 13367 : if (ndr == NULL) {
1623 0 : return NT_STATUS_NO_MEMORY;
1624 : }
1625 :
1626 : /*
1627 : * for now we just copy and append
1628 : */
1629 :
1630 13367 : ndr_err = ndr_push_bytes(ndr, req->request_data.data,
1631 13367 : req->request_data.length);
1632 13367 : if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1633 0 : return ndr_map_error2ntstatus(ndr_err);
1634 : }
1635 :
1636 13367 : ndr_err = ndr_push_dcerpc_sec_verification_trailer(ndr,
1637 : NDR_SCALARS | NDR_BUFFERS,
1638 : t);
1639 13367 : if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1640 0 : return ndr_map_error2ntstatus(ndr_err);
1641 : }
1642 13367 : req->request_data = ndr_push_blob(ndr);
1643 :
1644 13367 : return NT_STATUS_OK;
1645 : }
1646 :
1647 : /*
1648 : Send a request using the transport
1649 : */
1650 :
1651 321914 : static void dcerpc_ship_next_request(struct dcecli_connection *c)
1652 : {
1653 : struct rpc_request *req;
1654 : struct dcerpc_pipe *p;
1655 : DATA_BLOB *stub_data;
1656 : struct ncacn_packet pkt;
1657 : DATA_BLOB blob;
1658 : uint32_t remaining, chunk_size;
1659 321914 : bool first_packet = true;
1660 321914 : size_t sig_size = 0;
1661 321914 : bool need_async = false;
1662 321914 : bool can_async = true;
1663 :
1664 321914 : req = c->request_queue;
1665 321914 : if (req == NULL) {
1666 293316 : return;
1667 : }
1668 :
1669 161149 : p = req->p;
1670 161149 : stub_data = &req->request_data;
1671 :
1672 161149 : if (c->pending) {
1673 388 : need_async = true;
1674 : }
1675 :
1676 161149 : if (c->security_state.auth_level >= DCERPC_AUTH_LEVEL_PACKET) {
1677 71129 : can_async = gensec_have_feature(c->security_state.generic_state,
1678 : GENSEC_FEATURE_ASYNC_REPLIES);
1679 : }
1680 :
1681 161149 : if (need_async && !can_async) {
1682 0 : req->wait_for_sync = true;
1683 0 : return;
1684 : }
1685 :
1686 161149 : DLIST_REMOVE(c->request_queue, req);
1687 161149 : DLIST_ADD(c->pending, req);
1688 161149 : req->state = RPC_REQUEST_PENDING;
1689 :
1690 161149 : init_ncacn_hdr(p->conn, &pkt);
1691 :
1692 161149 : remaining = stub_data->length;
1693 :
1694 : /* we can write a full max_recv_frag size, minus the dcerpc
1695 : request header size */
1696 161149 : chunk_size = p->conn->srv_max_recv_frag;
1697 161149 : chunk_size -= DCERPC_REQUEST_LENGTH;
1698 161149 : if (c->security_state.auth_level >= DCERPC_AUTH_LEVEL_PACKET) {
1699 71129 : size_t max_payload = chunk_size;
1700 :
1701 71129 : max_payload -= DCERPC_AUTH_TRAILER_LENGTH;
1702 71129 : max_payload -= (max_payload % DCERPC_AUTH_PAD_ALIGNMENT);
1703 :
1704 71129 : sig_size = gensec_sig_size(c->security_state.generic_state,
1705 : max_payload);
1706 71129 : if (sig_size) {
1707 71129 : chunk_size -= DCERPC_AUTH_TRAILER_LENGTH;
1708 71129 : chunk_size -= sig_size;
1709 : }
1710 : }
1711 161149 : chunk_size -= (chunk_size % DCERPC_AUTH_PAD_ALIGNMENT);
1712 :
1713 161149 : pkt.ptype = DCERPC_PKT_REQUEST;
1714 161149 : pkt.call_id = req->call_id;
1715 161149 : pkt.auth_length = 0;
1716 161149 : pkt.pfc_flags = 0;
1717 161149 : pkt.u.request.context_id = p->context_id;
1718 161149 : pkt.u.request.opnum = req->opnum;
1719 :
1720 161149 : if (req->object) {
1721 6 : pkt.u.request.object.object = *req->object;
1722 6 : pkt.pfc_flags |= DCERPC_PFC_FLAG_OBJECT_UUID;
1723 6 : chunk_size -= ndr_size_GUID(req->object,0);
1724 : }
1725 :
1726 : /* we send a series of pdus without waiting for a reply */
1727 467990 : while (remaining > 0 || first_packet) {
1728 173928 : uint32_t chunk = MIN(chunk_size, remaining);
1729 173928 : bool last_frag = false;
1730 173928 : bool do_trans = false;
1731 :
1732 173928 : first_packet = false;
1733 173928 : pkt.pfc_flags &= ~(DCERPC_PFC_FLAG_FIRST |DCERPC_PFC_FLAG_LAST);
1734 :
1735 173928 : if (remaining == stub_data->length) {
1736 161149 : pkt.pfc_flags |= DCERPC_PFC_FLAG_FIRST;
1737 : }
1738 173928 : if (chunk == remaining) {
1739 161149 : pkt.pfc_flags |= DCERPC_PFC_FLAG_LAST;
1740 161149 : last_frag = true;
1741 : }
1742 :
1743 173928 : pkt.u.request.alloc_hint = remaining;
1744 315800 : pkt.u.request.stub_and_verifier.data = stub_data->data +
1745 173928 : (stub_data->length - remaining);
1746 173928 : pkt.u.request.stub_and_verifier.length = chunk;
1747 :
1748 173928 : req->status = ncacn_push_request_sign(p->conn, &blob, req, sig_size, &pkt);
1749 173928 : if (!NT_STATUS_IS_OK(req->status)) {
1750 0 : req->state = RPC_REQUEST_DONE;
1751 0 : DLIST_REMOVE(p->conn->pending, req);
1752 0 : return;
1753 : }
1754 :
1755 173928 : if (last_frag && !need_async) {
1756 160761 : do_trans = true;
1757 : }
1758 :
1759 173928 : req->status = dcerpc_send_request(p->conn, &blob, do_trans);
1760 173928 : if (!NT_STATUS_IS_OK(req->status)) {
1761 0 : req->state = RPC_REQUEST_DONE;
1762 0 : DLIST_REMOVE(p->conn->pending, req);
1763 0 : return;
1764 : }
1765 :
1766 173928 : if (last_frag && !do_trans) {
1767 388 : req->status = dcerpc_send_read(p->conn);
1768 388 : if (!NT_STATUS_IS_OK(req->status)) {
1769 0 : req->state = RPC_REQUEST_DONE;
1770 0 : DLIST_REMOVE(p->conn->pending, req);
1771 0 : return;
1772 : }
1773 : }
1774 :
1775 173928 : remaining -= chunk;
1776 : }
1777 : }
1778 :
1779 321914 : static void dcerpc_io_trigger(struct tevent_context *ctx,
1780 : struct tevent_immediate *im,
1781 : void *private_data)
1782 : {
1783 265464 : struct dcecli_connection *c =
1784 56450 : talloc_get_type_abort(private_data,
1785 : struct dcecli_connection);
1786 :
1787 321914 : c->io_trigger_pending = false;
1788 :
1789 321914 : dcerpc_schedule_io_trigger(c);
1790 :
1791 321914 : dcerpc_ship_next_request(c);
1792 321914 : }
1793 :
1794 663762 : static void dcerpc_schedule_io_trigger(struct dcecli_connection *c)
1795 : {
1796 663762 : if (c->dead) {
1797 0 : return;
1798 : }
1799 :
1800 663762 : if (c->request_queue == NULL) {
1801 341464 : return;
1802 : }
1803 :
1804 322298 : if (c->request_queue->wait_for_sync && c->pending) {
1805 0 : return;
1806 : }
1807 :
1808 322298 : if (c->io_trigger_pending) {
1809 384 : return;
1810 : }
1811 :
1812 321914 : c->io_trigger_pending = true;
1813 :
1814 321914 : tevent_schedule_immediate(c->io_trigger,
1815 : c->event_ctx,
1816 : dcerpc_io_trigger,
1817 : c);
1818 : }
1819 :
1820 : /*
1821 : perform the receive side of a async dcerpc request
1822 : */
1823 161149 : static NTSTATUS dcerpc_request_recv(struct rpc_request *req,
1824 : TALLOC_CTX *mem_ctx,
1825 : DATA_BLOB *stub_data)
1826 : {
1827 : NTSTATUS status;
1828 :
1829 294062 : while (req->state != RPC_REQUEST_DONE) {
1830 0 : struct tevent_context *ctx = req->p->conn->event_ctx;
1831 0 : if (tevent_loop_once(ctx) != 0) {
1832 0 : return NT_STATUS_CONNECTION_DISCONNECTED;
1833 : }
1834 : }
1835 161149 : *stub_data = req->payload;
1836 161149 : status = req->status;
1837 161149 : if (stub_data->data) {
1838 145984 : stub_data->data = talloc_steal(mem_ctx, stub_data->data);
1839 : }
1840 161149 : if (NT_STATUS_EQUAL(status, NT_STATUS_NET_WRITE_FAULT)) {
1841 14891 : req->p->last_fault_code = req->fault_code;
1842 : }
1843 161149 : talloc_unlink(talloc_parent(req), req);
1844 161149 : return status;
1845 : }
1846 :
1847 : /*
1848 : this is a paranoid NDR validator. For every packet we push onto the wire
1849 : we pull it back again, then push it again. Then we compare the raw NDR data
1850 : for that to the NDR we initially generated. If they don't match then we know
1851 : we must have a bug in either the pull or push side of our code
1852 : */
1853 18769 : static NTSTATUS dcerpc_ndr_validate_in(struct dcecli_connection *c,
1854 : TALLOC_CTX *mem_ctx,
1855 : DATA_BLOB blob,
1856 : size_t struct_size,
1857 : ndr_push_flags_fn_t ndr_push,
1858 : ndr_pull_flags_fn_t ndr_pull)
1859 : {
1860 : void *st;
1861 : struct ndr_pull *pull;
1862 : struct ndr_push *push;
1863 : DATA_BLOB blob2;
1864 : enum ndr_err_code ndr_err;
1865 :
1866 18769 : st = talloc_size(mem_ctx, struct_size);
1867 18769 : if (!st) {
1868 0 : return NT_STATUS_NO_MEMORY;
1869 : }
1870 :
1871 18769 : pull = ndr_pull_init_flags(c, &blob, mem_ctx);
1872 18769 : if (!pull) {
1873 0 : return NT_STATUS_NO_MEMORY;
1874 : }
1875 18769 : pull->flags |= LIBNDR_FLAG_REF_ALLOC;
1876 :
1877 18769 : if (c->flags & DCERPC_PUSH_BIGENDIAN) {
1878 12 : pull->flags |= LIBNDR_FLAG_BIGENDIAN;
1879 : }
1880 :
1881 18769 : if (c->flags & DCERPC_NDR64) {
1882 0 : pull->flags |= LIBNDR_FLAG_NDR64;
1883 : }
1884 :
1885 18769 : ndr_err = ndr_pull(pull, NDR_IN, st);
1886 18769 : if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1887 0 : NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
1888 0 : ndr_err = ndr_pull_error(pull, NDR_ERR_VALIDATE,
1889 : "failed input validation pull - %s",
1890 : nt_errstr(status));
1891 0 : return ndr_map_error2ntstatus(ndr_err);
1892 : }
1893 :
1894 18769 : push = ndr_push_init_ctx(mem_ctx);
1895 18769 : if (!push) {
1896 0 : return NT_STATUS_NO_MEMORY;
1897 : }
1898 :
1899 18769 : if (c->flags & DCERPC_PUSH_BIGENDIAN) {
1900 12 : push->flags |= LIBNDR_FLAG_BIGENDIAN;
1901 : }
1902 :
1903 18769 : if (c->flags & DCERPC_NDR64) {
1904 0 : push->flags |= LIBNDR_FLAG_NDR64;
1905 : }
1906 :
1907 18769 : ndr_err = ndr_push(push, NDR_IN, st);
1908 18769 : if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1909 0 : NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
1910 0 : ndr_err = ndr_pull_error(pull, NDR_ERR_VALIDATE,
1911 : "failed input validation push - %s",
1912 : nt_errstr(status));
1913 0 : return ndr_map_error2ntstatus(ndr_err);
1914 : }
1915 :
1916 18769 : blob2 = ndr_push_blob(push);
1917 :
1918 18769 : if (data_blob_cmp(&blob, &blob2) != 0) {
1919 0 : DEBUG(3,("original:\n"));
1920 0 : dump_data(3, blob.data, blob.length);
1921 0 : DEBUG(3,("secondary:\n"));
1922 0 : dump_data(3, blob2.data, blob2.length);
1923 0 : ndr_err = ndr_pull_error(pull, NDR_ERR_VALIDATE,
1924 : "failed input validation blobs doesn't match");
1925 0 : return ndr_map_error2ntstatus(ndr_err);
1926 : }
1927 :
1928 18769 : return NT_STATUS_OK;
1929 : }
1930 :
1931 : /*
1932 : this is a paranoid NDR input validator. For every packet we pull
1933 : from the wire we push it back again then pull and push it
1934 : again. Then we compare the raw NDR data for that to the NDR we
1935 : initially generated. If they don't match then we know we must have a
1936 : bug in either the pull or push side of our code
1937 : */
1938 13832 : static NTSTATUS dcerpc_ndr_validate_out(struct dcecli_connection *c,
1939 : struct ndr_pull *pull_in,
1940 : void *struct_ptr,
1941 : size_t struct_size,
1942 : ndr_push_flags_fn_t ndr_push,
1943 : ndr_pull_flags_fn_t ndr_pull,
1944 : ndr_print_function_t ndr_print)
1945 : {
1946 : void *st;
1947 : struct ndr_pull *pull;
1948 : struct ndr_push *push;
1949 : DATA_BLOB blob, blob2;
1950 13832 : TALLOC_CTX *mem_ctx = pull_in;
1951 : char *s1, *s2;
1952 : enum ndr_err_code ndr_err;
1953 :
1954 13832 : st = talloc_size(mem_ctx, struct_size);
1955 13832 : if (!st) {
1956 0 : return NT_STATUS_NO_MEMORY;
1957 : }
1958 13832 : memcpy(st, struct_ptr, struct_size);
1959 :
1960 13832 : push = ndr_push_init_ctx(mem_ctx);
1961 13832 : if (!push) {
1962 0 : return NT_STATUS_NO_MEMORY;
1963 : }
1964 :
1965 13832 : ndr_err = ndr_push(push, NDR_OUT, struct_ptr);
1966 13832 : if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1967 0 : NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
1968 0 : ndr_err = ndr_push_error(push, NDR_ERR_VALIDATE,
1969 : "failed output validation push - %s",
1970 : nt_errstr(status));
1971 0 : return ndr_map_error2ntstatus(ndr_err);
1972 : }
1973 :
1974 13832 : blob = ndr_push_blob(push);
1975 :
1976 13832 : pull = ndr_pull_init_flags(c, &blob, mem_ctx);
1977 13832 : if (!pull) {
1978 0 : return NT_STATUS_NO_MEMORY;
1979 : }
1980 :
1981 13832 : pull->flags |= LIBNDR_FLAG_REF_ALLOC;
1982 13832 : ndr_err = ndr_pull(pull, NDR_OUT, st);
1983 13832 : if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1984 0 : NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
1985 0 : ndr_err = ndr_pull_error(pull, NDR_ERR_VALIDATE,
1986 : "failed output validation pull - %s",
1987 : nt_errstr(status));
1988 0 : return ndr_map_error2ntstatus(ndr_err);
1989 : }
1990 :
1991 13832 : push = ndr_push_init_ctx(mem_ctx);
1992 13832 : if (!push) {
1993 0 : return NT_STATUS_NO_MEMORY;
1994 : }
1995 :
1996 13832 : ndr_err = ndr_push(push, NDR_OUT, st);
1997 13832 : if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1998 0 : NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
1999 0 : ndr_err = ndr_push_error(push, NDR_ERR_VALIDATE,
2000 : "failed output validation push2 - %s",
2001 : nt_errstr(status));
2002 0 : return ndr_map_error2ntstatus(ndr_err);
2003 : }
2004 :
2005 13832 : blob2 = ndr_push_blob(push);
2006 :
2007 13832 : if (data_blob_cmp(&blob, &blob2) != 0) {
2008 0 : DEBUG(3,("original:\n"));
2009 0 : dump_data(3, blob.data, blob.length);
2010 0 : DEBUG(3,("secondary:\n"));
2011 0 : dump_data(3, blob2.data, blob2.length);
2012 0 : ndr_err = ndr_push_error(push, NDR_ERR_VALIDATE,
2013 : "failed output validation blobs doesn't match");
2014 0 : return ndr_map_error2ntstatus(ndr_err);
2015 : }
2016 :
2017 : /* this checks the printed forms of the two structures, which effectively
2018 : tests all of the value() attributes */
2019 13832 : s1 = ndr_print_function_string(mem_ctx, ndr_print, "VALIDATE",
2020 : NDR_OUT, struct_ptr);
2021 13832 : s2 = ndr_print_function_string(mem_ctx, ndr_print, "VALIDATE",
2022 : NDR_OUT, st);
2023 13832 : if (strcmp(s1, s2) != 0) {
2024 : #if 1
2025 0 : DEBUG(3,("VALIDATE ERROR:\nWIRE:\n%s\n GEN:\n%s\n", s1, s2));
2026 : #else
2027 : /* this is sometimes useful */
2028 : printf("VALIDATE ERROR\n");
2029 : file_save("wire.dat", s1, strlen(s1));
2030 : file_save("gen.dat", s2, strlen(s2));
2031 : system("diff -u wire.dat gen.dat");
2032 : #endif
2033 0 : ndr_err = ndr_push_error(push, NDR_ERR_VALIDATE,
2034 : "failed output validation strings doesn't match");
2035 0 : return ndr_map_error2ntstatus(ndr_err);
2036 : }
2037 :
2038 13832 : return NT_STATUS_OK;
2039 : }
2040 :
2041 : /*
2042 : a useful function for retrieving the server name we connected to
2043 : */
2044 9890 : _PUBLIC_ const char *dcerpc_server_name(struct dcerpc_pipe *p)
2045 : {
2046 9890 : return p->conn ? p->conn->server_name : NULL;
2047 : }
2048 :
2049 :
2050 : /*
2051 : get the dcerpc auth_level for a open connection
2052 : */
2053 6103 : uint32_t dcerpc_auth_level(struct dcecli_connection *c)
2054 : {
2055 : uint8_t auth_level;
2056 :
2057 6103 : if (c->flags & DCERPC_SEAL) {
2058 3892 : auth_level = DCERPC_AUTH_LEVEL_PRIVACY;
2059 2211 : } else if (c->flags & DCERPC_SIGN) {
2060 2171 : auth_level = DCERPC_AUTH_LEVEL_INTEGRITY;
2061 40 : } else if (c->flags & DCERPC_PACKET) {
2062 28 : auth_level = DCERPC_AUTH_LEVEL_PACKET;
2063 12 : } else if (c->flags & DCERPC_CONNECT) {
2064 10 : auth_level = DCERPC_AUTH_LEVEL_CONNECT;
2065 : } else {
2066 2 : auth_level = DCERPC_AUTH_LEVEL_NONE;
2067 : }
2068 6103 : return auth_level;
2069 : }
2070 :
2071 : struct dcerpc_alter_context_state {
2072 : struct tevent_context *ev;
2073 : struct dcerpc_pipe *p;
2074 : };
2075 :
2076 : static void dcerpc_alter_context_fail_handler(struct rpc_request *subreq);
2077 : static void dcerpc_alter_context_recv_handler(struct rpc_request *req,
2078 : DATA_BLOB *raw_packet,
2079 : struct ncacn_packet *pkt);
2080 :
2081 5080 : struct tevent_req *dcerpc_alter_context_send(TALLOC_CTX *mem_ctx,
2082 : struct tevent_context *ev,
2083 : struct dcerpc_pipe *p,
2084 : const struct ndr_syntax_id *syntax,
2085 : const struct ndr_syntax_id *transfer_syntax)
2086 : {
2087 : struct tevent_req *req;
2088 : struct dcerpc_alter_context_state *state;
2089 : struct ncacn_packet pkt;
2090 : DATA_BLOB blob;
2091 : NTSTATUS status;
2092 : struct rpc_request *subreq;
2093 : uint32_t flags;
2094 :
2095 5080 : req = tevent_req_create(mem_ctx, &state,
2096 : struct dcerpc_alter_context_state);
2097 5080 : if (req == NULL) {
2098 0 : return NULL;
2099 : }
2100 :
2101 5080 : state->ev = ev;
2102 5080 : state->p = p;
2103 :
2104 5080 : p->syntax = *syntax;
2105 5080 : p->transfer_syntax = *transfer_syntax;
2106 :
2107 5080 : flags = dcerpc_binding_get_flags(p->binding);
2108 :
2109 5080 : init_ncacn_hdr(p->conn, &pkt);
2110 :
2111 5080 : pkt.ptype = DCERPC_PKT_ALTER;
2112 5080 : pkt.pfc_flags = DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST;
2113 5080 : pkt.call_id = p->conn->call_id;
2114 5080 : pkt.auth_length = 0;
2115 :
2116 5080 : if (flags & DCERPC_CONCURRENT_MULTIPLEX) {
2117 10 : pkt.pfc_flags |= DCERPC_PFC_FLAG_CONC_MPX;
2118 : }
2119 :
2120 5080 : pkt.u.alter.max_xmit_frag = p->conn->srv_max_xmit_frag;
2121 5080 : pkt.u.alter.max_recv_frag = p->conn->srv_max_recv_frag;
2122 5080 : pkt.u.alter.assoc_group_id = dcerpc_binding_get_assoc_group_id(p->binding);
2123 5080 : pkt.u.alter.num_contexts = 1;
2124 5080 : pkt.u.alter.ctx_list = talloc_zero_array(state, struct dcerpc_ctx_list,
2125 : pkt.u.alter.num_contexts);
2126 5080 : if (tevent_req_nomem(pkt.u.alter.ctx_list, req)) {
2127 0 : return tevent_req_post(req, ev);
2128 : }
2129 5080 : pkt.u.alter.ctx_list[0].context_id = p->context_id;
2130 5080 : pkt.u.alter.ctx_list[0].num_transfer_syntaxes = 1;
2131 5080 : pkt.u.alter.ctx_list[0].abstract_syntax = p->syntax;
2132 5080 : pkt.u.alter.ctx_list[0].transfer_syntaxes = &p->transfer_syntax;
2133 5080 : pkt.u.alter.auth_info = data_blob(NULL, 0);
2134 :
2135 : /* construct the NDR form of the packet */
2136 5080 : status = dcerpc_ncacn_push_auth(&blob,
2137 : state,
2138 : &pkt,
2139 5080 : p->conn->security_state.tmp_auth_info.out);
2140 5080 : if (tevent_req_nterror(req, status)) {
2141 0 : return tevent_req_post(req, ev);
2142 : }
2143 :
2144 : /*
2145 : * we allocate a dcerpc_request so we can be in the same
2146 : * request queue as normal requests
2147 : */
2148 5080 : subreq = talloc_zero(state, struct rpc_request);
2149 5080 : if (tevent_req_nomem(subreq, req)) {
2150 0 : return tevent_req_post(req, ev);
2151 : }
2152 :
2153 5080 : subreq->state = RPC_REQUEST_PENDING;
2154 5080 : subreq->call_id = pkt.call_id;
2155 5080 : subreq->async.private_data = req;
2156 5080 : subreq->async.callback = dcerpc_alter_context_fail_handler;
2157 5080 : subreq->p = p;
2158 5080 : subreq->recv_handler = dcerpc_alter_context_recv_handler;
2159 5080 : DLIST_ADD_END(p->conn->pending, subreq);
2160 5080 : talloc_set_destructor(subreq, dcerpc_req_dequeue);
2161 :
2162 5080 : status = dcerpc_send_request(p->conn, &blob, true);
2163 5080 : if (tevent_req_nterror(req, status)) {
2164 0 : return tevent_req_post(req, ev);
2165 : }
2166 :
2167 5080 : tevent_add_timer(ev, subreq,
2168 : timeval_current_ofs(DCERPC_REQUEST_TIMEOUT, 0),
2169 : dcerpc_timeout_handler, subreq);
2170 :
2171 5080 : return req;
2172 : }
2173 :
2174 0 : static void dcerpc_alter_context_fail_handler(struct rpc_request *subreq)
2175 : {
2176 0 : struct tevent_req *req =
2177 0 : talloc_get_type_abort(subreq->async.private_data,
2178 : struct tevent_req);
2179 0 : struct dcerpc_alter_context_state *state =
2180 0 : tevent_req_data(req,
2181 : struct dcerpc_alter_context_state);
2182 0 : NTSTATUS status = subreq->status;
2183 :
2184 0 : TALLOC_FREE(subreq);
2185 :
2186 : /*
2187 : * We trigger the callback in the next event run
2188 : * because the code in this file might trigger
2189 : * multiple request callbacks from within a single
2190 : * while loop.
2191 : *
2192 : * In order to avoid segfaults from within
2193 : * dcerpc_connection_dead() we call
2194 : * tevent_req_defer_callback().
2195 : */
2196 0 : tevent_req_defer_callback(req, state->ev);
2197 :
2198 0 : tevent_req_nterror(req, status);
2199 0 : }
2200 :
2201 5080 : static void dcerpc_alter_context_recv_handler(struct rpc_request *subreq,
2202 : DATA_BLOB *raw_packet,
2203 : struct ncacn_packet *pkt)
2204 : {
2205 4514 : struct tevent_req *req =
2206 5080 : talloc_get_type_abort(subreq->async.private_data,
2207 : struct tevent_req);
2208 4514 : struct dcerpc_alter_context_state *state =
2209 5080 : tevent_req_data(req,
2210 : struct dcerpc_alter_context_state);
2211 5080 : struct dcecli_connection *conn = state->p->conn;
2212 5080 : struct dcecli_security *sec = &conn->security_state;
2213 : NTSTATUS status;
2214 :
2215 : /*
2216 : * Note that pkt is allocated under raw_packet->data,
2217 : * while raw_packet->data is a child of subreq.
2218 : */
2219 5080 : talloc_steal(state, raw_packet->data);
2220 5080 : TALLOC_FREE(subreq);
2221 :
2222 : /*
2223 : * We trigger the callback in the next event run
2224 : * because the code in this file might trigger
2225 : * multiple request callbacks from within a single
2226 : * while loop.
2227 : *
2228 : * In order to avoid segfaults from within
2229 : * dcerpc_connection_dead() we call
2230 : * tevent_req_defer_callback().
2231 : */
2232 5080 : tevent_req_defer_callback(req, state->ev);
2233 :
2234 5080 : if (pkt->ptype == DCERPC_PKT_FAULT) {
2235 6 : DEBUG(5,("dcerpc: alter_resp - rpc fault: %s\n",
2236 : dcerpc_errstr(state, pkt->u.fault.status)));
2237 6 : if (pkt->u.fault.status == DCERPC_FAULT_ACCESS_DENIED) {
2238 0 : state->p->last_fault_code = pkt->u.fault.status;
2239 0 : tevent_req_nterror(req, NT_STATUS_LOGON_FAILURE);
2240 6 : } else if (pkt->u.fault.status == DCERPC_FAULT_SEC_PKG_ERROR) {
2241 0 : state->p->last_fault_code = pkt->u.fault.status;
2242 0 : tevent_req_nterror(req, NT_STATUS_LOGON_FAILURE);
2243 : } else {
2244 6 : state->p->last_fault_code = pkt->u.fault.status;
2245 6 : status = dcerpc_fault_to_nt_status(pkt->u.fault.status);
2246 6 : tevent_req_nterror(req, status);
2247 : }
2248 18 : return;
2249 : }
2250 :
2251 5074 : status = dcerpc_verify_ncacn_packet_header(pkt,
2252 : DCERPC_PKT_ALTER_RESP,
2253 : pkt->u.alter_resp.auth_info.length,
2254 : DCERPC_PFC_FLAG_FIRST |
2255 : DCERPC_PFC_FLAG_LAST,
2256 : DCERPC_PFC_FLAG_CONC_MPX |
2257 : DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN);
2258 5074 : if (!NT_STATUS_IS_OK(status)) {
2259 0 : state->p->last_fault_code = DCERPC_NCA_S_PROTO_ERROR;
2260 0 : tevent_req_nterror(req, NT_STATUS_NET_WRITE_FAULT);
2261 0 : return;
2262 : }
2263 :
2264 5074 : if (pkt->u.alter_resp.num_results != 1) {
2265 0 : state->p->last_fault_code = DCERPC_NCA_S_PROTO_ERROR;
2266 0 : tevent_req_nterror(req, NT_STATUS_NET_WRITE_FAULT);
2267 0 : return;
2268 : }
2269 :
2270 5074 : if (pkt->u.alter_resp.ctx_list[0].result != 0) {
2271 6 : status = dcerpc_map_ack_reason(&pkt->u.alter_resp.ctx_list[0]);
2272 6 : DEBUG(2,("dcerpc: alter_resp failed - reason %d - %s\n",
2273 : pkt->u.alter_resp.ctx_list[0].reason.value,
2274 : nt_errstr(status)));
2275 6 : tevent_req_nterror(req, status);
2276 6 : return;
2277 : }
2278 :
2279 : /* the alter_resp might contain a reply set of credentials */
2280 5068 : if (pkt->auth_length != 0 && sec->tmp_auth_info.in != NULL) {
2281 9504 : status = dcerpc_pull_auth_trailer(pkt, sec->tmp_auth_info.mem,
2282 5035 : &pkt->u.alter_resp.auth_info,
2283 : sec->tmp_auth_info.in,
2284 : NULL, true);
2285 5035 : if (tevent_req_nterror(req, status)) {
2286 0 : return;
2287 : }
2288 : }
2289 :
2290 5068 : tevent_req_done(req);
2291 : }
2292 :
2293 5080 : NTSTATUS dcerpc_alter_context_recv(struct tevent_req *req)
2294 : {
2295 5080 : return tevent_req_simple_recv_ntstatus(req);
2296 : }
2297 :
2298 : /*
2299 : send a dcerpc alter_context request
2300 : */
2301 45 : _PUBLIC_ NTSTATUS dcerpc_alter_context(struct dcerpc_pipe *p,
2302 : TALLOC_CTX *mem_ctx,
2303 : const struct ndr_syntax_id *syntax,
2304 : const struct ndr_syntax_id *transfer_syntax)
2305 : {
2306 : struct tevent_req *subreq;
2307 45 : struct tevent_context *ev = p->conn->event_ctx;
2308 : bool ok;
2309 :
2310 : /* TODO: create a new event context here */
2311 :
2312 45 : subreq = dcerpc_alter_context_send(mem_ctx, ev,
2313 : p, syntax, transfer_syntax);
2314 45 : if (subreq == NULL) {
2315 0 : return NT_STATUS_NO_MEMORY;
2316 : }
2317 :
2318 45 : ok = tevent_req_poll(subreq, ev);
2319 45 : if (!ok) {
2320 : NTSTATUS status;
2321 0 : status = map_nt_error_from_unix_common(errno);
2322 0 : return status;
2323 : }
2324 :
2325 45 : return dcerpc_alter_context_recv(subreq);
2326 : }
2327 :
2328 15 : static void dcerpc_transport_dead(struct dcecli_connection *c, NTSTATUS status)
2329 : {
2330 15 : if (c->transport.stream == NULL) {
2331 0 : return;
2332 : }
2333 :
2334 15 : tevent_queue_stop(c->transport.write_queue);
2335 15 : TALLOC_FREE(c->transport.read_subreq);
2336 15 : TALLOC_FREE(c->transport.stream);
2337 :
2338 15 : if (NT_STATUS_EQUAL(NT_STATUS_UNSUCCESSFUL, status)) {
2339 0 : status = NT_STATUS_UNEXPECTED_NETWORK_ERROR;
2340 : }
2341 :
2342 15 : if (NT_STATUS_EQUAL(NT_STATUS_OK, status)) {
2343 0 : status = NT_STATUS_END_OF_FILE;
2344 : }
2345 :
2346 15 : dcerpc_recv_data(c, NULL, status);
2347 : }
2348 :
2349 :
2350 : /*
2351 : shutdown SMB pipe connection
2352 : */
2353 : struct dcerpc_shutdown_pipe_state {
2354 : struct dcecli_connection *c;
2355 : NTSTATUS status;
2356 : };
2357 :
2358 : static void dcerpc_shutdown_pipe_done(struct tevent_req *subreq);
2359 :
2360 24279 : static NTSTATUS dcerpc_shutdown_pipe(struct dcecli_connection *c, NTSTATUS status)
2361 : {
2362 : struct dcerpc_shutdown_pipe_state *state;
2363 : struct tevent_req *subreq;
2364 :
2365 24279 : if (c->transport.stream == NULL) {
2366 9803 : return NT_STATUS_OK;
2367 : }
2368 :
2369 14476 : state = talloc_zero(c, struct dcerpc_shutdown_pipe_state);
2370 14476 : if (state == NULL) {
2371 0 : return NT_STATUS_NO_MEMORY;
2372 : }
2373 14476 : state->c = c;
2374 14476 : state->status = status;
2375 :
2376 14476 : subreq = tstream_disconnect_send(state, c->event_ctx, c->transport.stream);
2377 14476 : if (subreq == NULL) {
2378 0 : return NT_STATUS_NO_MEMORY;
2379 : }
2380 14476 : tevent_req_set_callback(subreq, dcerpc_shutdown_pipe_done, state);
2381 :
2382 14476 : return status;
2383 : }
2384 :
2385 0 : static void dcerpc_shutdown_pipe_done(struct tevent_req *subreq)
2386 : {
2387 0 : struct dcerpc_shutdown_pipe_state *state =
2388 0 : tevent_req_callback_data(subreq, struct dcerpc_shutdown_pipe_state);
2389 0 : struct dcecli_connection *c = state->c;
2390 0 : NTSTATUS status = state->status;
2391 : int error;
2392 :
2393 : /*
2394 : * here we ignore the return values...
2395 : */
2396 0 : tstream_disconnect_recv(subreq, &error);
2397 0 : TALLOC_FREE(subreq);
2398 :
2399 0 : TALLOC_FREE(state);
2400 :
2401 0 : dcerpc_transport_dead(c, status);
2402 0 : }
2403 :
2404 :
2405 :
2406 : struct dcerpc_send_read_state {
2407 : struct dcecli_connection *p;
2408 : };
2409 :
2410 407412 : static int dcerpc_send_read_state_destructor(struct dcerpc_send_read_state *state)
2411 : {
2412 407412 : struct dcecli_connection *p = state->p;
2413 :
2414 407412 : p->transport.read_subreq = NULL;
2415 :
2416 407412 : return 0;
2417 : }
2418 :
2419 : static void dcerpc_send_read_done(struct tevent_req *subreq);
2420 :
2421 407800 : static NTSTATUS dcerpc_send_read(struct dcecli_connection *p)
2422 : {
2423 : struct dcerpc_send_read_state *state;
2424 :
2425 407800 : if (p->transport.read_subreq != NULL) {
2426 388 : p->transport.pending_reads++;
2427 388 : return NT_STATUS_OK;
2428 : }
2429 :
2430 407412 : state = talloc_zero(p, struct dcerpc_send_read_state);
2431 407412 : if (state == NULL) {
2432 0 : return NT_STATUS_NO_MEMORY;
2433 : }
2434 407412 : state->p = p;
2435 :
2436 407412 : talloc_set_destructor(state, dcerpc_send_read_state_destructor);
2437 :
2438 407412 : p->transport.read_subreq = dcerpc_read_ncacn_packet_send(state,
2439 : p->event_ctx,
2440 : p->transport.stream);
2441 407412 : if (p->transport.read_subreq == NULL) {
2442 0 : return NT_STATUS_NO_MEMORY;
2443 : }
2444 407412 : tevent_req_set_callback(p->transport.read_subreq, dcerpc_send_read_done, state);
2445 :
2446 407412 : return NT_STATUS_OK;
2447 : }
2448 :
2449 407400 : static void dcerpc_send_read_done(struct tevent_req *subreq)
2450 : {
2451 370140 : struct dcerpc_send_read_state *state =
2452 407400 : tevent_req_callback_data(subreq,
2453 : struct dcerpc_send_read_state);
2454 407400 : struct dcecli_connection *p = state->p;
2455 : NTSTATUS status;
2456 : struct ncacn_packet *pkt;
2457 : DATA_BLOB blob;
2458 :
2459 407400 : status = dcerpc_read_ncacn_packet_recv(subreq, state,
2460 : &pkt, &blob);
2461 407400 : TALLOC_FREE(subreq);
2462 407400 : if (!NT_STATUS_IS_OK(status)) {
2463 3 : TALLOC_FREE(state);
2464 3 : dcerpc_transport_dead(p, status);
2465 3 : return;
2466 : }
2467 :
2468 : /*
2469 : * here we steal into thet connection context,
2470 : * but p->transport.recv_data() will steal or free it again
2471 : */
2472 407397 : talloc_steal(p, blob.data);
2473 407397 : TALLOC_FREE(state);
2474 :
2475 407397 : if (p->transport.pending_reads > 0) {
2476 388 : p->transport.pending_reads--;
2477 :
2478 388 : status = dcerpc_send_read(p);
2479 388 : if (!NT_STATUS_IS_OK(status)) {
2480 0 : dcerpc_transport_dead(p, status);
2481 0 : return;
2482 : }
2483 : }
2484 :
2485 407397 : dcerpc_recv_data(p, &blob, NT_STATUS_OK);
2486 : }
2487 :
2488 : struct dcerpc_send_request_state {
2489 : struct dcecli_connection *p;
2490 : DATA_BLOB blob;
2491 : struct iovec iov;
2492 : };
2493 :
2494 0 : static int dcerpc_send_request_state_destructor(struct dcerpc_send_request_state *state)
2495 : {
2496 0 : struct dcecli_connection *p = state->p;
2497 :
2498 0 : p->transport.read_subreq = NULL;
2499 :
2500 0 : return 0;
2501 : }
2502 :
2503 : static void dcerpc_send_request_wait_done(struct tevent_req *subreq);
2504 : static void dcerpc_send_request_done(struct tevent_req *subreq);
2505 :
2506 193602 : static NTSTATUS dcerpc_send_request(struct dcecli_connection *p, DATA_BLOB *data,
2507 : bool trigger_read)
2508 : {
2509 : struct dcerpc_send_request_state *state;
2510 : struct tevent_req *subreq;
2511 193602 : bool use_trans = trigger_read;
2512 :
2513 193602 : if (p->transport.stream == NULL) {
2514 0 : return NT_STATUS_CONNECTION_DISCONNECTED;
2515 : }
2516 :
2517 193602 : state = talloc_zero(p, struct dcerpc_send_request_state);
2518 193602 : if (state == NULL) {
2519 0 : return NT_STATUS_NO_MEMORY;
2520 : }
2521 193602 : state->p = p;
2522 :
2523 193602 : state->blob = data_blob_talloc(state, data->data, data->length);
2524 193602 : if (state->blob.data == NULL) {
2525 0 : TALLOC_FREE(state);
2526 0 : return NT_STATUS_NO_MEMORY;
2527 : }
2528 193602 : state->iov.iov_base = (void *)state->blob.data;
2529 193602 : state->iov.iov_len = state->blob.length;
2530 :
2531 193602 : if (p->transport.read_subreq != NULL) {
2532 388 : use_trans = false;
2533 : }
2534 :
2535 193602 : if (!tstream_is_smbXcli_np(p->transport.stream)) {
2536 68158 : use_trans = false;
2537 : }
2538 :
2539 193602 : if (use_trans) {
2540 : /*
2541 : * we need to block reads until our write is
2542 : * the next in the write queue.
2543 : */
2544 118694 : p->transport.read_subreq = tevent_queue_wait_send(state, p->event_ctx,
2545 : p->transport.write_queue);
2546 118694 : if (p->transport.read_subreq == NULL) {
2547 0 : TALLOC_FREE(state);
2548 0 : return NT_STATUS_NO_MEMORY;
2549 : }
2550 118694 : tevent_req_set_callback(p->transport.read_subreq,
2551 : dcerpc_send_request_wait_done,
2552 : state);
2553 :
2554 118694 : talloc_set_destructor(state, dcerpc_send_request_state_destructor);
2555 :
2556 118694 : trigger_read = false;
2557 : }
2558 :
2559 193602 : subreq = tstream_writev_queue_send(state, p->event_ctx,
2560 : p->transport.stream,
2561 : p->transport.write_queue,
2562 193602 : &state->iov, 1);
2563 193602 : if (subreq == NULL) {
2564 0 : TALLOC_FREE(state);
2565 0 : return NT_STATUS_NO_MEMORY;
2566 : }
2567 193602 : tevent_req_set_callback(subreq, dcerpc_send_request_done, state);
2568 :
2569 193602 : if (trigger_read) {
2570 61632 : dcerpc_send_read(p);
2571 : }
2572 :
2573 193602 : return NT_STATUS_OK;
2574 : }
2575 :
2576 118694 : static void dcerpc_send_request_wait_done(struct tevent_req *subreq)
2577 : {
2578 92597 : struct dcerpc_send_request_state *state =
2579 118694 : tevent_req_callback_data(subreq,
2580 : struct dcerpc_send_request_state);
2581 118694 : struct dcecli_connection *p = state->p;
2582 : NTSTATUS status;
2583 : bool ok;
2584 :
2585 118694 : p->transport.read_subreq = NULL;
2586 118694 : talloc_set_destructor(state, NULL);
2587 :
2588 118694 : ok = tevent_queue_wait_recv(subreq);
2589 118694 : if (!ok) {
2590 0 : TALLOC_FREE(state);
2591 0 : dcerpc_transport_dead(p, NT_STATUS_NO_MEMORY);
2592 0 : return;
2593 : }
2594 :
2595 118694 : if (tevent_queue_length(p->transport.write_queue) <= 2) {
2596 118656 : status = tstream_smbXcli_np_use_trans(p->transport.stream);
2597 118656 : if (!NT_STATUS_IS_OK(status)) {
2598 0 : TALLOC_FREE(state);
2599 0 : dcerpc_transport_dead(p, status);
2600 0 : return;
2601 : }
2602 : }
2603 :
2604 : /* we free subreq after tstream_cli_np_use_trans */
2605 118694 : TALLOC_FREE(subreq);
2606 :
2607 118694 : dcerpc_send_read(p);
2608 : }
2609 :
2610 193602 : static void dcerpc_send_request_done(struct tevent_req *subreq)
2611 : {
2612 159068 : struct dcerpc_send_request_state *state =
2613 193602 : tevent_req_callback_data(subreq,
2614 : struct dcerpc_send_request_state);
2615 : int ret;
2616 : int error;
2617 :
2618 193602 : ret = tstream_writev_queue_recv(subreq, &error);
2619 193602 : TALLOC_FREE(subreq);
2620 193602 : if (ret == -1) {
2621 12 : struct dcecli_connection *p = state->p;
2622 12 : NTSTATUS status = map_nt_error_from_unix_common(error);
2623 :
2624 12 : TALLOC_FREE(state);
2625 12 : dcerpc_transport_dead(p, status);
2626 12 : return;
2627 : }
2628 :
2629 193590 : TALLOC_FREE(state);
2630 : }
|