Coverage Report

Created: 2026-06-07 07:07

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/samba/libcli/named_pipe_auth/npa_tstream.c
Line
Count
Source
1
/*
2
   Unix SMB/CIFS implementation.
3
4
   Copyright (C) Stefan Metzmacher 2009
5
6
   This program is free software; you can redistribute it and/or modify
7
   it under the terms of the GNU General Public License as published by
8
   the Free Software Foundation; either version 3 of the License, or
9
   (at your option) any later version.
10
11
   This program is distributed in the hope that it will be useful,
12
   but WITHOUT ANY WARRANTY; without even the implied warranty of
13
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
   GNU General Public License for more details.
15
16
   You should have received a copy of the GNU General Public License
17
   along with this program.  If not, see <http://www.gnu.org/licenses/>.
18
*/
19
20
#include "includes.h"
21
#include "system/network.h"
22
#include "../util/tevent_unix.h"
23
#include "../lib/tsocket/tsocket.h"
24
#include "../lib/tsocket/tsocket_internal.h"
25
#include "../librpc/gen_ndr/ndr_named_pipe_auth.h"
26
#include "../libcli/named_pipe_auth/npa_tstream.h"
27
#include "../libcli/named_pipe_auth/tstream_u32_read.h"
28
#include "../libcli/smb/smb_constants.h"
29
30
static const struct tstream_context_ops tstream_npa_ops;
31
32
struct tstream_npa {
33
  struct tstream_context *unix_stream;
34
35
  uint16_t file_type;
36
37
  struct iovec pending;
38
};
39
40
struct tstream_npa_connect_state {
41
  struct {
42
    struct tevent_context *ev;
43
  } caller;
44
45
  const char *unix_path;
46
  struct tsocket_address *unix_laddr;
47
  struct tsocket_address *unix_raddr;
48
  struct tstream_context *unix_stream;
49
50
  struct named_pipe_auth_req auth_req;
51
  DATA_BLOB auth_req_blob;
52
  struct iovec auth_req_iov;
53
54
  struct named_pipe_auth_rep auth_rep;
55
};
56
57
static void tstream_npa_connect_unix_done(struct tevent_req *subreq);
58
59
struct tevent_req *tstream_npa_connect_send(TALLOC_CTX *mem_ctx,
60
              struct tevent_context *ev,
61
              const char *directory,
62
              const char *npipe,
63
              enum dcerpc_transport_t transport,
64
              const struct tsocket_address *remote_client_addr,
65
              const char *remote_client_name_in,
66
              const struct tsocket_address *local_server_addr,
67
              const char *local_server_name_in,
68
              const struct auth_session_info_transport *session_info)
69
0
{
70
0
  struct tevent_req *req;
71
0
  struct tstream_npa_connect_state *state;
72
0
  struct tevent_req *subreq;
73
0
  int ret;
74
0
  enum ndr_err_code ndr_err;
75
0
  char *lower_case_npipe;
76
0
  struct named_pipe_auth_req_info8 *info8;
77
78
0
  req = tevent_req_create(mem_ctx, &state,
79
0
        struct tstream_npa_connect_state);
80
0
  if (!req) {
81
0
    return NULL;
82
0
  }
83
84
0
  state->caller.ev = ev;
85
86
0
  lower_case_npipe = strlower_talloc(state, npipe);
87
0
  if (tevent_req_nomem(lower_case_npipe, req)) {
88
0
    goto post;
89
0
  }
90
91
0
  state->unix_path = talloc_asprintf(state, "%s/%s",
92
0
             directory,
93
0
             lower_case_npipe);
94
0
  talloc_free(lower_case_npipe);
95
0
  if (tevent_req_nomem(state->unix_path, req)) {
96
0
    goto post;
97
0
  }
98
99
0
  ret = tsocket_address_unix_from_path(state,
100
0
               "",
101
0
               &state->unix_laddr);
102
0
  if (ret == -1) {
103
0
    tevent_req_error(req, errno);
104
0
    goto post;
105
0
  }
106
107
0
  ret = tsocket_address_unix_from_path(state,
108
0
               state->unix_path,
109
0
               &state->unix_raddr);
110
0
  if (ret == -1) {
111
0
    tevent_req_error(req, errno);
112
0
    goto post;
113
0
  }
114
115
0
  ZERO_STRUCT(state->auth_req);
116
117
0
  if (!local_server_addr) {
118
0
    tevent_req_error(req, EINVAL);
119
0
    goto post;
120
0
  }
121
122
0
  state->auth_req.level = 8;
123
0
  info8 = &state->auth_req.info.info8;
124
125
0
  info8->transport = transport;
126
0
  SMB_ASSERT(info8->transport == transport); /* Assert no overflow */
127
128
0
  info8->remote_client_name = remote_client_name_in;
129
0
  info8->remote_client_addr =
130
0
    tsocket_address_inet_addr_string(remote_client_addr, state);
131
0
  if (!info8->remote_client_addr) {
132
    /* errno might be EINVAL */
133
0
    tevent_req_error(req, errno);
134
0
    goto post;
135
0
  }
136
0
  info8->remote_client_port =
137
0
    tsocket_address_inet_port(remote_client_addr);
138
0
  if (!info8->remote_client_name) {
139
0
    info8->remote_client_name = info8->remote_client_addr;
140
0
  }
141
142
0
  info8->local_server_name = local_server_name_in;
143
0
  info8->local_server_addr =
144
0
    tsocket_address_inet_addr_string(local_server_addr, state);
145
0
  if (!info8->local_server_addr) {
146
    /* errno might be EINVAL */
147
0
    tevent_req_error(req, errno);
148
0
    goto post;
149
0
  }
150
0
  info8->local_server_port =
151
0
    tsocket_address_inet_port(local_server_addr);
152
0
  if (!info8->local_server_name) {
153
0
    info8->local_server_name = info8->local_server_addr;
154
0
  }
155
156
0
  info8->session_info =
157
0
    discard_const_p(struct auth_session_info_transport,
158
0
        session_info);
159
160
0
  if (DEBUGLVL(10)) {
161
0
    NDR_PRINT_DEBUG(named_pipe_auth_req, &state->auth_req);
162
0
  }
163
164
0
  ndr_err = ndr_push_struct_blob(&state->auth_req_blob,
165
0
      state, &state->auth_req,
166
0
      (ndr_push_flags_fn_t)ndr_push_named_pipe_auth_req);
167
0
  if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
168
0
    tevent_req_error(req, EINVAL);
169
0
    goto post;
170
0
  }
171
172
0
  state->auth_req_iov.iov_base = (char *) state->auth_req_blob.data;
173
0
  state->auth_req_iov.iov_len = state->auth_req_blob.length;
174
175
0
  subreq = tstream_unix_connect_send(state,
176
0
             state->caller.ev,
177
0
             state->unix_laddr,
178
0
             state->unix_raddr);
179
0
  if (tevent_req_nomem(subreq, req)) {
180
0
    goto post;
181
0
  }
182
0
  tevent_req_set_callback(subreq, tstream_npa_connect_unix_done, req);
