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