Coverage Report

Created: 2026-07-25 07:00

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