183
184
0
  return req;
185
186
0
post:
187
0
  tevent_req_post(req, ev);
188
0
  return req;
189
0
}
190
191
static void tstream_npa_connect_writev_done(struct tevent_req *subreq);
192
193
static void tstream_npa_connect_unix_done(struct tevent_req *subreq)
194
0
{
195
0
  struct tevent_req *req =
196
0
    tevent_req_callback_data(subreq,
197
0
    struct tevent_req);
198
0
  struct tstream_npa_connect_state *state =
199
0
    tevent_req_data(req,
200
0
    struct tstream_npa_connect_state);
201
0
  int ret;
202
0
  int sys_errno;
203
204
0
  ret = tstream_unix_connect_recv(subreq, &sys_errno,
205
0
          state, &state->unix_stream);
206
0
  TALLOC_FREE(subreq);
207
0
  if (ret == -1) {
208
0
    tevent_req_error(req, sys_errno);
209
0
    return;
210
0
  }
211
212
0
  subreq = tstream_writev_send(state,
213
0
             state->caller.ev,
214
0
             state->unix_stream,
215
0
             &state->auth_req_iov, 1);
216
0
  if (tevent_req_nomem(subreq, req)) {
217
0
    return;
218
0
  }
219
0
  tevent_req_set_callback(subreq, tstream_npa_connect_writev_done, req);
220
0
}
221
222
static void tstream_npa_connect_readv_done(struct tevent_req *subreq);
223
224
static void tstream_npa_connect_writev_done(struct tevent_req *subreq)
225
0
{
226
0
  struct tevent_req *req =
227
0
    tevent_req_callback_data(subreq,
228
0
    struct tevent_req);
229
0
  struct tstream_npa_connect_state *state =
230
0
    tevent_req_data(req,
231
0
    struct tstream_npa_connect_state);
232
0
  int ret;
233
0
  int sys_errno;
234
235
0
  ret = tstream_writev_recv(subreq, &sys_errno);
236
0
  TALLOC_FREE(subreq);
237
0
  if (ret == -1) {
238
0
    tevent_req_error(req, sys_errno);
239
0
    return;
240
0
  }
241
242
0
  subreq = tstream_u32_read_send(
243
0
    state, state->caller.ev, 0x00FFFFFF, state->unix_stream);
244
0
  if (tevent_req_nomem(subreq, req)) {
245
0
    return;
246
0
  }
247
0
  tevent_req_set_callback(subreq, tstream_npa_connect_readv_done, req);
248
0
}
249
250
static void tstream_npa_connect_readv_done(struct tevent_req *subreq)
251
0
{
252
0
  struct tevent_req *req =
253
0
    tevent_req_callback_data(subreq,
254
0
    struct tevent_req);
255
0
  struct tstream_npa_connect_state *state =
256
0
    tevent_req_data(req,
257
0
    struct tstream_npa_connect_state);
258
0
  DATA_BLOB in;
259
0
  int err;
260
0
  enum ndr_err_code ndr_err;
261
262
0
  err = tstream_u32_read_recv(subreq, state, &in.data, &in.length);
263
0
  TALLOC_FREE(subreq);
264
0
  if (tevent_req_error(req, err)) {
265
0
    return;
266
0
  }
267
268
0
  DBG_DEBUG("name_pipe_auth_rep(client)[%zu]\n", in.length);
269
0
  dump_data(11, in.data, in.length);
270
271
0
  ndr_err = ndr_pull_struct_blob_all(
272
0
    &in,
273
0
    state,
274
0
    &state->auth_rep,
275
0
    (ndr_pull_flags_fn_t)ndr_pull_named_pipe_auth_rep);
276
277
0
  if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
278
0
    DEBUG(0, ("ndr_pull_named_pipe_auth_rep failed: %s\n",
279
0
        ndr_map_error2string(ndr_err)));
280
0
    tevent_req_error(req, EIO);
281
0
    return;
282
0
  }
283
284
0
  if (DEBUGLVL(10)) {
285
0
    NDR_PRINT_DEBUG(named_pipe_auth_rep, &state->auth_rep);
286
0
  }
287
288
0
  if (state->auth_rep.length < 16) {
289
0
    DEBUG(0, ("req invalid length: %u < 16\n",
290
0
        state->auth_rep.length));
291
0
    tevent_req_error(req, EIO);
292
0
    return;
293
0
  }
294
295
0
  if (strcmp(NAMED_PIPE_AUTH_MAGIC, state->auth_rep.magic) != 0) {
296
0
    DEBUG(0, ("req invalid magic: %s != %s\n",
297
0
        state->auth_rep.magic, NAMED_PIPE_AUTH_MAGIC));
298
0
    tevent_req_error(req, EIO);
299
0
    return;
300
0
  }
301
302
0
  if (!NT_STATUS_IS_OK(state->auth_rep.status)) {
303
0
    DEBUG(0, ("req failed: %s\n",
304
0
        nt_errstr(state->auth_rep.status)));
305
0
    tevent_req_error(req, EACCES);
306
0
    return;
307
0
  }
308
309
0
  if (state->auth_rep.level != state->auth_req.level) {
310
0
    DEBUG(0, ("req invalid level: %u != %u\n",
311
0
        state->auth_rep.level, state->auth_req.level));
312
0
    tevent_req_error(req, EIO);
313
0
    return;
314
0
  }
315
316
0
  tevent_req_done(req);
317
0
}
318
319
int _tstream_npa_connect_recv(struct tevent_req *req,
320
            int *perrno,
321
            TALLOC_CTX *mem_ctx,
322
            struct tstream_context **_stream,
323
            uint16_t *_file_type,
324
            uint16_t *_device_state,
325
            uint64_t *_allocation_size,
326
            const char *location)
