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 10767 : _PUBLIC_ NTSTATUS dcerpc_init(void)
80 : {
81 10767 : 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 32772 : static int dcerpc_connection_destructor(struct dcecli_connection *conn)
115 : {
116 32772 : if (conn->dead) {
117 0 : conn->free_skipped = true;
118 0 : return -1;
119 : }
120 32772 : dcerpc_connection_dead(conn, NT_STATUS_LOCAL_DISCONNECT);
121 32772 : return 0;
122 : }
123 :
124 :
125 : /* initialise a dcerpc connection.
126 : the event context is optional
127 : */
128 32816 : static struct dcecli_connection *dcerpc_connection_init(TALLOC_CTX *mem_ctx,
129 : struct tevent_context *ev)
130 : {
131 870 : struct dcecli_connection *c;
132 :
133 32816 : c = talloc_zero(mem_ctx, struct dcecli_connection);
134 32816 : if (!c) {
135 0 : return NULL;
136 : }
137 :
138 32816 : c->event_ctx = ev;
139 :
140 32816 : if (c->event_ctx == NULL) {
141 0 : talloc_free(c);
142 0 : return NULL;
143 : }
144 :
145 32816 : c->call_id = 1;
146 32816 : c->security_state.auth_type = DCERPC_AUTH_TYPE_NONE;
147 32816 : c->security_state.auth_level = DCERPC_AUTH_LEVEL_NONE;
148 32816 : c->security_state.auth_context_id = 0;
149 32816 : c->security_state.session_key = dcecli_generic_session_key;
150 32816 : c->security_state.generic_state = NULL;
151 32816 : 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 32816 : c->srv_max_xmit_frag = 5840;
159 32816 : c->srv_max_recv_frag = 5840;
160 32816 : c->max_total_response_size = DCERPC_NCACN_RESPONSE_DEFAULT_MAX_SIZE;
161 32816 : c->pending = NULL;
162 :
163 32816 : c->io_trigger = tevent_create_immediate(c);
164 32816 : if (c->io_trigger == NULL) {
165 0 : talloc_free(c);
166 0 : return NULL;
167 : }
168 :
169 32816 : talloc_set_destructor(c, dcerpc_connection_destructor);
170 :
171 32816 : return c;
172 : }
173 :
174 : struct dcerpc_bh_state {
175 : struct dcerpc_pipe *p;
176 : };
177 :
178 302080 : static bool dcerpc_bh_is_connected(struct dcerpc_binding_handle *h)
179 : {
180 302080 : struct dcerpc_bh_state *hs = dcerpc_binding_handle_data(h,
181 : struct dcerpc_bh_state);
182 :
183 302080 : if (!hs->p) {
184 0 : return false;
185 : }
186 :
187 302080 : if (!hs->p->conn) {
188 0 : return false;
189 : }
190 :
191 302080 : if (hs->p->conn->dead) {
192 34 : return false;
193 : }
194 :
195 295229 : return true;
196 : }
197 :
198 974 : static uint32_t dcerpc_bh_set_timeout(struct dcerpc_binding_handle *h,
199 : uint32_t timeout)
200 : {
201 974 : struct dcerpc_bh_state *hs = dcerpc_binding_handle_data(h,
202 : struct dcerpc_bh_state);
203 0 : uint32_t old;
204 :
205 974 : if (!hs->p) {
206 0 : return DCERPC_REQUEST_TIMEOUT;
207 : }
208 :
209 974 : old = hs->p->request_timeout;
210 974 : hs->p->request_timeout = timeout;
211 :
212 974 : return old;
213 : }
214 :
215 1617 : 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 1617 : struct dcerpc_bh_state *hs = dcerpc_binding_handle_data(h,
220 : struct dcerpc_bh_state);
221 :
222 1617 : if (hs->p == NULL) {
223 0 : return;
224 : }
225 :
226 1617 : if (hs->p->conn == NULL) {
227 0 : return;
228 : }
229 :
230 1617 : *auth_type = hs->p->conn->security_state.auth_type;
231 1617 : *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 296983 : 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 296983 : struct dcerpc_bh_state *hs = dcerpc_binding_handle_data(h,
254 : struct dcerpc_bh_state);
255 6817 : struct tevent_req *req;
256 6817 : struct dcerpc_bh_raw_call_state *state;
257 6817 : bool ok;
258 6817 : struct rpc_request *subreq;
259 :
260 296983 : req = tevent_req_create(mem_ctx, &state,
261 : struct dcerpc_bh_raw_call_state);
262 296983 : if (req == NULL) {
263 0 : return NULL;
264 : }
265 296983 : state->ev = ev;
266 296983 : state->h = h;
267 296983 : state->in_data.data = discard_const_p(uint8_t, in_data);
268 296983 : state->in_data.length = in_length;
269 :
270 296983 : ok = dcerpc_bh_is_connected(h);
271 296983 : if (!ok) {
272 0 : tevent_req_nterror(req, NT_STATUS_CONNECTION_DISCONNECTED);
273 0 : return tevent_req_post(req, ev);
274 : }
275 :
276 303800 : subreq = dcerpc_request_send(state,
277 : hs->p,
278 : object,
279 : opnum,
280 296983 : &state->in_data);
281 296983 : if (tevent_req_nomem(subreq, req)) {
282 0 : return tevent_req_post(req, ev);
283 : }
284 296983 : subreq->async.callback = dcerpc_bh_raw_call_done;
285 296983 : subreq->async.private_data = req;
286 :
287 296983 : return req;
288 : }
289 :
290 296983 : static void dcerpc_bh_raw_call_done(struct rpc_request *subreq)
291 : {
292 6817 : struct tevent_req *req =
293 296983 : talloc_get_type_abort(subreq->async.private_data,
294 : struct tevent_req);
295 6817 : struct dcerpc_bh_raw_call_state *state =
296 296983 : tevent_req_data(req,
297 : struct dcerpc_bh_raw_call_state);
298 6817 : NTSTATUS status;
299 6817 : uint32_t fault_code;
300 :
301 296983 : state->out_flags = 0;
302 296983 : if (subreq->flags & DCERPC_PULL_BIGENDIAN) {
303 0 : state->out_flags |= LIBNDR_FLAG_BIGENDIAN;
304 : }
305 :
306 296983 : fault_code = subreq->fault_code;
307 :
308 296983 : status = dcerpc_request_recv(subreq, state, &state->out_data);
309 296983 : if (NT_STATUS_EQUAL(status, NT_STATUS_NET_WRITE_FAULT)) {
310 2558 : 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 296983 : tevent_req_defer_callback(req, state->ev);
324 :
325 296983 : if (!NT_STATUS_IS_OK(status)) {
326 2598 : tevent_req_nterror(req, status);
327 2598 : return;
328 : }
329 :
330 294385 : tevent_req_done(req);
331 : }
332 :
333 296983 : 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 6817 : struct dcerpc_bh_raw_call_state *state =
340 296983 : tevent_req_data(req,
341 : struct dcerpc_bh_raw_call_state);
342 6817 : NTSTATUS status;
343 :
344 296983 : if (tevent_req_is_nterror(req, &status)) {
345 2598 : tevent_req_received(req);
346 2598 : return status;
347 : }
348 :
349 294385 : *out_data = talloc_move(mem_ctx, &state->out_data.data);
350 294385 : *out_length = state->out_data.length;
351 294385 : *out_flags = state->out_flags;
352 294385 : tevent_req_received(req);
353 294385 : 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 0 : struct tevent_req *req;
367 0 : struct dcerpc_bh_disconnect_state *state;
368 0 : 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 0 : 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 297066 : static bool dcerpc_bh_push_bigendian(struct dcerpc_binding_handle *h)
403 : {
404 297066 : struct dcerpc_bh_state *hs = dcerpc_binding_handle_data(h,
405 : struct dcerpc_bh_state);
406 :
407 297066 : if (hs->p->conn->flags & DCERPC_PUSH_BIGENDIAN) {
408 29007 : return true;
409 : }
410 :
411 262827 : return false;
412 : }
413 :
414 297066 : static bool dcerpc_bh_ref_alloc(struct dcerpc_binding_handle *h)
415 : {
416 297066 : struct dcerpc_bh_state *hs = dcerpc_binding_handle_data(h,
417 : struct dcerpc_bh_state);
418 :
419 297066 : if (hs->p->conn->flags & DCERPC_NDR_REF_ALLOC) {
420 23770 : return true;
421 : }
422 :
423 266489 : return false;
424 : }
425 :
426 297066 : static bool dcerpc_bh_use_ndr64(struct dcerpc_binding_handle *h)
427 : {
428 297066 : struct dcerpc_bh_state *hs = dcerpc_binding_handle_data(h,
429 : struct dcerpc_bh_state);
430 :
431 297066 : if (hs->p->conn->flags & DCERPC_NDR64) {
432 0 : return true;
433 : }
434 :
435 290249 : return false;
436 : }
437 :
438 591444 : static void dcerpc_bh_do_ndr_print(struct dcerpc_binding_handle *h,
439 : ndr_flags_type ndr_flags,
440 : const void *_struct_ptr,
441 : const struct ndr_interface_call *call)
442 : {
443 591444 : struct dcerpc_bh_state *hs = dcerpc_binding_handle_data(h,
444 : struct dcerpc_bh_state);
445 591444 : void *struct_ptr = discard_const(_struct_ptr);
446 591444 : bool print_in = false;
447 591444 : bool print_out = false;
448 :
449 591444 : if (hs->p->conn->flags & DCERPC_DEBUG_PRINT_IN) {
450 0 : print_in = true;
451 : }
452 :
453 591444 : if (hs->p->conn->flags & DCERPC_DEBUG_PRINT_OUT) {
454 0 : print_out = true;
455 : }
456 :
457 591444 : if (DEBUGLEVEL >= 11) {
458 0 : print_in = true;
459 0 : print_out = true;
460 : }
461 :
462 591444 : if (ndr_flags & NDR_IN) {
463 297066 : 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 591444 : if (ndr_flags & NDR_OUT) {
471 294378 : 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 591444 : }
479 :
480 90 : 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 90 : DEBUG(2,("Unable to ndr_push structure for %s - %s\n",
486 : call->name, nt_errstr(error)));
487 90 : }
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 0 : 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 0 : 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 296976 : 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 296976 : struct dcerpc_bh_state *hs = dcerpc_binding_handle_data(h,
531 : struct dcerpc_bh_state);
532 :
533 296976 : if (hs->p->conn->flags & DCERPC_DEBUG_VALIDATE_IN) {
534 1585 : NTSTATUS status;
535 :
536 25089 : status = dcerpc_ndr_validate_in(hs->p->conn,
537 : mem_ctx,
538 : *blob,
539 25089 : call->struct_size,
540 25089 : call->ndr_push,
541 25089 : call->ndr_pull);
542 25089 : 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 296976 : DEBUG(10,("rpc request data:\n"));
550 296976 : dump_data(10, blob->data, blob->length);
551 :
552 296976 : return NT_STATUS_OK;
553 : }
554 :
555 294378 : 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 294378 : struct dcerpc_bh_state *hs = dcerpc_binding_handle_data(h,
561 : struct dcerpc_bh_state);
562 294378 : void *struct_ptr = discard_const(_struct_ptr);
563 :
564 294378 : DEBUG(10,("rpc reply data:\n"));
565 294378 : dump_data(10, pull_in->data, pull_in->data_size);
566 :
567 294378 : 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 294378 : if (hs->p->conn->flags & DCERPC_DEBUG_VALIDATE_OUT) {
580 1495 : NTSTATUS status;
581 :
582 24483 : status = dcerpc_ndr_validate_out(hs->p->conn,
583 : pull_in,
584 : struct_ptr,
585 24483 : call->struct_size,
586 24483 : call->ndr_push,
587 24483 : call->ndr_pull,
588 24483 : call->ndr_print);
589 24483 : 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 294378 : 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 20167 : 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 876 : struct dcerpc_binding_handle *h;
625 876 : struct dcerpc_bh_state *hs;
626 :
627 20167 : h = dcerpc_binding_handle_create(p,
628 : &dcerpc_bh_ops,
629 : object,
630 : table,
631 : &hs,
632 : struct dcerpc_bh_state,
633 : __location__);
634 20167 : if (h == NULL) {
635 0 : return NULL;
636 : }
637 20167 : hs->p = p;
638 :
639 20167 : dcerpc_binding_handle_set_sync_ev(h, p->conn->event_ctx);
640 :
641 20167 : return h;
642 : }
643 :
644 : /* initialise a dcerpc pipe. */
645 32816 : _PUBLIC_ struct dcerpc_pipe *dcerpc_pipe_init(TALLOC_CTX *mem_ctx, struct tevent_context *ev)
646 : {
647 870 : struct dcerpc_pipe *p;
648 :
649 32816 : p = talloc_zero(mem_ctx, struct dcerpc_pipe);
650 32816 : if (!p) {
651 0 : return NULL;
652 : }
653 :
654 32816 : p->conn = dcerpc_connection_init(p, ev);
655 32816 : if (p->conn == NULL) {
656 0 : talloc_free(p);
657 0 : return NULL;
658 : }
659 :
660 32816 : p->request_timeout = DCERPC_REQUEST_TIMEOUT;
661 :
662 32816 : if (DEBUGLVL(100)) {
663 0 : p->conn->flags |= DCERPC_DEBUG_PRINT_BOTH;
664 : }
665 :
666 31946 : return p;
667 : }
668 :
669 :
670 : /*
671 : choose the next call id to use
672 : */
673 297168 : static uint32_t next_call_id(struct dcecli_connection *c)
674 : {
675 297168 : c->call_id++;
676 297168 : if (c->call_id == 0) {
677 0 : c->call_id++;
678 : }
679 297168 : return c->call_id;
680 : }
681 :
682 : /**
683 : setup for a ndr pull, also setting up any flags from the binding string
684 : */
685 49572 : static struct ndr_pull *ndr_pull_init_flags(struct dcecli_connection *c,
686 : DATA_BLOB *blob, TALLOC_CTX *mem_ctx)
687 : {
688 49572 : struct ndr_pull *ndr = ndr_pull_init_blob(blob, mem_ctx);
689 :
690 49572 : if (ndr == NULL) return ndr;
691 :
692 49572 : if (c->flags & DCERPC_DEBUG_PAD_CHECK) {
693 0 : ndr->flags |= LIBNDR_FLAG_PAD_CHECK;
694 : }
695 :
696 49572 : if (c->flags & DCERPC_NDR_REF_ALLOC) {
697 0 : ndr->flags |= LIBNDR_FLAG_REF_ALLOC;
698 : }
699 :
700 49572 : if (c->flags & DCERPC_NDR64) {
701 0 : ndr->flags |= LIBNDR_FLAG_NDR64;
702 : }
703 :
704 46492 : return ndr;
705 : }
706 :
707 : /*
708 : parse the authentication information on a dcerpc response packet
709 : */
710 584358 : 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 584358 : const struct dcerpc_auth tmp_auth = {
721 584358 : .auth_type = c->security_state.auth_type,
722 584358 : .auth_level = c->security_state.auth_level,
723 584358 : .auth_context_id = c->security_state.auth_context_id,
724 : };
725 6555 : NTSTATUS status;
726 :
727 584358 : 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 584358 : if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_PROTOCOL_ERROR)) {
739 0 : return NT_STATUS_INVALID_NETWORK_RESPONSE;
740 : }
741 584358 : if (!NT_STATUS_IS_OK(status)) {
742 0 : return status;
743 : }
744 :
745 584358 : return NT_STATUS_OK;
746 : }
747 :
748 :
749 : /*
750 : push a dcerpc request packet into a blob, possibly signing it.
751 : */
752 310611 : 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 310611 : const struct dcerpc_auth tmp_auth = {
758 310611 : .auth_type = c->security_state.auth_type,
759 310611 : .auth_level = c->security_state.auth_level,
760 310611 : .auth_context_id = c->security_state.auth_context_id,
761 : };
762 6898 : NTSTATUS status;
763 310611 : uint8_t payload_offset = DCERPC_REQUEST_LENGTH;
764 :
765 310611 : if (pkt->pfc_flags & DCERPC_PFC_FLAG_OBJECT_UUID) {
766 670 : payload_offset += 16;
767 : }
768 :
769 310611 : 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 310611 : &pkt->u.request.stub_and_verifier,
775 : pkt);
776 310611 : if (!NT_STATUS_IS_OK(status)) {
777 0 : return status;
778 : }
779 :
780 310611 : return NT_STATUS_OK;
781 : }
782 :
783 :
784 : /*
785 : fill in the fixed values in a dcerpc header
786 : */
787 323269 : static void init_ncacn_hdr(struct dcecli_connection *c, struct ncacn_packet *pkt)
788 : {
789 323269 : pkt->rpc_vers = 5;
790 323269 : pkt->rpc_vers_minor = 0;
791 323269 : if (c->flags & DCERPC_PUSH_BIGENDIAN) {
792 31615 : pkt->drep[0] = 0;
793 : } else {
794 291654 : pkt->drep[0] = DCERPC_DREP_LE;
795 : }
796 323269 : pkt->drep[1] = 0;
797 323269 : pkt->drep[2] = 0;
798 323269 : pkt->drep[3] = 0;
799 315465 : }
800 :
801 : /*
802 : map a bind nak reason to a NTSTATUS
803 : */
804 79 : static NTSTATUS dcerpc_map_nak_reason(enum dcerpc_bind_nak_reason reason)
805 : {
806 79 : 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 61 : default:
812 79 : break;
813 : }
814 79 : return NT_STATUS_UNSUCCESSFUL;
815 : }
816 :
817 36 : static NTSTATUS dcerpc_map_ack_reason(const struct dcerpc_ack_ctx *ack)
818 : {
819 36 : if (ack == NULL) {
820 0 : return NT_STATUS_RPC_PROTOCOL_ERROR;
821 : }
822 :
823 36 : 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 30 : default:
830 36 : break;
831 : }
832 :
833 36 : switch (ack->reason.value) {
834 30 : case DCERPC_BIND_ACK_REASON_ABSTRACT_SYNTAX_NOT_SUPPORTED:
835 30 : 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 646168 : static int dcerpc_req_dequeue(struct rpc_request *req)
848 : {
849 646168 : switch (req->state) {
850 0 : case RPC_REQUEST_QUEUED:
851 0 : DLIST_REMOVE(req->p->conn->request_queue, req);
852 0 : break;
853 323084 : case RPC_REQUEST_PENDING:
854 323084 : DLIST_REMOVE(req->p->conn->pending, req);
855 315280 : break;
856 315280 : case RPC_REQUEST_DONE:
857 315280 : break;
858 : }
859 646168 : return 0;
860 : }
861 :
862 :
863 : /*
864 : mark the dcerpc connection dead. All outstanding requests get an error
865 : */
866 32812 : static void dcerpc_connection_dead(struct dcecli_connection *conn, NTSTATUS status)
867 : {
868 32812 : if (conn->dead) return;
869 :
870 32812 : conn->dead = true;
871 :
872 32812 : TALLOC_FREE(conn->io_trigger);
873 32812 : conn->io_trigger_pending = false;
874 :
875 32812 : dcerpc_shutdown_pipe(conn, status);
876 :
877 : /* all pending requests get the error */
878 38799 : while (conn->pending) {
879 40 : struct rpc_request *req = conn->pending;
880 40 : dcerpc_req_dequeue(req);
881 40 : req->state = RPC_REQUEST_DONE;
882 40 : req->status = status;
883 40 : if (req->async.callback) {
884 40 : req->async.callback(req);
885 : }
886 : }
887 :
888 : /* all requests, which are not shipped */
889 37889 : 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 32812 : talloc_set_destructor(conn, NULL);
900 32812 : 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 613057 : static void dcerpc_recv_data(struct dcecli_connection *conn, DATA_BLOB *blob, NTSTATUS status)
918 : {
919 7885 : struct ncacn_packet pkt;
920 :
921 613057 : if (conn->dead) {
922 34 : return;
923 : }
924 :
925 613057 : 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 613057 : if (!NT_STATUS_IS_OK(status)) {
932 34 : data_blob_free(blob);
933 34 : dcerpc_connection_dead(conn, status);
934 34 : return;
935 : }
936 :
937 : /* parse the basic packet to work out what type of response this is */
938 613023 : status = dcerpc_pull_ncacn_packet(blob->data, blob, &pkt);
939 613023 : 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 613023 : 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 20110 : 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 870 : struct tevent_req *req;
986 870 : struct dcerpc_bind_state *state;
987 870 : struct ncacn_packet pkt;
988 870 : DATA_BLOB blob;
989 870 : NTSTATUS status;
990 870 : struct rpc_request *subreq;
991 870 : uint32_t flags;
992 870 : struct ndr_syntax_id bind_time_features;
993 :
994 20110 : 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 20110 : req = tevent_req_create(mem_ctx, &state,
999 : struct dcerpc_bind_state);
1000 20110 : if (req == NULL) {
1001 0 : return NULL;
1002 : }
1003 :
1004 20110 : state->ev = ev;
1005 20110 : state->p = p;
1006 :
1007 20110 : p->syntax = *syntax;
1008 20110 : p->transfer_syntax = *transfer_syntax;
1009 :
1010 20110 : flags = dcerpc_binding_get_flags(p->binding);
1011 :
1012 20110 : init_ncacn_hdr(p->conn, &pkt);
1013 :
1014 20110 : pkt.ptype = DCERPC_PKT_BIND;
1015 20110 : pkt.pfc_flags = DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST;
1016 20110 : pkt.call_id = p->conn->call_id;
1017 20110 : pkt.auth_length = 0;
1018 :
1019 20110 : if (flags & DCERPC_CONCURRENT_MULTIPLEX) {
1020 51 : pkt.pfc_flags |= DCERPC_PFC_FLAG_CONC_MPX;
1021 : }
1022 :
1023 20110 : if (p->conn->flags & DCERPC_PROPOSE_HEADER_SIGNING) {
1024 8350 : pkt.pfc_flags |= DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN;
1025 : }
1026 :
1027 20110 : pkt.u.bind.max_xmit_frag = p->conn->srv_max_xmit_frag;
1028 20110 : pkt.u.bind.max_recv_frag = p->conn->srv_max_recv_frag;
1029 20110 : pkt.u.bind.assoc_group_id = dcerpc_binding_get_assoc_group_id(p->binding);
1030 20110 : pkt.u.bind.num_contexts = 2;
1031 20110 : pkt.u.bind.ctx_list = talloc_zero_array(state, struct dcerpc_ctx_list,
1032 : pkt.u.bind.num_contexts);
1033 20110 : if (tevent_req_nomem(pkt.u.bind.ctx_list, req)) {
1034 0 : return tevent_req_post(req, ev);
1035 : }
1036 20110 : pkt.u.bind.ctx_list[0].context_id = p->context_id;
1037 20110 : pkt.u.bind.ctx_list[0].num_transfer_syntaxes = 1;
1038 20110 : pkt.u.bind.ctx_list[0].abstract_syntax = p->syntax;
1039 20110 : pkt.u.bind.ctx_list[0].transfer_syntaxes = &p->transfer_syntax;
1040 20110 : pkt.u.bind.ctx_list[1].context_id = p->context_id + 1;
1041 20110 : pkt.u.bind.ctx_list[1].num_transfer_syntaxes = 1;
1042 20110 : pkt.u.bind.ctx_list[1].abstract_syntax = p->syntax;
1043 20110 : pkt.u.bind.ctx_list[1].transfer_syntaxes = &bind_time_features;
1044 20110 : pkt.u.bind.auth_info = data_blob(NULL, 0);
1045 :
1046 : /* construct the NDR form of the packet */
1047 20110 : status = dcerpc_ncacn_push_auth(&blob,
1048 : state,
1049 : &pkt,
1050 20110 : p->conn->security_state.tmp_auth_info.out);
1051 20110 : 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 20110 : subreq = talloc_zero(state, struct rpc_request);
1060 20110 : if (tevent_req_nomem(subreq, req)) {
1061 0 : return tevent_req_post(req, ev);
1062 : }
1063 :
1064 20110 : subreq->state = RPC_REQUEST_PENDING;
1065 20110 : subreq->call_id = pkt.call_id;
1066 20110 : subreq->async.private_data = req;
1067 20110 : subreq->async.callback = dcerpc_bind_fail_handler;
1068 20110 : subreq->p = p;
1069 20110 : subreq->recv_handler = dcerpc_bind_recv_handler;
1070 20110 : DLIST_ADD_END(p->conn->pending, subreq);
1071 20110 : talloc_set_destructor(subreq, dcerpc_req_dequeue);
1072 :
1073 20110 : status = dcerpc_send_request(p->conn, &blob, true);
1074 20110 : if (tevent_req_nterror(req, status)) {
1075 0 : return tevent_req_post(req, ev);
1076 : }
1077 :
1078 20110 : tevent_add_timer(ev, subreq,
1079 : timeval_current_ofs(DCERPC_REQUEST_TIMEOUT, 0),
1080 : dcerpc_timeout_handler, subreq);
1081 :
1082 20110 : 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 20110 : static void dcerpc_bind_recv_handler(struct rpc_request *subreq,
1113 : DATA_BLOB *raw_packet,
1114 : struct ncacn_packet *pkt)
1115 : {
1116 870 : struct tevent_req *req =
1117 20110 : talloc_get_type_abort(subreq->async.private_data,
1118 : struct tevent_req);
1119 870 : struct dcerpc_bind_state *state =
1120 20110 : tevent_req_data(req,
1121 : struct dcerpc_bind_state);
1122 20110 : struct dcecli_connection *conn = state->p->conn;
1123 20110 : struct dcecli_security *sec = &conn->security_state;
1124 20110 : struct dcerpc_binding *b = NULL;
1125 870 : NTSTATUS status;
1126 870 : 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 20110 : talloc_steal(state, raw_packet->data);
1133 20110 : 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 20110 : tevent_req_defer_callback(req, state->ev);
1146 :
1147 20110 : if (pkt->ptype == DCERPC_PKT_BIND_NAK) {
1148 79 : status = dcerpc_map_nak_reason(pkt->u.bind_nak.reject_reason);
1149 :
1150 79 : DEBUG(2,("dcerpc: bind_nak reason %d - %s\n",
1151 : pkt->u.bind_nak.reject_reason, nt_errstr(status)));
1152 :
1153 79 : tevent_req_nterror(req, status);
1154 97 : return;
1155 : }
1156 :
1157 20031 : 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 20031 : 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 20031 : 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 20031 : if (pkt->u.bind_ack.ctx_list[0].result != 0) {
1177 21 : status = dcerpc_map_ack_reason(&pkt->u.bind_ack.ctx_list[0]);
1178 21 : 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 21 : tevent_req_nterror(req, status);
1182 21 : return;
1183 : }
1184 :
1185 20010 : if (pkt->u.bind_ack.num_results >= 2) {
1186 20010 : if (pkt->u.bind_ack.ctx_list[1].result == DCERPC_BIND_ACK_RESULT_NEGOTIATE_ACK) {
1187 20010 : 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 849 : 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 20010 : 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 20010 : 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 20010 : conn->srv_max_xmit_frag = MIN(conn->srv_max_xmit_frag,
1212 : pkt->u.bind_ack.max_xmit_frag);
1213 20010 : conn->srv_max_recv_frag = MIN(conn->srv_max_recv_frag,
1214 : pkt->u.bind_ack.max_recv_frag);
1215 :
1216 20010 : flags = dcerpc_binding_get_flags(state->p->binding);
1217 :
1218 20010 : 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 20010 : if (!(conn->flags & DCERPC_CONCURRENT_MULTIPLEX)) {
1227 19959 : struct dcerpc_binding *pb =
1228 19959 : discard_const_p(struct dcerpc_binding, state->p->binding);
1229 : /*
1230 : * clear DCERPC_CONCURRENT_MULTIPLEX
1231 : */
1232 19959 : status = dcerpc_binding_set_flags(pb, 0,
1233 : DCERPC_CONCURRENT_MULTIPLEX);
1234 19959 : if (tevent_req_nterror(req, status)) {
1235 0 : return;
1236 : }
1237 : }
1238 20010 : if ((conn->flags & DCERPC_PROPOSE_HEADER_SIGNING) &&
1239 8319 : (pkt->pfc_flags & DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN)) {
1240 7821 : conn->flags |= DCERPC_HEADER_SIGNING;
1241 : }
1242 :
1243 : /* the bind_ack might contain a reply set of credentials */
1244 20010 : if (pkt->auth_length != 0 && sec->tmp_auth_info.in != NULL) {
1245 9219 : status = dcerpc_pull_auth_trailer(pkt, sec->tmp_auth_info.mem,
1246 8795 : &pkt->u.bind_ack.auth_info,
1247 : sec->tmp_auth_info.in,
1248 : NULL, true);
1249 8795 : 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 20010 : b = discard_const_p(struct dcerpc_binding, state->p->binding);
1258 20010 : status = dcerpc_binding_set_assoc_group_id(b,
1259 : pkt->u.bind_ack.assoc_group_id);
1260 20010 : if (tevent_req_nterror(req, status)) {
1261 0 : return;
1262 : }
1263 :
1264 20010 : tevent_req_done(req);
1265 : }
1266 :
1267 20110 : NTSTATUS dcerpc_bind_recv(struct tevent_req *req)
1268 : {
1269 20110 : return tevent_req_simple_recv_ntstatus(req);
1270 : }
1271 :
1272 : /*
1273 : perform a continued bind (and auth3)
1274 : */
1275 185 : NTSTATUS dcerpc_auth3(struct dcerpc_pipe *p,
1276 : TALLOC_CTX *mem_ctx)
1277 : {
1278 0 : struct ncacn_packet pkt;
1279 0 : NTSTATUS status;
1280 0 : DATA_BLOB blob;
1281 0 : uint32_t flags;
1282 :
1283 185 : flags = dcerpc_binding_get_flags(p->binding);
1284 :
1285 185 : init_ncacn_hdr(p->conn, &pkt);
1286 :
1287 185 : pkt.ptype = DCERPC_PKT_AUTH3;
1288 185 : pkt.pfc_flags = DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST;
1289 185 : pkt.call_id = next_call_id(p->conn);
1290 185 : pkt.auth_length = 0;
1291 185 : pkt.u.auth3.auth_info = data_blob(NULL, 0);
1292 :
1293 185 : 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 185 : status = dcerpc_ncacn_push_auth(&blob,
1299 : mem_ctx,
1300 : &pkt,
1301 185 : p->conn->security_state.tmp_auth_info.out);
1302 185 : if (!NT_STATUS_IS_OK(status)) {
1303 0 : return status;
1304 : }
1305 :
1306 : /* send it on its way */
1307 185 : status = dcerpc_send_request(p->conn, &blob, false);
1308 185 : if (!NT_STATUS_IS_OK(status)) {
1309 0 : return status;
1310 : }
1311 :
1312 185 : 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 613023 : static void dcerpc_request_recv_data(struct dcecli_connection *c,
1323 : DATA_BLOB *raw_packet, struct ncacn_packet *pkt)
1324 : {
1325 7882 : struct rpc_request *req;
1326 7882 : unsigned int length;
1327 613023 : 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 613023 : switch (pkt->ptype) {
1338 584358 : case DCERPC_PKT_RESPONSE:
1339 584358 : 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 584358 : break;
1348 27338 : default:
1349 27338 : break;
1350 : }
1351 :
1352 : /* find the matching request */
1353 630173 : for (req=c->pending;req;req=req->next) {
1354 630173 : 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 613023 : 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 315012 : return;
1369 : }
1370 :
1371 613023 : talloc_steal(req, raw_packet->data);
1372 :
1373 613023 : if (req->recv_handler != NULL) {
1374 26101 : dcerpc_req_dequeue(req);
1375 26101 : 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 26101 : dcerpc_schedule_io_trigger(c);
1382 :
1383 26101 : req->recv_handler(req, raw_packet, pkt);
1384 26101 : return;
1385 : }
1386 :
1387 586922 : if (pkt->ptype == DCERPC_PKT_FAULT) {
1388 2564 : status = dcerpc_fault_to_nt_status(pkt->u.fault.status);
1389 2564 : DEBUG(5,("rpc fault: %s\n", dcerpc_errstr(c, pkt->u.fault.status)));
1390 2564 : if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_PROTOCOL_ERROR)) {
1391 6 : dcerpc_connection_dead(c, status);
1392 6 : return;
1393 : }
1394 2558 : if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_SEC_PKG_ERROR)) {
1395 0 : dcerpc_connection_dead(c, status);
1396 0 : return;
1397 : }
1398 2558 : req->fault_code = pkt->u.fault.status;
1399 2558 : req->status = NT_STATUS_NET_WRITE_FAULT;
1400 2558 : goto req_done;
1401 : }
1402 :
1403 584358 : 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 584358 : if (!NT_STATUS_IS_OK(status)) {
1413 0 : dcerpc_connection_dead(c, status);
1414 0 : return;
1415 : }
1416 :
1417 584358 : length = pkt->u.response.stub_and_verifier.length;
1418 :
1419 584358 : 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 584358 : if (length > 0) {
1428 584089 : req->payload.data = talloc_realloc(req,
1429 : req->payload.data,
1430 : uint8_t,
1431 : req->payload.length + length);
1432 584089 : if (!req->payload.data) {
1433 0 : req->status = NT_STATUS_NO_MEMORY;
1434 0 : goto req_done;
1435 : }
1436 584089 : memcpy(req->payload.data+req->payload.length,
1437 584089 : pkt->u.response.stub_and_verifier.data, length);
1438 584089 : req->payload.length += length;
1439 : }
1440 :
1441 584358 : if (!(pkt->pfc_flags & DCERPC_PFC_FLAG_LAST)) {
1442 289973 : data_blob_free(raw_packet);
1443 289973 : dcerpc_send_read(c);
1444 289973 : return;
1445 : }
1446 :
1447 294385 : if (req->verify_bitmask1) {
1448 8107 : req->p->conn->security_state.verified_bitmask1 = true;
1449 : }
1450 294385 : if (req->verify_pcontext) {
1451 8114 : req->p->verified_pcontext = true;
1452 : }
1453 :
1454 294385 : if (!(pkt->drep[0] & DCERPC_DREP_LE)) {
1455 0 : req->flags |= DCERPC_PULL_BIGENDIAN;
1456 : } else {
1457 294385 : req->flags &= ~DCERPC_PULL_BIGENDIAN;
1458 : }
1459 :
1460 296943 : req_done:
1461 296943 : data_blob_free(raw_packet);
1462 :
1463 : /* we've got the full payload */
1464 296943 : dcerpc_req_dequeue(req);
1465 296943 : 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 296943 : dcerpc_schedule_io_trigger(c);
1472 :
1473 296943 : if (req->async.callback) {
1474 296943 : 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 296983 : 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 6817 : struct rpc_request *req;
1490 6817 : NTSTATUS status;
1491 :
1492 296983 : req = talloc_zero(mem_ctx, struct rpc_request);
1493 296983 : if (req == NULL) {
1494 0 : return NULL;
1495 : }
1496 :
1497 296983 : req->p = p;
1498 296983 : req->call_id = next_call_id(p->conn);
1499 296983 : req->state = RPC_REQUEST_QUEUED;
1500 :
1501 296983 : if (object != NULL) {
1502 262 : req->object = (struct GUID *)talloc_memdup(req, (const void *)object, sizeof(*object));
1503 262 : if (req->object == NULL) {
1504 0 : talloc_free(req);
1505 0 : return NULL;
1506 : }
1507 : }
1508 :
1509 296983 : req->opnum = opnum;
1510 296983 : req->request_data.length = stub_data->length;
1511 296983 : req->request_data.data = stub_data->data;
1512 :
1513 296983 : status = dcerpc_request_prepare_vt(req);
1514 296983 : if (!NT_STATUS_IS_OK(status)) {
1515 0 : talloc_free(req);
1516 0 : return NULL;
1517 : }
1518 :
1519 296983 : DLIST_ADD_END(p->conn->request_queue, req);
1520 296983 : talloc_set_destructor(req, dcerpc_req_dequeue);
1521 :
1522 296983 : dcerpc_schedule_io_trigger(p->conn);
1523 :
1524 296983 : if (p->request_timeout) {
1525 296983 : tevent_add_timer(p->conn->event_ctx, req,
1526 : timeval_current_ofs(p->request_timeout, 0),
1527 : dcerpc_timeout_handler, req);
1528 : }
1529 :
1530 290166 : return req;
1531 : }
1532 :
1533 296983 : static NTSTATUS dcerpc_request_prepare_vt(struct rpc_request *req)
1534 : {
1535 296983 : struct dcecli_security *sec = &req->p->conn->security_state;
1536 6817 : struct dcerpc_sec_verification_trailer *t;
1537 296983 : struct dcerpc_sec_vt *c = NULL;
1538 296983 : struct ndr_push *ndr = NULL;
1539 6817 : enum ndr_err_code ndr_err;
1540 :
1541 296983 : if (sec->auth_level < DCERPC_AUTH_LEVEL_PACKET) {
1542 199615 : return NT_STATUS_OK;
1543 : }
1544 :
1545 97368 : t = talloc_zero(req, struct dcerpc_sec_verification_trailer);
1546 97368 : if (t == NULL) {
1547 0 : return NT_STATUS_NO_MEMORY;
1548 : }
1549 :
1550 97368 : if (!sec->verified_bitmask1) {
1551 9297 : t->commands = talloc_realloc(t, t->commands,
1552 : struct dcerpc_sec_vt,
1553 : t->count.count + 1);
1554 9297 : if (t->commands == NULL) {
1555 0 : return NT_STATUS_NO_MEMORY;
1556 : }
1557 9297 : c = &t->commands[t->count.count++];
1558 9297 : ZERO_STRUCTP(c);
1559 :
1560 9297 : c->command = DCERPC_SEC_VT_COMMAND_BITMASK1;
1561 9297 : if (req->p->conn->flags & DCERPC_PROPOSE_HEADER_SIGNING) {
1562 9297 : c->u.bitmask1 = DCERPC_SEC_VT_CLIENT_SUPPORTS_HEADER_SIGNING;
1563 : }
1564 9297 : req->verify_bitmask1 = true;
1565 : }
1566 :
1567 97368 : if (!req->p->verified_pcontext) {
1568 9304 : t->commands = talloc_realloc(t, t->commands,
1569 : struct dcerpc_sec_vt,
1570 : t->count.count + 1);
1571 9304 : if (t->commands == NULL) {
1572 0 : return NT_STATUS_NO_MEMORY;
1573 : }
1574 9304 : c = &t->commands[t->count.count++];
1575 9304 : ZERO_STRUCTP(c);
1576 :
1577 9304 : c->command = DCERPC_SEC_VT_COMMAND_PCONTEXT;
1578 9304 : c->u.pcontext.abstract_syntax = req->p->syntax;
1579 9304 : c->u.pcontext.transfer_syntax = req->p->transfer_syntax;
1580 :
1581 9304 : req->verify_pcontext = true;
1582 : }
1583 :
1584 97368 : if (!(req->p->conn->flags & DCERPC_HEADER_SIGNING)) {
1585 8166 : t->commands = talloc_realloc(t, t->commands,
1586 : struct dcerpc_sec_vt,
1587 : t->count.count + 1);
1588 8166 : if (t->commands == NULL) {
1589 0 : return NT_STATUS_NO_MEMORY;
1590 : }
1591 8166 : c = &t->commands[t->count.count++];
1592 8166 : ZERO_STRUCTP(c);
1593 :
1594 8166 : c->command = DCERPC_SEC_VT_COMMAND_HEADER2;
1595 8166 : c->u.header2.ptype = DCERPC_PKT_REQUEST;
1596 8166 : if (req->p->conn->flags & DCERPC_PUSH_BIGENDIAN) {
1597 168 : c->u.header2.drep[0] = 0;
1598 : } else {
1599 7998 : c->u.header2.drep[0] = DCERPC_DREP_LE;
1600 : }
1601 8166 : c->u.header2.drep[1] = 0;
1602 8166 : c->u.header2.drep[2] = 0;
1603 8166 : c->u.header2.drep[3] = 0;
1604 8166 : c->u.header2.call_id = req->call_id;
1605 8166 : c->u.header2.context_id = req->p->context_id;
1606 8166 : c->u.header2.opnum = req->opnum;
1607 : }
1608 :
1609 97368 : if (t->count.count == 0) {
1610 80400 : TALLOC_FREE(t);
1611 80400 : return NT_STATUS_OK;
1612 : }
1613 :
1614 16968 : c = &t->commands[t->count.count - 1];
1615 16968 : c->command |= DCERPC_SEC_VT_COMMAND_END;
1616 :
1617 16968 : if (DEBUGLEVEL >= 10) {
1618 0 : NDR_PRINT_DEBUG(dcerpc_sec_verification_trailer, t);
1619 : }
1620 :
1621 16968 : ndr = ndr_push_init_ctx(req);
1622 16968 : if (ndr == NULL) {
1623 0 : return NT_STATUS_NO_MEMORY;
1624 : }
1625 :
1626 : /*
1627 : * for now we just copy and append
1628 : */
1629 :
1630 17576 : ndr_err = ndr_push_bytes(ndr, req->request_data.data,
1631 16968 : req->request_data.length);
1632 16968 : if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1633 0 : return ndr_map_error2ntstatus(ndr_err);
1634 : }
1635 :
1636 16968 : ndr_err = ndr_push_dcerpc_sec_verification_trailer(ndr,
1637 : NDR_SCALARS | NDR_BUFFERS,
1638 : t);
1639 16968 : if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1640 0 : return ndr_map_error2ntstatus(ndr_err);
1641 : }
1642 16968 : req->request_data = ndr_push_blob(ndr);
1643 :
1644 16968 : return NT_STATUS_OK;
1645 : }
1646 :
1647 : /*
1648 : Send a request using the transport
1649 : */
1650 :
1651 593190 : static void dcerpc_ship_next_request(struct dcecli_connection *c)
1652 : {
1653 13634 : struct rpc_request *req;
1654 13634 : struct dcerpc_pipe *p;
1655 13634 : DATA_BLOB *stub_data;
1656 13634 : struct ncacn_packet pkt;
1657 13634 : DATA_BLOB blob;
1658 13634 : uint32_t remaining, chunk_size;
1659 593190 : bool first_packet = true;
1660 593190 : size_t sig_size = 0;
1661 593190 : bool need_async = false;
1662 593190 : bool can_async = true;
1663 :
1664 593190 : req = c->request_queue;
1665 593190 : if (req == NULL) {
1666 296207 : return;
1667 : }
1668 :
1669 296983 : p = req->p;
1670 296983 : stub_data = &req->request_data;
1671 :
1672 296983 : if (c->pending) {
1673 780 : need_async = true;
1674 : }
1675 :
1676 296983 : if (c->security_state.auth_level >= DCERPC_AUTH_LEVEL_PACKET) {
1677 97368 : can_async = gensec_have_feature(c->security_state.generic_state,
1678 : GENSEC_FEATURE_ASYNC_REPLIES);
1679 : }
1680 :
1681 296983 : if (need_async && !can_async) {
1682 0 : req->wait_for_sync = true;
1683 0 : return;
1684 : }
1685 :
1686 296983 : DLIST_REMOVE(c->request_queue, req);
1687 296983 : DLIST_ADD(c->pending, req);
1688 296983 : req->state = RPC_REQUEST_PENDING;
1689 :
1690 296983 : init_ncacn_hdr(p->conn, &pkt);
1691 :
1692 296983 : remaining = stub_data->length;
1693 :
1694 : /* we can write a full max_recv_frag size, minus the dcerpc
1695 : request header size */
1696 296983 : chunk_size = p->conn->srv_max_recv_frag;
1697 296983 : chunk_size -= DCERPC_REQUEST_LENGTH;
1698 296983 : if (c->security_state.auth_level >= DCERPC_AUTH_LEVEL_PACKET) {
1699 97368 : size_t max_payload = chunk_size;
1700 :
1701 97368 : max_payload -= DCERPC_AUTH_TRAILER_LENGTH;
1702 97368 : max_payload -= (max_payload % DCERPC_AUTH_PAD_ALIGNMENT);
1703 :
1704 97368 : sig_size = gensec_sig_size(c->security_state.generic_state,
1705 : max_payload);
1706 97368 : if (sig_size) {
1707 97368 : chunk_size -= DCERPC_AUTH_TRAILER_LENGTH;
1708 97368 : chunk_size -= sig_size;
1709 : }
1710 : }
1711 296983 : chunk_size -= (chunk_size % DCERPC_AUTH_PAD_ALIGNMENT);
1712 :
1713 296983 : pkt.ptype = DCERPC_PKT_REQUEST;
1714 296983 : pkt.call_id = req->call_id;
1715 296983 : pkt.auth_length = 0;
1716 296983 : pkt.pfc_flags = 0;
1717 296983 : pkt.u.request.context_id = p->context_id;
1718 296983 : pkt.u.request.opnum = req->opnum;
1719 :
1720 296983 : if (req->object) {
1721 262 : pkt.u.request.object.object = *req->object;
1722 262 : pkt.pfc_flags |= DCERPC_PFC_FLAG_OBJECT_UUID;
1723 262 : chunk_size -= ndr_size_GUID(req->object,0);
1724 : }
1725 :
1726 : /* we send a series of pdus without waiting for a reply */
1727 607594 : while (remaining > 0 || first_packet) {
1728 310611 : uint32_t chunk = MIN(chunk_size, remaining);
1729 310611 : bool last_frag = false;
1730 310611 : bool do_trans = false;
1731 :
1732 310611 : first_packet = false;
1733 310611 : pkt.pfc_flags &= ~(DCERPC_PFC_FLAG_FIRST |DCERPC_PFC_FLAG_LAST);
1734 :
1735 310611 : if (remaining == stub_data->length) {
1736 296983 : pkt.pfc_flags |= DCERPC_PFC_FLAG_FIRST;
1737 : }
1738 310611 : if (chunk == remaining) {
1739 296983 : pkt.pfc_flags |= DCERPC_PFC_FLAG_LAST;
1740 296983 : last_frag = true;
1741 : }
1742 :
1743 310611 : pkt.u.request.alloc_hint = remaining;
1744 310611 : pkt.u.request.stub_and_verifier.data = stub_data->data +
1745 310611 : (stub_data->length - remaining);
1746 310611 : pkt.u.request.stub_and_verifier.length = chunk;
1747 :
1748 310611 : req->status = ncacn_push_request_sign(p->conn, &blob, req, sig_size, &pkt);
1749 310611 : 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 310611 : if (last_frag && !need_async) {
1756 296203 : do_trans = true;
1757 : }
1758 :
1759 310611 : req->status = dcerpc_send_request(p->conn, &blob, do_trans);
1760 310611 : 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 310611 : if (last_frag && !do_trans) {
1767 780 : req->status = dcerpc_send_read(p->conn);
1768 780 : 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 310611 : remaining -= chunk;
1776 : }
1777 : }
1778 :
1779 593190 : static void dcerpc_io_trigger(struct tevent_context *ctx,
1780 : struct tevent_immediate *im,
1781 : void *private_data)
1782 : {
1783 13634 : struct dcecli_connection *c =
1784 593190 : talloc_get_type_abort(private_data,
1785 : struct dcecli_connection);
1786 :
1787 593190 : c->io_trigger_pending = false;
1788 :
1789 593190 : dcerpc_schedule_io_trigger(c);
1790 :
1791 593190 : dcerpc_ship_next_request(c);
1792 593190 : }
1793 :
1794 1213217 : static void dcerpc_schedule_io_trigger(struct dcecli_connection *c)
1795 : {
1796 1213217 : if (c->dead) {
1797 0 : return;
1798 : }
1799 :
1800 1213217 : if (c->request_queue == NULL) {
1801 604633 : return;
1802 : }
1803 :
1804 593966 : if (c->request_queue->wait_for_sync && c->pending) {
1805 0 : return;
1806 : }
1807 :
1808 593966 : if (c->io_trigger_pending) {
1809 776 : return;
1810 : }
1811 :
1812 593190 : c->io_trigger_pending = true;
1813 :
1814 593190 : tevent_schedule_immediate(c->io_trigger,
1815 : c->event_ctx,
1816 : dcerpc_io_trigger,
1817 28252 : c);
1818 : }
1819 :
1820 : /*
1821 : perform the receive side of a async dcerpc request
1822 : */
1823 296983 : static NTSTATUS dcerpc_request_recv(struct rpc_request *req,
1824 : TALLOC_CTX *mem_ctx,
1825 : DATA_BLOB *stub_data)
1826 : {
1827 6817 : NTSTATUS status;
1828 :
1829 296983 : 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 296983 : *stub_data = req->payload;
1836 296983 : status = req->status;
1837 296983 : if (stub_data->data) {
1838 294116 : stub_data->data = talloc_steal(mem_ctx, stub_data->data);
1839 : }
1840 296983 : if (NT_STATUS_EQUAL(status, NT_STATUS_NET_WRITE_FAULT)) {
1841 2558 : req->p->last_fault_code = req->fault_code;
1842 : }
1843 296983 : talloc_unlink(talloc_parent(req), req);
1844 296983 : 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 25089 : 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 1585 : void *st;
1861 1585 : struct ndr_pull *pull;
1862 1585 : struct ndr_push *push;
1863 1585 : DATA_BLOB blob2;
1864 1585 : enum ndr_err_code ndr_err;
1865 :
1866 25089 : st = talloc_size(mem_ctx, struct_size);
1867 25089 : if (!st) {
1868 0 : return NT_STATUS_NO_MEMORY;
1869 : }
1870 :
1871 25089 : pull = ndr_pull_init_flags(c, &blob, mem_ctx);
1872 25089 : if (!pull) {
1873 0 : return NT_STATUS_NO_MEMORY;
1874 : }
1875 25089 : pull->flags |= LIBNDR_FLAG_REF_ALLOC;
1876 :
1877 25089 : if (c->flags & DCERPC_PUSH_BIGENDIAN) {
1878 12 : pull->flags |= LIBNDR_FLAG_BIGENDIAN;
1879 : }
1880 :
1881 25089 : if (c->flags & DCERPC_NDR64) {
1882 0 : pull->flags |= LIBNDR_FLAG_NDR64;
1883 : }
1884 :
1885 25089 : ndr_err = ndr_pull(pull, NDR_IN, st);
1886 25089 : 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 25089 : push = ndr_push_init_ctx(mem_ctx);
1895 25089 : if (!push) {
1896 0 : return NT_STATUS_NO_MEMORY;
1897 : }
1898 :
1899 25089 : if (c->flags & DCERPC_PUSH_BIGENDIAN) {
1900 12 : push->flags |= LIBNDR_FLAG_BIGENDIAN;
1901 : }
1902 :
1903 25089 : if (c->flags & DCERPC_NDR64) {
1904 0 : push->flags |= LIBNDR_FLAG_NDR64;
1905 : }
1906 :
1907 25089 : ndr_err = ndr_push(push, NDR_IN, st);
1908 25089 : 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 25089 : blob2 = ndr_push_blob(push);
1917 :
1918 25089 : 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 25089 : 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 24483 : 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 1495 : void *st;
1947 1495 : struct ndr_pull *pull;
1948 1495 : struct ndr_push *push;
1949 1495 : DATA_BLOB blob, blob2;
1950 24483 : TALLOC_CTX *mem_ctx = pull_in;
1951 1495 : char *s1, *s2;
1952 1495 : enum ndr_err_code ndr_err;
1953 :
1954 24483 : st = talloc_size(mem_ctx, struct_size);
1955 24483 : if (!st) {
1956 0 : return NT_STATUS_NO_MEMORY;
1957 : }
1958 24483 : memcpy(st, struct_ptr, struct_size);
1959 :
1960 24483 : push = ndr_push_init_ctx(mem_ctx);
1961 24483 : if (!push) {
1962 0 : return NT_STATUS_NO_MEMORY;
1963 : }
1964 :
1965 24483 : ndr_err = ndr_push(push, NDR_OUT, struct_ptr);
1966 24483 : 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 24483 : blob = ndr_push_blob(push);
1975 :
1976 24483 : pull = ndr_pull_init_flags(c, &blob, mem_ctx);
1977 24483 : if (!pull) {
1978 0 : return NT_STATUS_NO_MEMORY;
1979 : }
1980 :
1981 24483 : pull->flags |= LIBNDR_FLAG_REF_ALLOC;
1982 24483 : ndr_err = ndr_pull(pull, NDR_OUT, st);
1983 24483 : 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 24483 : push = ndr_push_init_ctx(mem_ctx);
1992 24483 : if (!push) {
1993 0 : return NT_STATUS_NO_MEMORY;
1994 : }
1995 :
1996 24483 : ndr_err = ndr_push(push, NDR_OUT, st);
1997 24483 : 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 24483 : blob2 = ndr_push_blob(push);
2006 :
2007 24483 : 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 24483 : s1 = ndr_print_function_string(mem_ctx, ndr_print, "VALIDATE",
2020 : NDR_OUT, struct_ptr);
2021 24483 : s2 = ndr_print_function_string(mem_ctx, ndr_print, "VALIDATE",
2022 : NDR_OUT, st);
2023 24483 : 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 24483 : return NT_STATUS_OK;
2039 : }
2040 :
2041 : /*
2042 : a useful function for retrieving the server name we connected to
2043 : */
2044 15822 : _PUBLIC_ const char *dcerpc_server_name(struct dcerpc_pipe *p)
2045 : {
2046 15822 : return p->conn ? p->conn->server_name : NULL;
2047 : }
2048 :
2049 :
2050 : /*
2051 : get the dcerpc auth_level for a open connection
2052 : */
2053 8382 : uint32_t dcerpc_auth_level(struct dcecli_connection *c)
2054 : {
2055 422 : uint8_t auth_level;
2056 :
2057 8382 : if (c->flags & DCERPC_SEAL) {
2058 5034 : auth_level = DCERPC_AUTH_LEVEL_PRIVACY;
2059 3079 : } else if (c->flags & DCERPC_SIGN) {
2060 2808 : auth_level = DCERPC_AUTH_LEVEL_INTEGRITY;
2061 118 : } else if (c->flags & DCERPC_PACKET) {
2062 78 : auth_level = DCERPC_AUTH_LEVEL_PACKET;
2063 40 : } else if (c->flags & DCERPC_CONNECT) {
2064 36 : auth_level = DCERPC_AUTH_LEVEL_CONNECT;
2065 : } else {
2066 4 : auth_level = DCERPC_AUTH_LEVEL_NONE;
2067 : }
2068 8382 : 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 5991 : 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 117 : struct tevent_req *req;
2088 117 : struct dcerpc_alter_context_state *state;
2089 117 : struct ncacn_packet pkt;
2090 117 : DATA_BLOB blob;
2091 117 : NTSTATUS status;
2092 117 : struct rpc_request *subreq;
2093 117 : uint32_t flags;
2094 :
2095 5991 : req = tevent_req_create(mem_ctx, &state,
2096 : struct dcerpc_alter_context_state);
2097 5991 : if (req == NULL) {
2098 0 : return NULL;
2099 : }
2100 :
2101 5991 : state->ev = ev;
2102 5991 : state->p = p;
2103 :
2104 5991 : p->syntax = *syntax;
2105 5991 : p->transfer_syntax = *transfer_syntax;
2106 :
2107 5991 : flags = dcerpc_binding_get_flags(p->binding);
2108 :
2109 5991 : init_ncacn_hdr(p->conn, &pkt);
2110 :
2111 5991 : pkt.ptype = DCERPC_PKT_ALTER;
2112 5991 : pkt.pfc_flags = DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST;
2113 5991 : pkt.call_id = p->conn->call_id;
2114 5991 : pkt.auth_length = 0;
2115 :
2116 5991 : if (flags & DCERPC_CONCURRENT_MULTIPLEX) {
2117 10 : pkt.pfc_flags |= DCERPC_PFC_FLAG_CONC_MPX;
2118 : }
2119 :
2120 5991 : pkt.u.alter.max_xmit_frag = p->conn->srv_max_xmit_frag;
2121 5991 : pkt.u.alter.max_recv_frag = p->conn->srv_max_recv_frag;
2122 5991 : pkt.u.alter.assoc_group_id = dcerpc_binding_get_assoc_group_id(p->binding);
2123 5991 : pkt.u.alter.num_contexts = 1;
2124 5991 : pkt.u.alter.ctx_list = talloc_zero_array(state, struct dcerpc_ctx_list,
2125 : pkt.u.alter.num_contexts);
2126 5991 : if (tevent_req_nomem(pkt.u.alter.ctx_list, req)) {
2127 0 : return tevent_req_post(req, ev);
2128 : }
2129 5991 : pkt.u.alter.ctx_list[0].context_id = p->context_id;
2130 5991 : pkt.u.alter.ctx_list[0].num_transfer_syntaxes = 1;
2131 5991 : pkt.u.alter.ctx_list[0].abstract_syntax = p->syntax;
2132 5991 : pkt.u.alter.ctx_list[0].transfer_syntaxes = &p->transfer_syntax;
2133 5991 : pkt.u.alter.auth_info = data_blob(NULL, 0);
2134 :
2135 : /* construct the NDR form of the packet */
2136 5991 : status = dcerpc_ncacn_push_auth(&blob,
2137 : state,
2138 : &pkt,
2139 5991 : p->conn->security_state.tmp_auth_info.out);
2140 5991 : 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 5991 : subreq = talloc_zero(state, struct rpc_request);
2149 5991 : if (tevent_req_nomem(subreq, req)) {
2150 0 : return tevent_req_post(req, ev);
2151 : }
2152 :
2153 5991 : subreq->state = RPC_REQUEST_PENDING;
2154 5991 : subreq->call_id = pkt.call_id;
2155 5991 : subreq->async.private_data = req;
2156 5991 : subreq->async.callback = dcerpc_alter_context_fail_handler;
2157 5991 : subreq->p = p;
2158 5991 : subreq->recv_handler = dcerpc_alter_context_recv_handler;
2159 5991 : DLIST_ADD_END(p->conn->pending, subreq);
2160 5991 : talloc_set_destructor(subreq, dcerpc_req_dequeue);
2161 :
2162 5991 : status = dcerpc_send_request(p->conn, &blob, true);
2163 5991 : if (tevent_req_nterror(req, status)) {
2164 0 : return tevent_req_post(req, ev);
2165 : }
2166 :
2167 5991 : tevent_add_timer(ev, subreq,
2168 : timeval_current_ofs(DCERPC_REQUEST_TIMEOUT, 0),
2169 : dcerpc_timeout_handler, subreq);
2170 :
2171 5991 : 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 5991 : static void dcerpc_alter_context_recv_handler(struct rpc_request *subreq,
2202 : DATA_BLOB *raw_packet,
2203 : struct ncacn_packet *pkt)
2204 : {
2205 117 : struct tevent_req *req =
2206 5991 : talloc_get_type_abort(subreq->async.private_data,
2207 : struct tevent_req);
2208 117 : struct dcerpc_alter_context_state *state =
2209 5991 : tevent_req_data(req,
2210 : struct dcerpc_alter_context_state);
2211 5991 : struct dcecli_connection *conn = state->p->conn;
2212 5991 : struct dcecli_security *sec = &conn->security_state;
2213 117 : 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 5991 : talloc_steal(state, raw_packet->data);
2220 5991 : 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 5991 : tevent_req_defer_callback(req, state->ev);
2233 :
2234 5991 : if (pkt->ptype == DCERPC_PKT_FAULT) {
2235 15 : DEBUG(5,("dcerpc: alter_resp - rpc fault: %s\n",
2236 : dcerpc_errstr(state, pkt->u.fault.status)));
2237 15 : 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 15 : } 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 15 : state->p->last_fault_code = pkt->u.fault.status;
2245 15 : status = dcerpc_fault_to_nt_status(pkt->u.fault.status);
2246 15 : tevent_req_nterror(req, status);
2247 : }
2248 27 : return;
2249 : }
2250 :
2251 5976 : 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 5976 : 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 5976 : 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 5976 : if (pkt->u.alter_resp.ctx_list[0].result != 0) {
2271 15 : status = dcerpc_map_ack_reason(&pkt->u.alter_resp.ctx_list[0]);
2272 15 : 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 15 : tevent_req_nterror(req, status);
2276 15 : return;
2277 : }
2278 :
2279 : /* the alter_resp might contain a reply set of credentials */
2280 5961 : if (pkt->auth_length != 0 && sec->tmp_auth_info.in != NULL) {
2281 5979 : status = dcerpc_pull_auth_trailer(pkt, sec->tmp_auth_info.mem,
2282 5883 : &pkt->u.alter_resp.auth_info,
2283 : sec->tmp_auth_info.in,
2284 : NULL, true);
2285 5883 : if (tevent_req_nterror(req, status)) {
2286 0 : return;
2287 : }
2288 : }
2289 :
2290 5961 : tevent_req_done(req);
2291 : }
2292 :
2293 5991 : NTSTATUS dcerpc_alter_context_recv(struct tevent_req *req)
2294 : {
2295 5991 : return tevent_req_simple_recv_ntstatus(req);
2296 : }
2297 :
2298 : /*
2299 : send a dcerpc alter_context request
2300 : */
2301 108 : _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 21 : struct tevent_req *subreq;
2307 108 : struct tevent_context *ev = p->conn->event_ctx;
2308 21 : bool ok;
2309 :
2310 : /* TODO: create a new event context here */
2311 :
2312 108 : subreq = dcerpc_alter_context_send(mem_ctx, ev,
2313 : p, syntax, transfer_syntax);
2314 108 : if (subreq == NULL) {
2315 0 : return NT_STATUS_NO_MEMORY;
2316 : }
2317 :
2318 108 : ok = tevent_req_poll(subreq, ev);
2319 108 : if (!ok) {
2320 0 : NTSTATUS status;
2321 0 : status = map_nt_error_from_unix_common(errno);
2322 0 : return status;
2323 : }
2324 :
2325 108 : return dcerpc_alter_context_recv(subreq);
2326 : }
2327 :
2328 34 : static void dcerpc_transport_dead(struct dcecli_connection *c, NTSTATUS status)
2329 : {
2330 34 : if (c->transport.stream == NULL) {
2331 0 : return;
2332 : }
2333 :
2334 34 : tevent_queue_stop(c->transport.write_queue);
2335 34 : TALLOC_FREE(c->transport.read_subreq);
2336 34 : TALLOC_FREE(c->transport.stream);
2337 :
2338 34 : if (NT_STATUS_EQUAL(NT_STATUS_UNSUCCESSFUL, status)) {
2339 0 : status = NT_STATUS_UNEXPECTED_NETWORK_ERROR;
2340 : }
2341 :
2342 34 : if (NT_STATUS_EQUAL(NT_STATUS_OK, status)) {
2343 0 : status = NT_STATUS_END_OF_FILE;
2344 : }
2345 :
2346 34 : 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 32812 : static NTSTATUS dcerpc_shutdown_pipe(struct dcecli_connection *c, NTSTATUS status)
2361 : {
2362 870 : struct dcerpc_shutdown_pipe_state *state;
2363 870 : struct tevent_req *subreq;
2364 :
2365 32812 : if (c->transport.stream == NULL) {
2366 12712 : return NT_STATUS_OK;
2367 : }
2368 :
2369 20100 : state = talloc_zero(c, struct dcerpc_shutdown_pipe_state);
2370 20100 : if (state == NULL) {
2371 0 : return NT_STATUS_NO_MEMORY;
2372 : }
2373 20100 : state->c = c;
2374 20100 : state->status = status;
2375 :
2376 20100 : subreq = tstream_disconnect_send(state, c->event_ctx, c->transport.stream);
2377 20100 : if (subreq == NULL) {
2378 0 : return NT_STATUS_NO_MEMORY;
2379 : }
2380 20100 : tevent_req_set_callback(subreq, dcerpc_shutdown_pipe_done, state);
2381 :
2382 20100 : 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 0 : 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 613057 : static int dcerpc_send_read_state_destructor(struct dcerpc_send_read_state *state)
2411 : {
2412 613057 : struct dcecli_connection *p = state->p;
2413 :
2414 613057 : p->transport.read_subreq = NULL;
2415 :
2416 613057 : return 0;
2417 : }
2418 :
2419 : static void dcerpc_send_read_done(struct tevent_req *subreq);
2420 :
2421 613837 : static NTSTATUS dcerpc_send_read(struct dcecli_connection *p)
2422 : {
2423 7885 : struct dcerpc_send_read_state *state;
2424 :
2425 613837 : if (p->transport.read_subreq != NULL) {
2426 780 : p->transport.pending_reads++;
2427 780 : return NT_STATUS_OK;
2428 : }
2429 :
2430 613057 : state = talloc_zero(p, struct dcerpc_send_read_state);
2431 613057 : if (state == NULL) {
2432 0 : return NT_STATUS_NO_MEMORY;
2433 : }
2434 613057 : state->p = p;
2435 :
2436 613057 : talloc_set_destructor(state, dcerpc_send_read_state_destructor);
2437 :
2438 613057 : p->transport.read_subreq = dcerpc_read_ncacn_packet_send(state,
2439 : p->event_ctx,
2440 : p->transport.stream);
2441 613057 : if (p->transport.read_subreq == NULL) {
2442 0 : return NT_STATUS_NO_MEMORY;
2443 : }
2444 613057 : tevent_req_set_callback(p->transport.read_subreq, dcerpc_send_read_done, state);
2445 :
2446 613057 : return NT_STATUS_OK;
2447 : }
2448 :
2449 613026 : static void dcerpc_send_read_done(struct tevent_req *subreq)
2450 : {
2451 7882 : struct dcerpc_send_read_state *state =
2452 613026 : tevent_req_callback_data(subreq,
2453 : struct dcerpc_send_read_state);
2454 613026 : struct dcecli_connection *p = state->p;
2455 7882 : NTSTATUS status;
2456 7882 : struct ncacn_packet *pkt;
2457 7882 : DATA_BLOB blob;
2458 :
2459 613026 : status = dcerpc_read_ncacn_packet_recv(subreq, state,
2460 : &pkt, &blob);
2461 613026 : TALLOC_FREE(subreq);
2462 613026 : 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 613023 : talloc_steal(p, blob.data);
2473 613023 : TALLOC_FREE(state);
2474 :
2475 613023 : if (p->transport.pending_reads > 0) {
2476 780 : p->transport.pending_reads--;
2477 :
2478 780 : status = dcerpc_send_read(p);
2479 780 : if (!NT_STATUS_IS_OK(status)) {
2480 0 : dcerpc_transport_dead(p, status);
2481 0 : return;
2482 : }
2483 : }
2484 :
2485 613023 : 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 336897 : static NTSTATUS dcerpc_send_request(struct dcecli_connection *p, DATA_BLOB *data,
2507 : bool trigger_read)
2508 : {
2509 7885 : struct dcerpc_send_request_state *state;
2510 7885 : struct tevent_req *subreq;
2511 336897 : bool use_trans = trigger_read;
2512 :
2513 336897 : if (p->transport.stream == NULL) {
2514 0 : return NT_STATUS_CONNECTION_DISCONNECTED;
2515 : }
2516 :
2517 336897 : state = talloc_zero(p, struct dcerpc_send_request_state);
2518 336897 : if (state == NULL) {
2519 0 : return NT_STATUS_NO_MEMORY;
2520 : }
2521 336897 : state->p = p;
2522 :
2523 336897 : state->blob = data_blob_talloc(state, data->data, data->length);
2524 336897 : if (state->blob.data == NULL) {
2525 0 : TALLOC_FREE(state);
2526 0 : return NT_STATUS_NO_MEMORY;
2527 : }
2528 336897 : state->iov.iov_base = (void *)state->blob.data;
2529 336897 : state->iov.iov_len = state->blob.length;
2530 :
2531 336897 : if (p->transport.read_subreq != NULL) {
2532 780 : use_trans = false;
2533 : }
2534 :
2535 336897 : if (!tstream_is_smbXcli_np(p->transport.stream)) {
2536 80813 : use_trans = false;
2537 : }
2538 :
2539 336017 : if (use_trans) {
2540 : /*
2541 : * we need to block reads until our write is
2542 : * the next in the write queue.
2543 : */
2544 247251 : p->transport.read_subreq = tevent_queue_wait_send(state, p->event_ctx,
2545 : p->transport.write_queue);
2546 247251 : if (p->transport.read_subreq == NULL) {
2547 0 : TALLOC_FREE(state);
2548 0 : return NT_STATUS_NO_MEMORY;
2549 : }
2550 247251 : tevent_req_set_callback(p->transport.read_subreq,
2551 : dcerpc_send_request_wait_done,
2552 : state);
2553 :
2554 247251 : talloc_set_destructor(state, dcerpc_send_request_state_destructor);
2555 :
2556 247251 : trigger_read = false;
2557 : }
2558 :
2559 344782 : subreq = tstream_writev_queue_send(state, p->event_ctx,
2560 : p->transport.stream,
2561 : p->transport.write_queue,
2562 336897 : &state->iov, 1);
2563 336897 : if (subreq == NULL) {
2564 0 : TALLOC_FREE(state);
2565 0 : return NT_STATUS_NO_MEMORY;
2566 : }
2567 336897 : tevent_req_set_callback(subreq, dcerpc_send_request_done, state);
2568 :
2569 336897 : if (trigger_read) {
2570 75053 : dcerpc_send_read(p);
2571 : }
2572 :
2573 336897 : return NT_STATUS_OK;
2574 : }
2575 :
2576 247251 : static void dcerpc_send_request_wait_done(struct tevent_req *subreq)
2577 : {
2578 6958 : struct dcerpc_send_request_state *state =
2579 247251 : tevent_req_callback_data(subreq,
2580 : struct dcerpc_send_request_state);
2581 247251 : struct dcecli_connection *p = state->p;
2582 6958 : NTSTATUS status;
2583 6958 : bool ok;
2584 :
2585 247251 : p->transport.read_subreq = NULL;
2586 247251 : talloc_set_destructor(state, NULL);
2587 :
2588 247251 : ok = tevent_queue_wait_recv(subreq);
2589 247251 : if (!ok) {
2590 0 : TALLOC_FREE(state);
2591 0 : dcerpc_transport_dead(p, NT_STATUS_NO_MEMORY);
2592 0 : return;
2593 : }
2594 :
2595 247251 : if (tevent_queue_length(p->transport.write_queue) <= 2) {
2596 247205 : status = tstream_smbXcli_np_use_trans(p->transport.stream);
2597 247205 : 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 247251 : TALLOC_FREE(subreq);
2606 :
2607 247251 : dcerpc_send_read(p);
2608 : }
2609 :
2610 336877 : static void dcerpc_send_request_done(struct tevent_req *subreq)
2611 : {
2612 7885 : struct dcerpc_send_request_state *state =
2613 336877 : tevent_req_callback_data(subreq,
2614 : struct dcerpc_send_request_state);
2615 7885 : int ret;
2616 7885 : int error;
2617 :
2618 336877 : ret = tstream_writev_queue_recv(subreq, &error);
2619 336877 : TALLOC_FREE(subreq);
2620 336877 : if (ret == -1) {
2621 31 : struct dcecli_connection *p = state->p;
2622 31 : NTSTATUS status = map_nt_error_from_unix_common(error);
2623 :
2624 31 : TALLOC_FREE(state);
2625 31 : dcerpc_transport_dead(p, status);
2626 31 : return;
2627 : }
2628 :
2629 336846 : TALLOC_FREE(state);
2630 : }
|