327
0
{
328
0
  struct tstream_npa_connect_state *state =
329
0
    tevent_req_data(req,
330
0
    struct tstream_npa_connect_state);
331
0
  struct tstream_context *stream;
332
0
  struct tstream_npa *npas;
333
0
  uint16_t device_state = 0;
334
0
  uint64_t allocation_size = 0;
335
336
0
  if (tevent_req_is_unix_error(req, perrno)) {
337
0
    tevent_req_received(req);
338
0
    return -1;
339
0
  }
340
341
0
  stream = tstream_context_create(mem_ctx,
342
0
          &tstream_npa_ops,
343
0
          &npas,
344
0
          struct tstream_npa,
345
0
          location);
346
0
  if (!stream) {
347
0
    *perrno = ENOMEM;
348
0
    tevent_req_received(req);
349
0
    return -1;
350
0
  }
351
0
  ZERO_STRUCTP(npas);
352
353
0
  npas->unix_stream = talloc_move(stream, &state->unix_stream);
354
0
  switch (state->auth_rep.level) {
355
0
  case 8:
356
0
    npas->file_type = state->auth_rep.info.info8.file_type;
357
0
    device_state = state->auth_rep.info.info8.device_state;
358
0
    allocation_size = state->auth_rep.info.info8.allocation_size;
359
0
    break;
360
0
  }
361
362
0
  *_stream = stream;
363
0
  *_file_type = npas->file_type;
364
0
  *_device_state = device_state;
365
0
  *_allocation_size = allocation_size;
366
0
  tevent_req_received(req);
367
0
  return 0;
368
0
}
369
370
static ssize_t tstream_npa_pending_bytes(struct tstream_context *stream)
371
0
{
372
0
  struct tstream_npa *npas = tstream_context_data(stream,
373
0
           struct tstream_npa);
374
0
  ssize_t ret;
375
376
0
  if (!npas->unix_stream) {
377
0
    errno = ENOTCONN;
378
0
    return -1;
379
0
  }
380
381
0
  switch (npas->file_type) {
382
0
  case FILE_TYPE_BYTE_MODE_PIPE:
383
0
    ret = tstream_pending_bytes(npas->unix_stream);
384
0
    break;
385
386
0
  case FILE_TYPE_MESSAGE_MODE_PIPE:
387
0
    ret = npas->pending.iov_len;
388
0
    break;
389
390
0
  default:
391
0
    ret = -1;
392
0
  }
393
394
0
  return ret;
395
0
}
396
397
struct tstream_npa_readv_state {
398
  struct tstream_context *stream;
399
400
  struct iovec *vector;
401
  size_t count;
402
403
  /* the header for message mode */
404
  uint8_t hdr[2];
405
  bool wait_for_hdr;
406
407
  int ret;
408
};
409
410
static void tstream_npa_readv_byte_mode_handler(struct tevent_req *subreq);
411
static int tstream_npa_readv_next_vector(struct tstream_context *stream,
412
           void *private_data,
413
           TALLOC_CTX *mem_ctx,
414
           struct iovec **_vector,
415
           size_t *_count);
416
static void tstream_npa_readv_msg_mode_handler(struct tevent_req *subreq);
417
418
static struct tevent_req *tstream_npa_readv_send(TALLOC_CTX *mem_ctx,
419
          struct tevent_context *ev,
420
          struct tstream_context *stream,
421
          struct iovec *vector,
422
          size_t count)
423
0
{
424
0
  struct tevent_req *req;
425
0
  struct tstream_npa_readv_state *state;
426
0
  struct tstream_npa *npas = tstream_context_data(stream, struct tstream_npa);
427
0
  struct tevent_req *subreq;
428
0
  off_t ofs;
429
0
  size_t left;
430
0
  uint8_t *pbase;
431
432
0
  req = tevent_req_create(mem_ctx, &state,
433
0
        struct tstream_npa_readv_state);
434
0
  if (!req) {
435
0
    return NULL;
436
0
  }
437
438
0
  state->stream = stream;
439
0
  state->ret  = 0;
440
441
0
  if (!npas->unix_stream) {
442
0
    tevent_req_error(req, ENOTCONN);
443
0
    goto post;
444
0
  }
445
446
0
  switch (npas->file_type) {
447
0
  case FILE_TYPE_BYTE_MODE_PIPE:
448
0
    state->vector = vector;
449
0
    state->count = count;
450
451
0
    subreq = tstream_readv_send(state,
452
0
              ev,
453
0
              npas->unix_stream,
454
0
              state->vector,
455
0
              state->count);
456
0
    if (tevent_req_nomem(subreq,req)) {
457
0
      goto post;
458
0
    }
459
0
    tevent_req_set_callback(subreq,
460
0
          tstream_npa_readv_byte_mode_handler,
461
0
          req);
462
463
0
    return req;
464
465
0
  case FILE_TYPE_MESSAGE_MODE_PIPE:
466
    /*
467
     * we make a copy of the vector and prepend a header
468
     * with the length
469
     */
470
0
    state->vector = talloc_array(state, struct iovec, count);
471
0
    if (tevent_req_nomem(state->vector, req)) {
472
0
      goto post;
473
0
    }
474
0
    memcpy(state->vector, vector, sizeof(struct iovec)*count);
475
0
    state->count = count;
476
477
    /*
478
     * copy the pending buffer first
479
     */
480
0
    ofs = 0;
481
0
    left = npas->pending.iov_len;
482
0
    pbase = (uint8_t *)npas->pending.iov_base;
483
484
0
    while (left > 0 && state->count > 0) {
485
0
      uint8_t *base;
486
0
      base = (uint8_t *)state->vector[0].iov_base;
487
0
      if (left < state->vector[0].iov_len) {
488
0
        memcpy(base, pbase + ofs, left);
489
490
0
        base += left;
491
0
        state->vector[0].iov_base = (char *) base;
492
0
        state->vector[0].iov_len -= left;
493
494
0
        ofs += left;
495
0
        left = 0;
496
0
        TALLOC_FREE(pbase);
497
0
        ZERO_STRUCT(npas->pending);
498
0
        break;
499
0
      }
500
0
      memcpy(base, pbase + ofs, state->vector[0].iov_len);
501
502
0
      ofs += state->vector[0].iov_len;
503
0
      left -= state->vector[0].iov_len;
504
0
      state->vector += 1;
505
0
      state->count -= 1;
506
507
0
      if (left == 0) {
508
0
        TALLOC_FREE(pbase);
509
0
        ZERO_STRUCT(npas->pending);
510
0
        break;
511
0
      }
512
0
    }
513
514
0
    if (left > 0) {
515
0
      memmove(pbase, pbase + ofs, left);
516
0
      npas->pending.iov_base = (char *) pbase;
517
0
      npas->pending.iov_len = left;
518
      /*
519
       * this cannot fail and even if it
520
       * fails we can handle it
521
       */
522
0
      pbase = talloc_realloc(npas, pbase, uint8_t, left);
523
0
      if (pbase) {
524
0
        npas->pending.iov_base = (char *) pbase;
525
0
      }
526
0
      pbase = NULL;
527
0
    }
528
529
0
    state->ret += ofs;
530
531
0
    if (state->count == 0) {
532
0
      tevent_req_done(req);
533
0
      goto post;
534
0
    }
535
536
0
    ZERO_STRUCT(state->hdr);
537
0
    state->wait_for_hdr = false;
538
539
0
    subreq = tstream_readv_pdu_send(state,
540
0
            ev,
541
0
            npas->unix_stream,
542
0
            tstream_npa_readv_next_vector,
543
0
            state);
544
0
    if (tevent_req_nomem(subreq, req)) {
545
0
      goto post;
546
0
    }
547
0
    tevent_req_set_callback(subreq,
548
0
          tstream_npa_readv_msg_mode_handler,
549
0
          req);
550
551
0
    return req;
552
0
  }
553
554
  /* this can't happen */
555
0
  tevent_req_error(req, EINVAL);
556
0
  goto post;
557
558
0
 post:
559
0
  tevent_req_post(req, ev);
560
0
  return req;
561
0
}
562
563
static void tstream_npa_readv_byte_mode_handler(struct tevent_req *subreq)
564
0
{
565
0
  struct tevent_req *req = tevent_req_callback_data(subreq,
566
0
         struct tevent_req);
567
0
  struct tstream_npa_readv_state *state = tevent_req_data(req,
568
0
          struct tstream_npa_readv_state);
569
0
  int ret;
570
0
  int sys_errno;
571
572
0
  ret = tstream_readv_recv(subreq, &sys_errno);
573
0
  TALLOC_FREE(subreq);
574
0
  if (ret == -1) {
575
0
    tevent_req_error(req, sys_errno);
576
0
    return;
577
0
  }
578
579
0
  state->ret = ret;
580
581
0
  tevent_req_done(req);
582
0
}
583
584
static int tstream_npa_readv_next_vector(struct tstream_context *unix_stream,
585
           void *private_data,
586
           TALLOC_CTX *mem_ctx,
587
           struct iovec **_vector,
588
           size_t *_count)
589
0
{
590
0
  struct tstream_npa_readv_state *state = talloc_get_type_abort(private_data,
591
0
          struct tstream_npa_readv_state);
592
0
  struct tstream_npa *npas = tstream_context_data(state->stream,
593
0
           struct tstream_npa);
594
0
  struct iovec *vector;
595
0
  size_t count;
596
0
  uint16_t msg_len;
597
0
  size_t left;
598
599
0
  if (state->count == 0) {
600
0
    *_vector = NULL;
601
0
    *_count = 0;
602
0
    return 0;
603
0
  }
604
605
0
  if (!state->wait_for_hdr) {
606
    /* we need to get a message header */
607
0
    vector = talloc_array(mem_ctx, struct iovec, 1);
608
0
    if (!vector) {
609
0
      return -1;
610
0
    }
611
0
    ZERO_STRUCT(state->hdr);
612
0
    vector[0].iov_base = (char *) state->hdr;
613
0
    vector[0].iov_len = sizeof(state->hdr);
614
615
0
    count = 1;
616
617
0
    state->wait_for_hdr = true;
618
619
0
    *_vector = vector;
620
0
    *_count = count;
621
0
    return 0;
622
0
  }
623
624
  /* and now fill the callers buffers and maybe the pending buffer */
625
0
  state->wait_for_hdr = false;
626
627
0
  msg_len = SVAL(state->hdr, 0);
628
629
0
  if (msg_len == 0) {
630
0
    errno = EIO;
631
0
    return -1;
632
0
  }
633
634
0
  state->wait_for_hdr = false;
635
636
  /* +1 because we may need to fill the pending buffer */
637
0
  vector = talloc_array(mem_ctx, struct iovec, state->count + 1);
638
0
  if (!vector) {
639
0
    return -1;
640
0
  }
641
642
0
  count = 0;
643
0
  left = msg_len;
644
0
  while (left > 0 && state->count > 0) {
645
0
    if (left < state->vector[0].iov_len) {
646
0
      uint8_t *base;
647
0
      base = (uint8_t *)state->vector[0].iov_base;
648
0
      vector[count].iov_base = (char *) base;
649
0
      vector[count].iov_len = left;
650
0
      count++;
651
0
      base += left;
652
0
      state->vector[0].iov_base = (char *) base;
653
0
      state->vector[0].iov_len -= left;
654
0
      break;
655
0
    }
656
0
    vector[count] = state->vector[0];
657
0
    count++;
658
0
    left -= state->vector[0].iov_len;
659
0
    state->vector += 1;
660
0
    state->count -= 1;
661
0
  }
662
663
0
  if (left > 0) {
664
    /*
665
     * if the message is longer than the buffers the caller
666
     * requested, we need to consume the rest of the message
667
     * into the pending buffer, where the next readv can
668
     * be served from.
669
     */
670
0
    npas->pending.iov_base = talloc_array(npas, char, left);
671
0
    if (!npas->pending.iov_base) {
672
0
      return -1;
673
0
    }
674
0
    npas->pending.iov_len = left;
675
676
0
    vector[count] = npas->pending;
677
0
    count++;
678
0
  }
679
680
0
  state->ret += (msg_len - left);
681
682
0
  *_vector = vector;
683
0
  *_count = count;
684
0
  return 0;
685
0
}
686
687
static void tstream_npa_readv_msg_mode_handler(struct tevent_req *subreq)
688
0
{
689
0
  struct tevent_req *req = tevent_req_callback_data(subreq,
690
0
         struct tevent_req);
691
0
  int ret;
692
0
  int sys_errno;
693
694
0
  ret = tstream_readv_pdu_recv(subreq, &sys_errno);
695
0
  TALLOC_FREE(subreq);
696
0
  if (ret == -1) {
697
0
    tevent_req_error(req, sys_errno);
698
0
    return;
699
0
  }
700
701
  /*
702
   * we do not set state->ret here as ret includes the header size.
703
   * we set it in tstream_npa_readv_pdu_next_vector()
704
   */
705
706
0
  tevent_req_done(req);
707
0
}
708
709
static int tstream_npa_readv_recv(struct tevent_req *req,
710
           int *perrno)
711
0
{
712
0
  struct tstream_npa_readv_state *state = tevent_req_data(req,
713
0
          struct tstream_npa_readv_state);
714
0
  int ret;
715
716
0
  ret = tsocket_simple_int_recv(req, perrno);
717
0
  if (ret == 0) {
718
0
    ret = state->ret;
719
0
  }
720
721
0
  tevent_req_received(req);
722
0
  return ret;
723
0
}
724
725
struct tstream_npa_writev_state {
726
  const struct iovec *vector;
727
  size_t count;
728
729
  /* the header for message mode */
730
  bool hdr_used;
731
  uint8_t hdr[2];
732
733
  int ret;
734
};
735
736
static void tstream_npa_writev_handler(struct tevent_req *subreq);
737
738
static struct tevent_req *tstream_npa_writev_send(TALLOC_CTX *mem_ctx,
739
          struct tevent_context *ev,
740
          struct tstream_context *stream,
741
          const struct iovec *vector,
742
          size_t count)
743
0
{
744
0
  struct tevent_req *req;
745
0
  struct tstream_npa_writev_state *state;
746
0
  struct tstream_npa *npas = tstream_context_data(stream, struct tstream_npa);
747
0
  struct tevent_req *subreq;
748
0
  size_t msg_len;
749
0
  size_t i;
750
0
  struct iovec *new_vector;
751
752
0
  req = tevent_req_create(mem_ctx, &state,
753
0
        struct tstream_npa_writev_state);
754
0
  if (!req) {
755
0
    return NULL;
756
0
  }
757
758
0
  state->ret  = 0;
759
760
0
  if (!npas->unix_stream) {
761
0
    tevent_req_error(req, ENOTCONN);
762
0
    goto post;
763
0
  }
764
765
0
  switch (npas->file_type) {
766
0
  case FILE_TYPE_BYTE_MODE_PIPE:
767
0
    state->hdr_used = false;
768
0
    state->vector = vector;
769
0
    state->count  = count;
770
0
    break;
771
772
0
  case FILE_TYPE_MESSAGE_MODE_PIPE:
773
    /*
774
     * we make a copy of the vector and prepend a header
775
     * with the length
776
     */
777
0
    new_vector  = talloc_array(state, struct iovec, count + 1);
778
0
    if (tevent_req_nomem(new_vector, req)) {
779
0
      goto post;
780
0
    }
781
0
    new_vector[0].iov_base = (char *) state->hdr;
782
0
    new_vector[0].iov_len = sizeof(state->hdr);
783
0
    memcpy(new_vector + 1, vector, sizeof(struct iovec)*count);
784
785
0
    state->hdr_used = true;
786
0
    state->vector = new_vector;
787
0
    state->count  = count + 1;
788
789
0
    msg_len = 0;
790
0
    for (i=0; i < count; i++) {
791
      /*
792
       * overflow check already done in tstream_writev_send
793
       */
794
0
      msg_len += vector[i].iov_len;
795
0
    }
796
797
0
    if (msg_len > UINT16_MAX) {
798
0
      tevent_req_error(req, EMSGSIZE);
799
0
      goto post;
800
0
    }
801
802
0
    SSVAL(state->hdr, 0, msg_len);
803
0
    break;
804
0
  }
805
806
0
  subreq = tstream_writev_send(state,
807
0
             ev,
808
0
             npas->unix_stream,
809
0
             state->vector,
810
0
             state->count);
811
0
  if (tevent_req_nomem(subreq, req)) {
812
0
    goto post;
813
0
  }
814
0
  tevent_req_set_callback(subreq, tstream_npa_writev_handler, req);
815
816
0
  return req;
817
818
0
 post:
819
0
  tevent_req_post(req, ev);
820
0
  return req;
821
0
}
822
823
static void tstream_npa_writev_handler(struct tevent_req *subreq)
824
0
{
825
0
  struct tevent_req *req = tevent_req_callback_data(subreq,
826
0
         struct tevent_req);
827
0
  struct tstream_npa_writev_state *state = tevent_req_data(req,
828
0
          struct tstream_npa_writev_state);
829
0
  int ret;
830
0
  int sys_errno;
831
832
0
  ret = tstream_writev_recv(subreq, &sys_errno);
833
0
  TALLOC_FREE(subreq);
834
0
  if (ret == -1) {
835
0
    tevent_req_error(req, sys_errno);
836
0
    return;
837
0
  }
838
839
  /*
840
   * in message mode we need to hide the length
841
   * of the hdr from the caller
842
   */
843
0
  if (state->hdr_used) {
844
0
    ret -= sizeof(state->hdr);
845
0
  }
846
847
0
  state->ret = ret;
848
849
0
  tevent_req_done(req);
850
0
}
851
852
static int tstream_npa_writev_recv(struct tevent_req *req,
853
           int *perrno)
854
0
{
855
0
  struct tstream_npa_writev_state *state = tevent_req_data(req,
856
0
          struct tstream_npa_writev_state);
857
0
  int ret;
858
859
0
  ret = tsocket_simple_int_recv(req, perrno);
860
0
  if (ret == 0) {
861
0
    ret = state->ret;
862
0
  }
863
864
0
  tevent_req_received(req);
865
0
  return ret;
866
0
}
867
868
struct tstream_npa_disconnect_state {
869
  struct tstream_context *stream;
870
};
871
872
static void tstream_npa_disconnect_handler(struct tevent_req *subreq);
873
874
static struct tevent_req *tstream_npa_disconnect_send(TALLOC_CTX *mem_ctx,
875
            struct tevent_context *ev,
876
            struct tstream_context *stream)
877
0
{
878
0
  struct tstream_npa *npas = tstream_context_data(stream, struct tstream_npa);
879
0
  struct tevent_req *req;
880
0
  struct tstream_npa_disconnect_state *state;
881
0
  struct tevent_req *subreq;
882
883
0
  req = tevent_req_create(mem_ctx, &state,
884
0
        struct tstream_npa_disconnect_state);
885
0
  if (req == NULL) {
886
0
    return NULL;
887
0
  }
888
889
0
  state->stream = stream;
890
891
0
  if (!npas->unix_stream) {
892
0
    tevent_req_error(req, ENOTCONN);
893
0
    goto post;
894
0
  }
895
896
0
  subreq = tstream_disconnect_send(state,
897
0
           ev,
898
0
           npas->unix_stream);
899
0
  if (tevent_req_nomem(subreq, req)) {
900
0
    goto post;
901
0
  }
902
0
  tevent_req_set_callback(subreq, tstream_npa_disconnect_handler, req);
903
904
0
  return req;
905
906
0
post:
907
0
  tevent_req_post(req, ev);
908
0
  return req;
909
0
}
910
911
static void tstream_npa_disconnect_handler(struct tevent_req *subreq)
912
0
{
913
0
  struct tevent_req *req = tevent_req_callback_data(subreq,
914
0
         struct tevent_req);
915
0
  struct tstream_npa_disconnect_state *state = tevent_req_data(req,
916
0
          struct tstream_npa_disconnect_state);
917
0
  struct tstream_context *stream = state->stream;
918
0
  struct tstream_npa *npas = tstream_context_data(stream, struct tstream_npa);
919
0
  int ret;
920
0
  int sys_errno;
921
922
0
  ret = tstream_disconnect_recv(subreq, &sys_errno);
923
0
  TALLOC_FREE(subreq);
924
0
  if (ret == -1) {
925
0
    tevent_req_error(req, sys_errno);
926
0
    return;
927
0
  }
928
929
0
  TALLOC_FREE(npas->unix_stream);
930
931
0
  tevent_req_done(req);
932
0
}
933
934
static int tstream_npa_disconnect_recv(struct tevent_req *req,
935
               int *perrno)
936
0
{
937
0
  int ret;
938
939
0
  ret = tsocket_simple_int_recv(req, perrno);
940
941
0
  tevent_req_received(req);
942
0
  return ret;
943
0
}
944
945
struct tstream_npa_monitor_state {
946
  struct tevent_req *subreq;
947
};
948
949
static void tstream_npa_monitor_cleanup(struct tevent_req *req,
950
          enum tevent_req_state req_state)
951
0
{
952
0
  struct tstream_npa_monitor_state *state =
953
0
    tevent_req_data(req,
954
0
    struct tstream_npa_monitor_state);
955
956
0
  TALLOC_FREE(state->subreq);
957
0
}
958
959
static void tstream_npa_monitor_done(struct tevent_req *subreq);
960
961
static struct tevent_req *tstream_npa_monitor_send(TALLOC_CTX *mem_ctx,
962
          struct tevent_context *ev,
963
          struct tstream_context *stream)
964
0
{
965
0
  struct tevent_req *req = NULL;
966
0
  struct tstream_npa_monitor_state *state = NULL;
967
0
  struct tstream_npa *npas =
968
0
    tstream_context_data(stream, struct tstream_npa);
969
970
0
  req = tevent_req_create(mem_ctx, &state,
971
0
        struct tstream_npa_monitor_state);
972
0
  if (req == NULL) {
973
0
    return NULL;
974
0
  }
975
976
0
  tevent_req_set_cleanup_fn(req, tstream_npa_monitor_cleanup);
977
978
0
  state->subreq = tstream_monitor_send(state,
979
0
               ev,
980
0
               npas->unix_stream);
981
0
  if (tevent_req_nomem(state->subreq, req)) {
982
0
    return tevent_req_post(req, ev);
983
0
  }
984
0
  tevent_req_set_callback(state->subreq,
985
0
        tstream_npa_monitor_done,
986
0
        req);
987
988
0
  return req;
989
0
}
990
991
static void tstream_npa_monitor_done(struct tevent_req *subreq)
992
0
{
993
0
  struct tevent_req *req =
994
0
    tevent_req_callback_data(subreq,
995
0
    struct tevent_req);
996
0
  struct tstream_npa_monitor_state *state =
997
0
    tevent_req_data(req,
998
0
    struct tstream_npa_monitor_state);
999
0
  int ret;
1000
0
  int sys_error = EPIPE;
1001
1002
0
  state->subreq = NULL;
1003
1004
0
  ret = tstream_monitor_recv(subreq, &sys_error);
1005
0
  TALLOC_FREE(subreq);
1006
0
  if (ret == 0) {
1007
0
    sys_error = EPIPE;
1008
0
  }
1009
0
  if (sys_error == 0) {
1010
0
    sys_error = EPIPE;
1011
0
  }
1012
1013
0
  tevent_req_error(req, sys_error);
1014
0
}
1015
1016
static int tstream_npa_monitor_recv(struct tevent_req *req,
1017
            int *perrno)
1018
0
{
1019
0
  int ret;
1020
1021
0
  ret = tsocket_simple_int_recv(req, perrno);
1022
1023
0
  tevent_req_received(req);
1024
0
  return ret;
1025
0
}
1026
1027
static const struct tstream_context_ops tstream_npa_ops = {
1028
  .name     = "npa",
1029
1030
  .pending_bytes    = tstream_npa_pending_bytes,
1031
1032
  .readv_send   = tstream_npa_readv_send,
1033
  .readv_recv   = tstream_npa_readv_recv,
1034
1035
  .writev_send    = tstream_npa_writev_send,
1036
  .writev_recv    = tstream_npa_writev_recv,
1037
1038
  .disconnect_send  = tstream_npa_disconnect_send,
1039
  .disconnect_recv  = tstream_npa_disconnect_recv,
1040
1041
  .monitor_send   = tstream_npa_monitor_send,
1042
  .monitor_recv   = tstream_npa_monitor_recv,
1043
};
1044
1045
int _tstream_npa_existing_stream(TALLOC_CTX *mem_ctx,
1046
         struct tstream_context **transport,
1047
         uint16_t file_type,
1048
         struct tstream_context **_stream,
1049
         const char *location)
1050
0
{
1051
0
  struct tstream_context *stream;
1052
0
  struct tstream_npa *npas;
1053
1054
0
  switch (file_type) {
1055
0
  case FILE_TYPE_BYTE_MODE_PIPE:
1056
0
    break;
1057
0
  case FILE_TYPE_MESSAGE_MODE_PIPE:
1058
0
    break;
1059
0
  default:
1060
0
    errno = EINVAL;
1061
0
    return -1;
1062
0
  }
1063
1064
0
  stream = tstream_context_create(mem_ctx,
1065
0
          &tstream_npa_ops,
1066
0
          &npas,
1067
0
          struct tstream_npa,
1068
0
          location);
1069
0
  if (!stream) {
1070
0
    return -1;
1071
0
  }
1072
1073
0
  *npas = (struct tstream_npa) {
1074
0
    .file_type = file_type,
1075
0
    .unix_stream = talloc_move(npas, transport),
1076
0
  };
1077
1078
0
  *_stream = stream;
1079
0
  return 0;
1080
0
}
1081
1082
int _tstream_npa_existing_socket(TALLOC_CTX *mem_ctx,
1083
         int fd,
1084
         uint16_t file_type,
1085
         struct tstream_context **_stream,
1086
         const char *location)
1087
0
{
1088
0
  struct tstream_context *transport = NULL;
1089
0
  int ret;
1090
1091
0
  ret = _tstream_bsd_existing_socket(
1092
0
    mem_ctx, fd, &transport, location);
1093
0
  if (ret == -1) {
1094
0
    return -1;
1095
0
  }
1096
  /* as server we want to fail early */
1097
0
  tstream_bsd_fail_readv_first_error(transport, true);
1098
0
  return _tstream_npa_existing_stream(
1099
0
    mem_ctx, &transport, file_type, _stream, location);
1100
0
}
1101
1102
struct tstream_npa_accept_state {
1103
  struct tevent_context *ev;
1104
  struct tstream_context *plain;
1105
  uint16_t file_type;
1106
  uint16_t device_state;
1107
  uint64_t alloc_size;
1108
1109
  struct named_pipe_auth_req *pipe_request;
1110
1111
  DATA_BLOB npa_blob;
1112
  struct iovec out_iov;
1113
1114
  /* results */
1115
  NTSTATUS accept_status;
1116
  struct tsocket_address *remote_client_addr;
1117
  struct tsocket_address *local_server_addr;
1118
};
1119
1120
static void tstream_npa_accept_existing_reply(struct tevent_req *subreq);
1121
static void tstream_npa_accept_existing_done(struct tevent_req *subreq);
1122
1123
struct tevent_req *tstream_npa_accept_existing_send(TALLOC_CTX *mem_ctx,
1124
          struct tevent_context *ev,
1125
          struct tstream_context *plain,
1126
          uint16_t file_type,
1127
          uint16_t device_state,
1128
          uint64_t allocation_size)
1129
0
{
1130
0
  struct tstream_npa_accept_state *state;
1131
0
  struct tevent_req *req, *subreq;
1132
1133
0
  req = tevent_req_create(mem_ctx, &state,
1134
0
        struct tstream_npa_accept_state);
1135
0
  if (req == NULL) {
1136
0
    return NULL;
1137
0
  }
1138
1139
0
  switch (file_type) {
1140
0
  case FILE_TYPE_BYTE_MODE_PIPE:
1141
0
    break;
1142
0
  case FILE_TYPE_MESSAGE_MODE_PIPE:
1143
0
    break;
1144
0
  default:
1145
0
    tevent_req_error(req, EINVAL);
1146
0
    goto post;
1147
0
  }
1148
1149
0
  state->ev = ev;
1150
0
  state->plain = plain;
1151
0
  state->file_type = file_type;
1152
0
  state->device_state = device_state;
1153
0
  state->alloc_size = allocation_size;
1154
1155
0
  subreq = tstream_u32_read_send(state, ev, 0x00FFFFFF, plain);
1156
0
  if (tevent_req_nomem(subreq, req)) {
1157
0
    goto post;
1158
0
  }
1159
1160
0
  tevent_req_set_callback(subreq,
1161
0
        tstream_npa_accept_existing_reply, req);
1162
1163
0
  return req;
1164
1165
0
post:
1166
0
  tevent_req_post(req, ev);
1167
0
  return req;
1168
0
}
1169
1170
static void tstream_npa_accept_existing_reply(struct tevent_req *subreq)
1171
0
{
1172
0
  struct tevent_req *req =
1173
0
      tevent_req_callback_data(subreq, struct tevent_req);
1174
0
  struct tstream_npa_accept_state *state =
1175
0
      tevent_req_data(req, struct tstream_npa_accept_state);
1176
0
  struct named_pipe_auth_req *pipe_request;
1177
0
  struct named_pipe_auth_rep pipe_reply;
1178
0
  struct named_pipe_auth_req_info8 i8;
1179
0
  enum ndr_err_code ndr_err;
1180
0
  DATA_BLOB in, out;
1181
0
  int err;
1182
0
  int ret;
1183
1184
0
  err = tstream_u32_read_recv(subreq, state, &in.data, &in.length);
1185
0
  if (err != 0) {
1186
0
    tevent_req_error(req, err);
1187
0
    return;
1188
0
  }
1189
0
  if (in.length < 8) {
1190
0
    tevent_req_error(req, EMSGSIZE);
1191
0
    return;
1192
0
  }
1193
1194
0
  if (memcmp(&in.data[4], NAMED_PIPE_AUTH_MAGIC, 4) != 0) {
1195
0
    DBG_ERR("Wrong protocol\n");
1196
0
#if defined(EPROTONOSUPPORT)
1197
0
    err = EPROTONOSUPPORT;
1198
#elif defined(EPROTO)
1199
    err = EPROTO;
1200
#else
1201
    err = EINVAL;
1202
#endif
1203
0
    tevent_req_error(req, err);
1204
0
    return;
1205
0
  }
1206
1207
0
  DBG_DEBUG("Received packet of length %zu\n", in.length);
1208
0
  dump_data(11, in.data, in.length);
1209
1210
0
  ZERO_STRUCT(pipe_reply);
1211
0
  pipe_reply.level = 0;
1212
0
  pipe_reply.status = NT_STATUS_INTERNAL_ERROR;
1213
  /*
1214
   * TODO: check it's a root (uid == 0) pipe
1215
   */
1216
1217
0
  pipe_request = talloc(state, struct named_pipe_auth_req);
1218
0
  if (!pipe_request) {
1219
0
    DEBUG(0, ("Out of memory!\n"));
1220
0
    goto reply;
1221
0
  }
1222
0
  state->pipe_request = pipe_request;
1223
1224
  /* parse the passed credentials */
1225
0
  ndr_err = ndr_pull_struct_blob_all(
1226
0
    &in,
1227
0
    pipe_request,
1228
0
    pipe_request,
1229
0
    (ndr_pull_flags_fn_t)ndr_pull_named_pipe_auth_req);
1230
0
  if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1231
0
    pipe_reply.status = ndr_map_error2ntstatus(ndr_err);
1232
0
    DEBUG(2, ("Could not unmarshall named_pipe_auth_req: %s\n",
1233
0
        nt_errstr(pipe_reply.status)));
1234
0
    goto reply;
1235
0
  }
1236
1237
0
  if (DEBUGLVL(10)) {
1238
0
    NDR_PRINT_DEBUG(named_pipe_auth_req, pipe_request);
1239
0
  }
1240
1241
0
  ZERO_STRUCT(i8);
1242
1243
0
  if (pipe_request->level != 8) {
1244
0
    DEBUG(0, ("Unknown level %u\n", pipe_request->level));
1245
0
    pipe_reply.level = 0;
1246
0
    pipe_reply.status = NT_STATUS_INVALID_LEVEL;
1247
0
    goto reply;
1248
0
  }
1249
1250
0
  pipe_reply.level = 8;
1251
0
  pipe_reply.status = NT_STATUS_OK;
1252
0
  pipe_reply.info.info8.file_type = state->file_type;
1253
0
  pipe_reply.info.info8.device_state = state->device_state;
1254
0
  pipe_reply.info.info8.allocation_size = state->alloc_size;
1255
1256
0
  i8 = pipe_request->info.info8;
1257
0
  if (i8.local_server_addr == NULL) {
1258
0
    pipe_reply.status = NT_STATUS_INVALID_ADDRESS;
1259
0
    DEBUG(2, ("Missing local server address\n"));
1260
0
    goto reply;
1261
0
  }
1262
0
  if (i8.remote_client_addr == NULL) {
1263
0
    pipe_reply.status = NT_STATUS_INVALID_ADDRESS;
1264
0
    DEBUG(2, ("Missing remote client address\n"));
1265
0
    goto reply;
1266
0
  }
1267
1268
0
  ret = tsocket_address_inet_from_strings(state,
1269
0
            "ip",
1270
0
            i8.local_server_addr,
1271
0
            i8.local_server_port,
1272
0
            &state->local_server_addr);
1273
0
  if (ret != 0) {
1274
0
    DEBUG(2,
1275
0
          ("Invalid local server address[%s:%u] - %s\n",
1276
0
           i8.local_server_addr,
1277
0
           i8.local_server_port,
1278
0
           strerror(errno)));
1279
0
    pipe_reply.status = NT_STATUS_INVALID_ADDRESS;
1280
0
    goto reply;
1281
0
  }
1282
1283
0
  ret = tsocket_address_inet_from_strings(state,
1284
0
            "ip",
1285
0
            i8.remote_client_addr,
1286
0
            i8.remote_client_port,
1287
0
            &state->remote_client_addr);
1288
0
  if (ret != 0) {
1289
0
    DEBUG(2,
1290
0
          ("Invalid remote client address[%s:%u] - %s\n",
1291
0
           i8.remote_client_addr,
1292
0
           i8.remote_client_port,
1293
0
           strerror(errno)));
1294
0
    pipe_reply.status = NT_STATUS_INVALID_ADDRESS;
1295
0
    goto reply;
1296
0
  }
1297
1298
0
reply:
1299
  /* create the output */
1300
0
  ndr_err = ndr_push_struct_blob(&out, state, &pipe_reply,
1301
0
      (ndr_push_flags_fn_t)ndr_push_named_pipe_auth_rep);
1302
0
  if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1303
0
    DEBUG(2, ("Error encoding structure: %s\n",
1304
0
        ndr_map_error2string(ndr_err)));
1305
0
    tevent_req_error(req, EIO);
1306
0
    return;
1307
0
  }
1308
1309
0
  DEBUG(10, ("named_pipe_auth reply[%u]\n", (unsigned)out.length));
1310
0
  dump_data(11, out.data, out.length);
1311
1312
0
  if (DEBUGLVL(10)) {
1313
0
    NDR_PRINT_DEBUG(named_pipe_auth_rep, &pipe_reply);
1314
0
  }
1315
1316
0
  state->accept_status = pipe_reply.status;
1317
1318
0
  state->out_iov.iov_base = (char *) out.data;
1319
0
  state->out_iov.iov_len = out.length;
1320
1321
0
  subreq = tstream_writev_send(state, state->ev,
1322
0
             state->plain,
1323
0
             &state->out_iov, 1);
1324
0
  if (tevent_req_nomem(subreq, req)) {
1325
0
    DEBUG(0, ("no memory for tstream_writev_send\n"));
1326
0
    return;
1327
0
  }
1328
1329
0
  tevent_req_set_callback(subreq, tstream_npa_accept_existing_done, req);
1330
0
}
1331
1332
static void tstream_npa_accept_existing_done(struct tevent_req *subreq)
1333
0
{
1334
0
  struct tevent_req *req =
1335
0
      tevent_req_callback_data(subreq, struct tevent_req);
1336
0
  int sys_errno;
1337
0
  int ret;
1338
1339
0
  ret = tstream_writev_recv(subreq, &sys_errno);
1340
0
  TALLOC_FREE(subreq);
1341
0
  if (ret == -1) {
1342
0
    tevent_req_error(req, sys_errno);
1343
0
    return;
1344
0
  }
1345
1346
0
  tevent_req_done(req);
1347
0
}
1348
1349
static struct named_pipe_auth_req_info8 *
1350
copy_npa_info8(TALLOC_CTX *mem_ctx,
1351
         const struct named_pipe_auth_req_info8 *src)
1352
0
{
1353
0
  struct named_pipe_auth_req_info8 *dst = NULL;
1354
0
  DATA_BLOB blob;
1355
0
  enum ndr_err_code ndr_err;
1356
1357
0
  dst = talloc_zero(mem_ctx, struct named_pipe_auth_req_info8);
1358
0
  if (dst == NULL) {
1359
0
    return NULL;
1360
0
  }
1361
1362
0
  ndr_err = ndr_push_struct_blob(
1363
0
    &blob,
1364
0
    dst,
1365
0
    src,
1366
0
    (ndr_push_flags_fn_t)ndr_push_named_pipe_auth_req_info8);
1367
0
  if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1368
0
    DBG_WARNING("ndr_push_named_pipe_auth_req_info8 failed: %s\n",
1369
0
          ndr_errstr(ndr_err));
1370
0
    TALLOC_FREE(dst);
1371
0
    return NULL;
1372
0
  }
1373
1374
0
  ndr_err = ndr_pull_struct_blob_all(
1375
0
    &blob,
1376
0
    dst,
1377
0
    dst,
1378
0
    (ndr_pull_flags_fn_t)ndr_pull_named_pipe_auth_req_info8);
1379
0
  TALLOC_FREE(blob.data);
1380
0
  if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1381
0
    DBG_WARNING("ndr_push_named_pipe_auth_req_info8 failed: %s\n",
1382
0
          ndr_errstr(ndr_err));
1383
0
    TALLOC_FREE(dst);
1384
0
    return NULL;
1385
0
  }
1386
1387
0
  return dst;
1388
0
}
1389
1390
int _tstream_npa_accept_existing_recv(
1391
  struct tevent_req *req,
1392
  int *perrno,
1393
  TALLOC_CTX *mem_ctx,
1394
  struct tstream_context **stream,
1395
  struct named_pipe_auth_req_info8 **info8,
1396
  enum dcerpc_transport_t *transport,
1397
  struct tsocket_address **remote_client_addr,
1398
  char **_remote_client_name,
1399
  struct tsocket_address **local_server_addr,
1400
  char **local_server_name,
1401
  struct auth_session_info_transport **session_info,
1402
  const char *location)
1403
0
{
1404
0
  struct tstream_npa_accept_state *state =
1405
0
      tevent_req_data(req, struct tstream_npa_accept_state);
1406
0
  struct named_pipe_auth_req_info8 *i8 =
1407
0
    &state->pipe_request->info.info8;
1408
0
  struct tstream_npa *npas;
1409
0
  int ret;
1410
1411
0
  ret = tsocket_simple_int_recv(req, perrno);
1412
0
  if (ret != 0) {
1413
0
    DEBUG(2, ("Failed to accept named pipe connection: %s\n",
1414
0
        strerror(*perrno)));
1415
0
    tevent_req_received(req);
1416
0
    return -1;
1417
0
  }
1418
1419
0
  if (!NT_STATUS_IS_OK(state->accept_status)) {
1420
0
#if defined(EPROTONOSUPPORT)
1421
0
    *perrno = EPROTONOSUPPORT;
1422
#elif defined(EPROTO)
1423
    *perrno = EPROTO;
1424
#else
1425
    *perrno = EINVAL;
1426
#endif
1427
0
    DEBUG(2, ("Failed to accept named pipe connection: %s => %s\n",
1428
0
        nt_errstr(state->accept_status),
1429
0
        strerror(*perrno)));
1430
0
    tevent_req_received(req);
1431
0
    return -1;
1432
0
  }
1433
1434
0
  *stream = tstream_context_create(mem_ctx,
1435
0
           &tstream_npa_ops,
1436
0
           &npas,
1437
0
           struct tstream_npa,
1438
0
           location);
1439
0
  if (!*stream) {
1440
0
    *perrno = ENOMEM;
1441
0
    tevent_req_received(req);
1442
0
    return -1;
1443
0
  }
1444
0
  ZERO_STRUCTP(npas);
1445
0
  npas->unix_stream = state->plain;
1446
0
  npas->file_type = state->file_type;
1447
1448
0
  if (info8 != NULL) {
1449
    /*
1450
     * Make a full copy of "info8" because further down we
1451
     * talloc_move() away substructures from
1452
     * state->pipe_request.
1453
     */
1454
0
    struct named_pipe_auth_req_info8 *dst =
1455
0
      copy_npa_info8(mem_ctx, i8);
1456
0
    if (dst == NULL) {
1457
0
      *perrno = ENOMEM;
1458
0
      tevent_req_received(req);
1459
0
      return -1;
1460
0
    }
1461
0
    *info8 = dst;
1462
0
  }
1463
1464
0
  if (transport != NULL) {
1465
0
    *transport = i8->transport;
1466
0
  }
1467
0
  if (remote_client_addr != NULL) {
1468
0
    *remote_client_addr = talloc_move(
1469
0
      mem_ctx, &state->remote_client_addr);
1470
0
  }
1471
0
  if (_remote_client_name != NULL) {
1472
0
    *_remote_client_name = discard_const_p(
1473
0
      char,
1474
0
      talloc_move(mem_ctx, &i8->remote_client_name));
1475
0
  }
1476
0
  if (local_server_addr != NULL) {
1477
0
    *local_server_addr = talloc_move(
1478
0
      mem_ctx, &state->local_server_addr);
1479
0
  }
1480
0
  if (local_server_name != NULL) {
1481
0
    *local_server_name = discard_const_p(
1482
0
      char,
1483
0
      talloc_move(mem_ctx, &i8->local_server_name));
1484
0
  }
1485
0
  if (session_info != NULL) {
1486
0
    *session_info = talloc_move(mem_ctx, &i8->session_info);
1487
0
  }
1488
1489
0
  tevent_req_received(req);
1490
0
  return 0;
1491
0
}