dcdf1f5a24445a4282cdbd904bec2b5ac4968fb5
[samba.git] / source3 / rpc_client / cli_pipe.c
1 /*
2  *  Unix SMB/CIFS implementation.
3  *  RPC Pipe client routines
4  *  Largely rewritten by Jeremy Allison             2005.
5  *  Heavily modified by Simo Sorce                  2010.
6  *
7  *  This program is free software; you can redistribute it and/or modify
8  *  it under the terms of the GNU General Public License as published by
9  *  the Free Software Foundation; either version 3 of the License, or
10  *  (at your option) any later version.
11  *
12  *  This program is distributed in the hope that it will be useful,
13  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  *  GNU General Public License for more details.
16  *
17  *  You should have received a copy of the GNU General Public License
18  *  along with this program; if not, see <http://www.gnu.org/licenses/>.
19  */
20
21 #include "includes.h"
22 #include "../lib/util/tevent_ntstatus.h"
23 #include "librpc/gen_ndr/ndr_epmapper_c.h"
24 #include "../librpc/gen_ndr/ndr_schannel.h"
25 #include "../librpc/gen_ndr/ndr_dssetup.h"
26 #include "../libcli/auth/schannel.h"
27 #include "../libcli/auth/spnego.h"
28 #include "../libcli/auth/ntlmssp.h"
29 #include "ntlmssp_wrap.h"
30 #include "librpc/gen_ndr/ndr_dcerpc.h"
31 #include "librpc/rpc/dcerpc.h"
32 #include "librpc/crypto/gse.h"
33 #include "librpc/crypto/spnego.h"
34 #include "rpc_dce.h"
35 #include "cli_pipe.h"
36 #include "client.h"
37
38 #undef DBGC_CLASS
39 #define DBGC_CLASS DBGC_RPC_CLI
40
41 /********************************************************************
42  Pipe description for a DEBUG
43  ********************************************************************/
44 static const char *rpccli_pipe_txt(TALLOC_CTX *mem_ctx,
45                                    struct rpc_pipe_client *cli)
46 {
47         char *result = talloc_asprintf(mem_ctx, "host %s", cli->desthost);
48         if (result == NULL) {
49                 return "pipe";
50         }
51         return result;
52 }
53
54 /********************************************************************
55  Rpc pipe call id.
56  ********************************************************************/
57
58 static uint32 get_rpc_call_id(void)
59 {
60         static uint32 call_id = 0;
61         return ++call_id;
62 }
63
64 /*******************************************************************
65  Use SMBreadX to get rest of one fragment's worth of rpc data.
66  Reads the whole size or give an error message
67  ********************************************************************/
68
69 struct rpc_read_state {
70         struct event_context *ev;
71         struct rpc_cli_transport *transport;
72         uint8_t *data;
73         size_t size;
74         size_t num_read;
75 };
76
77 static void rpc_read_done(struct tevent_req *subreq);
78
79 static struct tevent_req *rpc_read_send(TALLOC_CTX *mem_ctx,
80                                         struct event_context *ev,
81                                         struct rpc_cli_transport *transport,
82                                         uint8_t *data, size_t size)
83 {
84         struct tevent_req *req, *subreq;
85         struct rpc_read_state *state;
86
87         req = tevent_req_create(mem_ctx, &state, struct rpc_read_state);
88         if (req == NULL) {
89                 return NULL;
90         }
91         state->ev = ev;
92         state->transport = transport;
93         state->data = data;
94         state->size = size;
95         state->num_read = 0;
96
97         DEBUG(5, ("rpc_read_send: data_to_read: %u\n", (unsigned int)size));
98
99         subreq = transport->read_send(state, ev, (uint8_t *)data, size,
100                                       transport->priv);
101         if (subreq == NULL) {
102                 goto fail;
103         }
104         tevent_req_set_callback(subreq, rpc_read_done, req);
105         return req;
106
107  fail:
108         TALLOC_FREE(req);
109         return NULL;
110 }
111
112 static void rpc_read_done(struct tevent_req *subreq)
113 {
114         struct tevent_req *req = tevent_req_callback_data(
115                 subreq, struct tevent_req);
116         struct rpc_read_state *state = tevent_req_data(
117                 req, struct rpc_read_state);
118         NTSTATUS status;
119         ssize_t received;
120
121         status = state->transport->read_recv(subreq, &received);
122         TALLOC_FREE(subreq);
123         if (!NT_STATUS_IS_OK(status)) {
124                 tevent_req_nterror(req, status);
125                 return;
126         }
127
128         state->num_read += received;
129         if (state->num_read == state->size) {
130                 tevent_req_done(req);
131                 return;
132         }
133
134         subreq = state->transport->read_send(state, state->ev,
135                                              state->data + state->num_read,
136                                              state->size - state->num_read,
137                                              state->transport->priv);
138         if (tevent_req_nomem(subreq, req)) {
139                 return;
140         }
141         tevent_req_set_callback(subreq, rpc_read_done, req);
142 }
143
144 static NTSTATUS rpc_read_recv(struct tevent_req *req)
145 {
146         return tevent_req_simple_recv_ntstatus(req);
147 }
148
149 struct rpc_write_state {
150         struct event_context *ev;
151         struct rpc_cli_transport *transport;
152         const uint8_t *data;
153         size_t size;
154         size_t num_written;
155 };
156
157 static void rpc_write_done(struct tevent_req *subreq);
158
159 static struct tevent_req *rpc_write_send(TALLOC_CTX *mem_ctx,
160                                          struct event_context *ev,
161                                          struct rpc_cli_transport *transport,
162                                          const uint8_t *data, size_t size)
163 {
164         struct tevent_req *req, *subreq;
165         struct rpc_write_state *state;
166
167         req = tevent_req_create(mem_ctx, &state, struct rpc_write_state);
168         if (req == NULL) {
169                 return NULL;
170         }
171         state->ev = ev;
172         state->transport = transport;
173         state->data = data;
174         state->size = size;
175         state->num_written = 0;
176
177         DEBUG(5, ("rpc_write_send: data_to_write: %u\n", (unsigned int)size));
178
179         subreq = transport->write_send(state, ev, data, size, transport->priv);
180         if (subreq == NULL) {
181                 goto fail;
182         }
183         tevent_req_set_callback(subreq, rpc_write_done, req);
184         return req;
185  fail:
186         TALLOC_FREE(req);
187         return NULL;
188 }
189
190 static void rpc_write_done(struct tevent_req *subreq)
191 {
192         struct tevent_req *req = tevent_req_callback_data(
193                 subreq, struct tevent_req);
194         struct rpc_write_state *state = tevent_req_data(
195                 req, struct rpc_write_state);
196         NTSTATUS status;
197         ssize_t written;
198
199         status = state->transport->write_recv(subreq, &written);
200         TALLOC_FREE(subreq);
201         if (!NT_STATUS_IS_OK(status)) {
202                 tevent_req_nterror(req, status);
203                 return;
204         }
205
206         state->num_written += written;
207
208         if (state->num_written == state->size) {
209                 tevent_req_done(req);
210                 return;
211         }
212
213         subreq = state->transport->write_send(state, state->ev,
214                                               state->data + state->num_written,
215                                               state->size - state->num_written,
216                                               state->transport->priv);
217         if (tevent_req_nomem(subreq, req)) {
218                 return;
219         }
220         tevent_req_set_callback(subreq, rpc_write_done, req);
221 }
222
223 static NTSTATUS rpc_write_recv(struct tevent_req *req)
224 {
225         return tevent_req_simple_recv_ntstatus(req);
226 }
227
228
229 /****************************************************************************
230  Try and get a PDU's worth of data from current_pdu. If not, then read more
231  from the wire.
232  ****************************************************************************/
233
234 struct get_complete_frag_state {
235         struct event_context *ev;
236         struct rpc_pipe_client *cli;
237         uint16_t frag_len;
238         DATA_BLOB *pdu;
239 };
240
241 static void get_complete_frag_got_header(struct tevent_req *subreq);
242 static void get_complete_frag_got_rest(struct tevent_req *subreq);
243
244 static struct tevent_req *get_complete_frag_send(TALLOC_CTX *mem_ctx,
245                                                  struct event_context *ev,
246                                                  struct rpc_pipe_client *cli,
247                                                  DATA_BLOB *pdu)
248 {
249         struct tevent_req *req, *subreq;
250         struct get_complete_frag_state *state;
251         size_t received;
252         NTSTATUS status;
253
254         req = tevent_req_create(mem_ctx, &state,
255                                 struct get_complete_frag_state);
256         if (req == NULL) {
257                 return NULL;
258         }
259         state->ev = ev;
260         state->cli = cli;
261         state->frag_len = RPC_HEADER_LEN;
262         state->pdu = pdu;
263
264         received = pdu->length;
265         if (received < RPC_HEADER_LEN) {
266                 if (!data_blob_realloc(mem_ctx, pdu, RPC_HEADER_LEN)) {
267                         status = NT_STATUS_NO_MEMORY;
268                         goto post_status;
269                 }
270                 subreq = rpc_read_send(state, state->ev,
271                                         state->cli->transport,
272                                         pdu->data + received,
273                                         RPC_HEADER_LEN - received);
274                 if (subreq == NULL) {
275                         status = NT_STATUS_NO_MEMORY;
276                         goto post_status;
277                 }
278                 tevent_req_set_callback(subreq, get_complete_frag_got_header,
279                                         req);
280                 return req;
281         }
282
283         state->frag_len = dcerpc_get_frag_length(pdu);
284
285         /*
286          * Ensure we have frag_len bytes of data.
287          */
288         if (received < state->frag_len) {
289                 if (!data_blob_realloc(NULL, pdu, state->frag_len)) {
290                         status = NT_STATUS_NO_MEMORY;
291                         goto post_status;
292                 }
293                 subreq = rpc_read_send(state, state->ev,
294                                         state->cli->transport,
295                                         pdu->data + received,
296                                         state->frag_len - received);
297                 if (subreq == NULL) {
298                         status = NT_STATUS_NO_MEMORY;
299                         goto post_status;
300                 }
301                 tevent_req_set_callback(subreq, get_complete_frag_got_rest,
302                                         req);
303                 return req;
304         }
305
306         status = NT_STATUS_OK;
307  post_status:
308         if (NT_STATUS_IS_OK(status)) {
309                 tevent_req_done(req);
310         } else {
311                 tevent_req_nterror(req, status);
312         }
313         return tevent_req_post(req, ev);
314 }
315
316 static void get_complete_frag_got_header(struct tevent_req *subreq)
317 {
318         struct tevent_req *req = tevent_req_callback_data(
319                 subreq, struct tevent_req);
320         struct get_complete_frag_state *state = tevent_req_data(
321                 req, struct get_complete_frag_state);
322         NTSTATUS status;
323
324         status = rpc_read_recv(subreq);
325         TALLOC_FREE(subreq);
326         if (!NT_STATUS_IS_OK(status)) {
327                 tevent_req_nterror(req, status);
328                 return;
329         }
330
331         state->frag_len = dcerpc_get_frag_length(state->pdu);
332
333         if (!data_blob_realloc(NULL, state->pdu, state->frag_len)) {
334                 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
335                 return;
336         }
337
338         /*
339          * We're here in this piece of code because we've read exactly
340          * RPC_HEADER_LEN bytes into state->pdu.
341          */
342
343         subreq = rpc_read_send(state, state->ev, state->cli->transport,
344                                 state->pdu->data + RPC_HEADER_LEN,
345                                 state->frag_len - RPC_HEADER_LEN);
346         if (tevent_req_nomem(subreq, req)) {
347                 return;
348         }
349         tevent_req_set_callback(subreq, get_complete_frag_got_rest, req);
350 }
351
352 static void get_complete_frag_got_rest(struct tevent_req *subreq)
353 {
354         struct tevent_req *req = tevent_req_callback_data(
355                 subreq, struct tevent_req);
356         NTSTATUS status;
357
358         status = rpc_read_recv(subreq);
359         TALLOC_FREE(subreq);
360         if (!NT_STATUS_IS_OK(status)) {
361                 tevent_req_nterror(req, status);
362                 return;
363         }
364         tevent_req_done(req);
365 }
366
367 static NTSTATUS get_complete_frag_recv(struct tevent_req *req)
368 {
369         return tevent_req_simple_recv_ntstatus(req);
370 }
371
372 /****************************************************************************
373  Do basic authentication checks on an incoming pdu.
374  ****************************************************************************/
375
376 static NTSTATUS cli_pipe_validate_current_pdu(TALLOC_CTX *mem_ctx,
377                                                 struct rpc_pipe_client *cli,
378                                                 struct ncacn_packet *pkt,
379                                                 DATA_BLOB *pdu,
380                                                 uint8_t expected_pkt_type,
381                                                 DATA_BLOB *rdata,
382                                                 DATA_BLOB *reply_pdu)
383 {
384         struct dcerpc_response *r;
385         NTSTATUS ret = NT_STATUS_OK;
386         size_t pad_len = 0;
387
388         /*
389          * Point the return values at the real data including the RPC
390          * header. Just in case the caller wants it.
391          */
392         *rdata = *pdu;
393
394         /* Ensure we have the correct type. */
395         switch (pkt->ptype) {
396         case DCERPC_PKT_ALTER_RESP:
397         case DCERPC_PKT_BIND_ACK:
398
399                 /* Client code never receives this kind of packets */
400                 break;
401
402
403         case DCERPC_PKT_RESPONSE:
404
405                 r = &pkt->u.response;
406
407                 /* Here's where we deal with incoming sign/seal. */
408                 ret = dcerpc_check_auth(cli->auth, pkt,
409                                         &r->stub_and_verifier,
410                                         DCERPC_RESPONSE_LENGTH,
411                                         pdu, &pad_len);
412                 if (!NT_STATUS_IS_OK(ret)) {
413                         return ret;
414                 }
415
416                 if (pkt->frag_length < DCERPC_RESPONSE_LENGTH + pad_len) {
417                         return NT_STATUS_BUFFER_TOO_SMALL;
418                 }
419
420                 /* Point the return values at the NDR data. */
421                 rdata->data = r->stub_and_verifier.data;
422
423                 if (pkt->auth_length) {
424                         /* We've already done integer wrap tests in
425                          * dcerpc_check_auth(). */
426                         rdata->length = r->stub_and_verifier.length
427                                          - pad_len
428                                          - DCERPC_AUTH_TRAILER_LENGTH
429                                          - pkt->auth_length;
430                 } else {
431                         rdata->length = r->stub_and_verifier.length;
432                 }
433
434                 DEBUG(10, ("Got pdu len %lu, data_len %lu, ss_len %u\n",
435                            (long unsigned int)pdu->length,
436                            (long unsigned int)rdata->length,
437                            (unsigned int)pad_len));
438
439                 /*
440                  * If this is the first reply, and the allocation hint is
441                  * reasonable, try and set up the reply_pdu DATA_BLOB to the
442                  * correct size.
443                  */
444
445                 if ((reply_pdu->length == 0) &&
446                     r->alloc_hint && (r->alloc_hint < 15*1024*1024)) {
447                         if (!data_blob_realloc(mem_ctx, reply_pdu,
448                                                         r->alloc_hint)) {
449                                 DEBUG(0, ("reply alloc hint %d too "
450                                           "large to allocate\n",
451                                           (int)r->alloc_hint));
452                                 return NT_STATUS_NO_MEMORY;
453                         }
454                 }
455
456                 break;
457
458         case DCERPC_PKT_BIND_NAK:
459                 DEBUG(1, (__location__ ": Bind NACK received from %s!\n",
460                           rpccli_pipe_txt(talloc_tos(), cli)));
461                 /* Use this for now... */
462                 return NT_STATUS_NETWORK_ACCESS_DENIED;
463
464         case DCERPC_PKT_FAULT:
465
466                 DEBUG(1, (__location__ ": RPC fault code %s received "
467                           "from %s!\n",
468                           dcerpc_errstr(talloc_tos(),
469                           pkt->u.fault.status),
470                           rpccli_pipe_txt(talloc_tos(), cli)));
471
472                 return dcerpc_fault_to_nt_status(pkt->u.fault.status);
473
474         default:
475                 DEBUG(0, (__location__ "Unknown packet type %u received "
476                           "from %s!\n",
477                           (unsigned int)pkt->ptype,
478                           rpccli_pipe_txt(talloc_tos(), cli)));
479                 return NT_STATUS_INVALID_INFO_CLASS;
480         }
481
482         if (pkt->ptype != expected_pkt_type) {
483                 DEBUG(3, (__location__ ": Connection to %s got an unexpected "
484                           "RPC packet type - %u, not %u\n",
485                           rpccli_pipe_txt(talloc_tos(), cli),
486                           pkt->ptype, expected_pkt_type));
487                 return NT_STATUS_INVALID_INFO_CLASS;
488         }
489
490         /* Do this just before return - we don't want to modify any rpc header
491            data before now as we may have needed to do cryptographic actions on
492            it before. */
493
494         if ((pkt->ptype == DCERPC_PKT_BIND_ACK) &&
495             !(pkt->pfc_flags & DCERPC_PFC_FLAG_LAST)) {
496                 DEBUG(5, (__location__ ": bug in server (AS/U?), setting "
497                           "fragment first/last ON.\n"));
498                 pkt->pfc_flags |= DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST;
499         }
500
501         return NT_STATUS_OK;
502 }
503
504 /****************************************************************************
505  Call a remote api on an arbitrary pipe.  takes param, data and setup buffers.
506 ****************************************************************************/
507
508 struct cli_api_pipe_state {
509         struct event_context *ev;
510         struct rpc_cli_transport *transport;
511         uint8_t *rdata;
512         uint32_t rdata_len;
513 };
514
515 static void cli_api_pipe_trans_done(struct tevent_req *subreq);
516 static void cli_api_pipe_write_done(struct tevent_req *subreq);
517 static void cli_api_pipe_read_done(struct tevent_req *subreq);
518
519 static struct tevent_req *cli_api_pipe_send(TALLOC_CTX *mem_ctx,
520                                             struct event_context *ev,
521                                             struct rpc_cli_transport *transport,
522                                             uint8_t *data, size_t data_len,
523                                             uint32_t max_rdata_len)
524 {
525         struct tevent_req *req, *subreq;
526         struct cli_api_pipe_state *state;
527         NTSTATUS status;
528
529         req = tevent_req_create(mem_ctx, &state, struct cli_api_pipe_state);
530         if (req == NULL) {
531                 return NULL;
532         }
533         state->ev = ev;
534         state->transport = transport;
535
536         if (max_rdata_len < RPC_HEADER_LEN) {
537                 /*
538                  * For a RPC reply we always need at least RPC_HEADER_LEN
539                  * bytes. We check this here because we will receive
540                  * RPC_HEADER_LEN bytes in cli_trans_sock_send_done.
541                  */
542                 status = NT_STATUS_INVALID_PARAMETER;
543                 goto post_status;
544         }
545
546         if (transport->trans_send != NULL) {
547                 subreq = transport->trans_send(state, ev, data, data_len,
548                                                max_rdata_len, transport->priv);
549                 if (subreq == NULL) {
550                         goto fail;
551                 }
552                 tevent_req_set_callback(subreq, cli_api_pipe_trans_done, req);
553                 return req;
554         }
555
556         /*
557          * If the transport does not provide a "trans" routine, i.e. for
558          * example the ncacn_ip_tcp transport, do the write/read step here.
559          */
560
561         subreq = rpc_write_send(state, ev, transport, data, data_len);
562         if (subreq == NULL) {
563                 goto fail;
564         }
565         tevent_req_set_callback(subreq, cli_api_pipe_write_done, req);
566         return req;
567
568  post_status:
569         tevent_req_nterror(req, status);
570         return tevent_req_post(req, ev);
571  fail:
572         TALLOC_FREE(req);
573         return NULL;
574 }
575
576 static void cli_api_pipe_trans_done(struct tevent_req *subreq)
577 {
578         struct tevent_req *req = tevent_req_callback_data(
579                 subreq, struct tevent_req);
580         struct cli_api_pipe_state *state = tevent_req_data(
581                 req, struct cli_api_pipe_state);
582         NTSTATUS status;
583
584         status = state->transport->trans_recv(subreq, state, &state->rdata,
585                                               &state->rdata_len);
586         TALLOC_FREE(subreq);
587         if (!NT_STATUS_IS_OK(status)) {
588                 tevent_req_nterror(req, status);
589                 return;
590         }
591         tevent_req_done(req);
592 }
593
594 static void cli_api_pipe_write_done(struct tevent_req *subreq)
595 {
596         struct tevent_req *req = tevent_req_callback_data(
597                 subreq, struct tevent_req);
598         struct cli_api_pipe_state *state = tevent_req_data(
599                 req, struct cli_api_pipe_state);
600         NTSTATUS status;
601
602         status = rpc_write_recv(subreq);
603         TALLOC_FREE(subreq);
604         if (!NT_STATUS_IS_OK(status)) {
605                 tevent_req_nterror(req, status);
606                 return;
607         }
608
609         state->rdata = TALLOC_ARRAY(state, uint8_t, RPC_HEADER_LEN);
610         if (tevent_req_nomem(state->rdata, req)) {
611                 return;
612         }
613
614         /*
615          * We don't need to use rpc_read_send here, the upper layer will cope
616          * with a short read, transport->trans_send could also return less
617          * than state->max_rdata_len.
618          */
619         subreq = state->transport->read_send(state, state->ev, state->rdata,
620                                              RPC_HEADER_LEN,
621                                              state->transport->priv);
622         if (tevent_req_nomem(subreq, req)) {
623                 return;
624         }
625         tevent_req_set_callback(subreq, cli_api_pipe_read_done, req);
626 }
627
628 static void cli_api_pipe_read_done(struct tevent_req *subreq)
629 {
630         struct tevent_req *req = tevent_req_callback_data(
631                 subreq, struct tevent_req);
632         struct cli_api_pipe_state *state = tevent_req_data(
633                 req, struct cli_api_pipe_state);
634         NTSTATUS status;
635         ssize_t received;
636
637         status = state->transport->read_recv(subreq, &received);
638         TALLOC_FREE(subreq);
639         if (!NT_STATUS_IS_OK(status)) {
640                 tevent_req_nterror(req, status);
641                 return;
642         }
643         state->rdata_len = received;
644         tevent_req_done(req);
645 }
646
647 static NTSTATUS cli_api_pipe_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
648                                   uint8_t **prdata, uint32_t *prdata_len)
649 {
650         struct cli_api_pipe_state *state = tevent_req_data(
651                 req, struct cli_api_pipe_state);
652         NTSTATUS status;
653
654         if (tevent_req_is_nterror(req, &status)) {
655                 return status;
656         }
657
658         *prdata = talloc_move(mem_ctx, &state->rdata);
659         *prdata_len = state->rdata_len;
660         return NT_STATUS_OK;
661 }
662
663 /****************************************************************************
664  Send data on an rpc pipe via trans. The data must be the last
665  pdu fragment of an NDR data stream.
666
667  Receive response data from an rpc pipe, which may be large...
668
669  Read the first fragment: unfortunately have to use SMBtrans for the first
670  bit, then SMBreadX for subsequent bits.
671
672  If first fragment received also wasn't the last fragment, continue
673  getting fragments until we _do_ receive the last fragment.
674
675  Request/Response PDU's look like the following...
676
677  |<------------------PDU len----------------------------------------------->|
678  |<-HDR_LEN-->|<--REQ LEN------>|.............|<-AUTH_HDRLEN->|<-AUTH_LEN-->|
679
680  +------------+-----------------+-------------+---------------+-------------+
681  | RPC HEADER | REQ/RESP HEADER | DATA ...... | AUTH_HDR      | AUTH DATA   |
682  +------------+-----------------+-------------+---------------+-------------+
683
684  Where the presence of the AUTH_HDR and AUTH DATA are dependent on the
685  signing & sealing being negotiated.
686
687  ****************************************************************************/
688
689 struct rpc_api_pipe_state {
690         struct event_context *ev;
691         struct rpc_pipe_client *cli;
692         uint8_t expected_pkt_type;
693
694         DATA_BLOB incoming_frag;
695         struct ncacn_packet *pkt;
696
697         /* Incoming reply */
698         DATA_BLOB reply_pdu;
699         size_t reply_pdu_offset;
700         uint8_t endianess;
701 };
702
703 static void rpc_api_pipe_trans_done(struct tevent_req *subreq);
704 static void rpc_api_pipe_got_pdu(struct tevent_req *subreq);
705 static void rpc_api_pipe_auth3_done(struct tevent_req *subreq);
706
707 static struct tevent_req *rpc_api_pipe_send(TALLOC_CTX *mem_ctx,
708                                             struct event_context *ev,
709                                             struct rpc_pipe_client *cli,
710                                             DATA_BLOB *data, /* Outgoing PDU */
711                                             uint8_t expected_pkt_type)
712 {
713         struct tevent_req *req, *subreq;
714         struct rpc_api_pipe_state *state;
715         uint16_t max_recv_frag;
716         NTSTATUS status;
717
718         req = tevent_req_create(mem_ctx, &state, struct rpc_api_pipe_state);
719         if (req == NULL) {
720                 return NULL;
721         }
722         state->ev = ev;
723         state->cli = cli;
724         state->expected_pkt_type = expected_pkt_type;
725         state->incoming_frag = data_blob_null;
726         state->reply_pdu = data_blob_null;
727         state->reply_pdu_offset = 0;
728         state->endianess = DCERPC_DREP_LE;
729
730         /*
731          * Ensure we're not sending too much.
732          */
733         if (data->length > cli->max_xmit_frag) {
734                 status = NT_STATUS_INVALID_PARAMETER;
735                 goto post_status;
736         }
737
738         DEBUG(5,("rpc_api_pipe: %s\n", rpccli_pipe_txt(talloc_tos(), cli)));
739
740         if (state->expected_pkt_type == DCERPC_PKT_AUTH3) {
741                 subreq = rpc_write_send(state, ev, cli->transport,
742                                         data->data, data->length);
743                 if (subreq == NULL) {
744                         goto fail;
745                 }
746                 tevent_req_set_callback(subreq, rpc_api_pipe_auth3_done, req);
747                 return req;
748         }
749
750         /* get the header first, then fetch the rest once we have
751          * the frag_length available */
752         max_recv_frag = RPC_HEADER_LEN;
753
754         subreq = cli_api_pipe_send(state, ev, cli->transport,
755                                    data->data, data->length, max_recv_frag);
756         if (subreq == NULL) {
757                 goto fail;
758         }
759         tevent_req_set_callback(subreq, rpc_api_pipe_trans_done, req);
760         return req;
761
762  post_status:
763         tevent_req_nterror(req, status);
764         return tevent_req_post(req, ev);
765  fail:
766         TALLOC_FREE(req);
767         return NULL;
768 }
769
770 static void rpc_api_pipe_auth3_done(struct tevent_req *subreq)
771 {
772         struct tevent_req *req =
773                 tevent_req_callback_data(subreq,
774                 struct tevent_req);
775         NTSTATUS status;
776
777         status = rpc_write_recv(subreq);
778         TALLOC_FREE(subreq);
779         if (!NT_STATUS_IS_OK(status)) {
780                 tevent_req_nterror(req, status);
781                 return;
782         }
783
784         tevent_req_done(req);
785 }
786
787 static void rpc_api_pipe_trans_done(struct tevent_req *subreq)
788 {
789         struct tevent_req *req = tevent_req_callback_data(
790                 subreq, struct tevent_req);
791         struct rpc_api_pipe_state *state = tevent_req_data(
792                 req, struct rpc_api_pipe_state);
793         NTSTATUS status;
794         uint8_t *rdata = NULL;
795         uint32_t rdata_len = 0;
796
797         status = cli_api_pipe_recv(subreq, state, &rdata, &rdata_len);
798         TALLOC_FREE(subreq);
799         if (!NT_STATUS_IS_OK(status)) {
800                 DEBUG(5, ("cli_api_pipe failed: %s\n", nt_errstr(status)));
801                 tevent_req_nterror(req, status);
802                 return;
803         }
804
805         if (rdata == NULL) {
806                 DEBUG(3,("rpc_api_pipe: %s failed to return data.\n",
807                          rpccli_pipe_txt(talloc_tos(), state->cli)));
808                 tevent_req_done(req);
809                 return;
810         }
811
812         /*
813          * Move data on state->incoming_frag.
814          */
815         state->incoming_frag.data = talloc_move(state, &rdata);
816         state->incoming_frag.length = rdata_len;
817         if (!state->incoming_frag.data) {
818                 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
819                 return;
820         }
821
822         /* Ensure we have enough data for a pdu. */
823         subreq = get_complete_frag_send(state, state->ev, state->cli,
824                                         &state->incoming_frag);
825         if (tevent_req_nomem(subreq, req)) {
826                 return;
827         }
828         tevent_req_set_callback(subreq, rpc_api_pipe_got_pdu, req);
829 }
830
831 static void rpc_api_pipe_got_pdu(struct tevent_req *subreq)
832 {
833         struct tevent_req *req = tevent_req_callback_data(
834                 subreq, struct tevent_req);
835         struct rpc_api_pipe_state *state = tevent_req_data(
836                 req, struct rpc_api_pipe_state);
837         NTSTATUS status;
838         DATA_BLOB rdata = data_blob_null;
839
840         status = get_complete_frag_recv(subreq);
841         TALLOC_FREE(subreq);
842         if (!NT_STATUS_IS_OK(status)) {
843                 DEBUG(5, ("get_complete_frag failed: %s\n",
844                           nt_errstr(status)));
845                 tevent_req_nterror(req, status);
846                 return;
847         }
848
849         state->pkt = talloc(state, struct ncacn_packet);
850         if (!state->pkt) {
851                 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
852                 return;
853         }
854
855         status = dcerpc_pull_ncacn_packet(state->pkt,
856                                           &state->incoming_frag,
857                                           state->pkt,
858                                           !state->endianess);
859         if (!NT_STATUS_IS_OK(status)) {
860                 tevent_req_nterror(req, status);
861                 return;
862         }
863
864         if (state->incoming_frag.length != state->pkt->frag_length) {
865                 DEBUG(5, ("Incorrect pdu length %u, expected %u\n",
866                           (unsigned int)state->incoming_frag.length,
867                           (unsigned int)state->pkt->frag_length));
868                 tevent_req_nterror(req,  NT_STATUS_INVALID_PARAMETER);
869                 return;
870         }
871
872         status = cli_pipe_validate_current_pdu(state,
873                                                 state->cli, state->pkt,
874                                                 &state->incoming_frag,
875                                                 state->expected_pkt_type,
876                                                 &rdata,
877                                                 &state->reply_pdu);
878
879         DEBUG(10,("rpc_api_pipe: got frag len of %u at offset %u: %s\n",
880                   (unsigned)state->incoming_frag.length,
881                   (unsigned)state->reply_pdu_offset,
882                   nt_errstr(status)));
883
884         if (!NT_STATUS_IS_OK(status)) {
885                 tevent_req_nterror(req, status);
886                 return;
887         }
888
889         if ((state->pkt->pfc_flags & DCERPC_PFC_FLAG_FIRST)
890             && (state->pkt->drep[0] != DCERPC_DREP_LE)) {
891                 /*
892                  * Set the data type correctly for big-endian data on the
893                  * first packet.
894                  */
895                 DEBUG(10,("rpc_api_pipe: On %s PDU data format is "
896                           "big-endian.\n",
897                           rpccli_pipe_txt(talloc_tos(), state->cli)));
898                 state->endianess = 0x00; /* BIG ENDIAN */
899         }
900         /*
901          * Check endianness on subsequent packets.
902          */
903         if (state->endianess != state->pkt->drep[0]) {
904                 DEBUG(0,("rpc_api_pipe: Error : Endianness changed from %s to "
905                          "%s\n",
906                          state->endianess?"little":"big",
907                          state->pkt->drep[0]?"little":"big"));
908                 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
909                 return;
910         }
911
912         /* Now copy the data portion out of the pdu into rbuf. */
913         if (state->reply_pdu.length < state->reply_pdu_offset + rdata.length) {
914                 if (!data_blob_realloc(NULL, &state->reply_pdu,
915                                 state->reply_pdu_offset + rdata.length)) {
916                         tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
917                         return;
918                 }
919         }
920
921         memcpy(state->reply_pdu.data + state->reply_pdu_offset,
922                 rdata.data, rdata.length);
923         state->reply_pdu_offset += rdata.length;
924
925         /* reset state->incoming_frag, there is no need to free it,
926          * it will be reallocated to the right size the next time
927          * it is used */
928         state->incoming_frag.length = 0;
929
930         if (state->pkt->pfc_flags & DCERPC_PFC_FLAG_LAST) {
931                 /* make sure the pdu length is right now that we
932                  * have all the data available (alloc hint may
933                  * have allocated more than was actually used) */
934                 state->reply_pdu.length = state->reply_pdu_offset;
935                 DEBUG(10,("rpc_api_pipe: %s returned %u bytes.\n",
936                           rpccli_pipe_txt(talloc_tos(), state->cli),
937                           (unsigned)state->reply_pdu.length));
938                 tevent_req_done(req);
939                 return;
940         }
941
942         subreq = get_complete_frag_send(state, state->ev, state->cli,
943                                         &state->incoming_frag);
944         if (tevent_req_nomem(subreq, req)) {
945                 return;
946         }
947         tevent_req_set_callback(subreq, rpc_api_pipe_got_pdu, req);
948 }
949
950 static NTSTATUS rpc_api_pipe_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
951                                   struct ncacn_packet **pkt,
952                                   DATA_BLOB *reply_pdu)
953 {
954         struct rpc_api_pipe_state *state = tevent_req_data(
955                 req, struct rpc_api_pipe_state);
956         NTSTATUS status;
957
958         if (tevent_req_is_nterror(req, &status)) {
959                 return status;
960         }
961
962         /* return data to caller and assign it ownership of memory */
963         if (reply_pdu) {
964                 reply_pdu->data = talloc_move(mem_ctx, &state->reply_pdu.data);
965                 reply_pdu->length = state->reply_pdu.length;
966                 state->reply_pdu.length = 0;
967         } else {
968                 data_blob_free(&state->reply_pdu);
969         }
970
971         if (pkt) {
972                 *pkt = talloc_steal(mem_ctx, state->pkt);
973         }
974
975         return NT_STATUS_OK;
976 }
977
978 /*******************************************************************
979  Creates spnego auth bind.
980  ********************************************************************/
981
982 static NTSTATUS create_spnego_auth_bind_req(TALLOC_CTX *mem_ctx,
983                                             struct pipe_auth_data *auth,
984                                             DATA_BLOB *auth_token)
985 {
986         struct spnego_context *spnego_ctx;
987         DATA_BLOB in_token = data_blob_null;
988         NTSTATUS status;
989
990         spnego_ctx = talloc_get_type_abort(auth->auth_ctx,
991                                            struct spnego_context);
992
993         /* Negotiate the initial auth token */
994         status = spnego_get_client_auth_token(mem_ctx, spnego_ctx,
995                                               &in_token, auth_token);
996         if (!NT_STATUS_IS_OK(status)) {
997                 return status;
998         }
999
1000         DEBUG(5, ("Created GSS Authentication Token:\n"));
1001         dump_data(5, auth_token->data, auth_token->length);
1002
1003         return NT_STATUS_OK;
1004 }
1005
1006 /*******************************************************************
1007  Creates krb5 auth bind.
1008  ********************************************************************/
1009
1010 static NTSTATUS create_gssapi_auth_bind_req(TALLOC_CTX *mem_ctx,
1011                                             struct pipe_auth_data *auth,
1012                                             DATA_BLOB *auth_token)
1013 {
1014         struct gse_context *gse_ctx;
1015         DATA_BLOB in_token = data_blob_null;
1016         NTSTATUS status;
1017
1018         gse_ctx = talloc_get_type_abort(auth->auth_ctx,
1019                                         struct gse_context);
1020
1021         /* Negotiate the initial auth token */
1022         status = gse_get_client_auth_token(mem_ctx, gse_ctx,
1023                                            &in_token,
1024                                            auth_token);
1025         if (!NT_STATUS_IS_OK(status)) {
1026                 return status;
1027         }
1028
1029         DEBUG(5, ("Created GSS Authentication Token:\n"));
1030         dump_data(5, auth_token->data, auth_token->length);
1031
1032         return NT_STATUS_OK;
1033 }
1034
1035 /*******************************************************************
1036  Creates NTLMSSP auth bind.
1037  ********************************************************************/
1038
1039 static NTSTATUS create_ntlmssp_auth_rpc_bind_req(struct rpc_pipe_client *cli,
1040                                                  DATA_BLOB *auth_token)
1041 {
1042         struct auth_ntlmssp_state *ntlmssp_ctx;
1043         DATA_BLOB null_blob = data_blob_null;
1044         NTSTATUS status;
1045
1046         ntlmssp_ctx = talloc_get_type_abort(cli->auth->auth_ctx,
1047                                             struct auth_ntlmssp_state);
1048
1049         DEBUG(5, ("create_ntlmssp_auth_rpc_bind_req: Processing NTLMSSP Negotiate\n"));
1050         status = auth_ntlmssp_update(ntlmssp_ctx, null_blob, auth_token);
1051
1052         if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1053                 data_blob_free(auth_token);
1054                 return status;
1055         }
1056
1057         DEBUG(5, ("create_ntlmssp_auth_rpc_bind_req: NTLMSSP Negotiate:\n"));
1058         dump_data(5, auth_token->data, auth_token->length);
1059
1060         return NT_STATUS_OK;
1061 }
1062
1063 /*******************************************************************
1064  Creates schannel auth bind.
1065  ********************************************************************/
1066
1067 static NTSTATUS create_schannel_auth_rpc_bind_req(struct rpc_pipe_client *cli,
1068                                                   DATA_BLOB *auth_token)
1069 {
1070         NTSTATUS status;
1071         struct NL_AUTH_MESSAGE r;
1072
1073         /* Use lp_workgroup() if domain not specified */
1074
1075         if (!cli->auth->domain || !cli->auth->domain[0]) {
1076                 cli->auth->domain = talloc_strdup(cli, lp_workgroup());
1077                 if (cli->auth->domain == NULL) {
1078                         return NT_STATUS_NO_MEMORY;
1079                 }
1080         }
1081
1082         /*
1083          * Now marshall the data into the auth parse_struct.
1084          */
1085
1086         r.MessageType                   = NL_NEGOTIATE_REQUEST;
1087         r.Flags                         = NL_FLAG_OEM_NETBIOS_DOMAIN_NAME |
1088                                           NL_FLAG_OEM_NETBIOS_COMPUTER_NAME;
1089         r.oem_netbios_domain.a          = cli->auth->domain;
1090         r.oem_netbios_computer.a        = global_myname();
1091
1092         status = dcerpc_push_schannel_bind(cli, &r, auth_token);
1093         if (!NT_STATUS_IS_OK(status)) {
1094                 return status;
1095         }
1096
1097         return NT_STATUS_OK;
1098 }
1099
1100 /*******************************************************************
1101  Creates the internals of a DCE/RPC bind request or alter context PDU.
1102  ********************************************************************/
1103
1104 static NTSTATUS create_bind_or_alt_ctx_internal(TALLOC_CTX *mem_ctx,
1105                                                 enum dcerpc_pkt_type ptype,
1106                                                 uint32 rpc_call_id,
1107                                                 const struct ndr_syntax_id *abstract,
1108                                                 const struct ndr_syntax_id *transfer,
1109                                                 const DATA_BLOB *auth_info,
1110                                                 DATA_BLOB *blob)
1111 {
1112         uint16 auth_len = auth_info->length;
1113         NTSTATUS status;
1114         union dcerpc_payload u;
1115         struct dcerpc_ctx_list ctx_list;
1116
1117         if (auth_len) {
1118                 auth_len -= DCERPC_AUTH_TRAILER_LENGTH;
1119         }
1120
1121         ctx_list.context_id = 0;
1122         ctx_list.num_transfer_syntaxes = 1;
1123         ctx_list.abstract_syntax = *abstract;
1124         ctx_list.transfer_syntaxes = (struct ndr_syntax_id *)discard_const(transfer);
1125
1126         u.bind.max_xmit_frag    = RPC_MAX_PDU_FRAG_LEN;
1127         u.bind.max_recv_frag    = RPC_MAX_PDU_FRAG_LEN;
1128         u.bind.assoc_group_id   = 0x0;
1129         u.bind.num_contexts     = 1;
1130         u.bind.ctx_list         = &ctx_list;
1131         u.bind.auth_info        = *auth_info;
1132
1133         status = dcerpc_push_ncacn_packet(mem_ctx,
1134                                           ptype,
1135                                           DCERPC_PFC_FLAG_FIRST |
1136                                           DCERPC_PFC_FLAG_LAST,
1137                                           auth_len,
1138                                           rpc_call_id,
1139                                           &u,
1140                                           blob);
1141         if (!NT_STATUS_IS_OK(status)) {
1142                 DEBUG(0, ("Failed to marshall bind/alter ncacn_packet.\n"));
1143                 return status;
1144         }
1145
1146         return NT_STATUS_OK;
1147 }
1148
1149 /*******************************************************************
1150  Creates a DCE/RPC bind request.
1151  ********************************************************************/
1152
1153 static NTSTATUS create_rpc_bind_req(TALLOC_CTX *mem_ctx,
1154                                     struct rpc_pipe_client *cli,
1155                                     struct pipe_auth_data *auth,
1156                                     uint32 rpc_call_id,
1157                                     const struct ndr_syntax_id *abstract,
1158                                     const struct ndr_syntax_id *transfer,
1159                                     DATA_BLOB *rpc_out)
1160 {
1161         DATA_BLOB auth_token = data_blob_null;
1162         DATA_BLOB auth_info = data_blob_null;
1163         NTSTATUS ret = NT_STATUS_OK;
1164
1165         switch (auth->auth_type) {
1166         case DCERPC_AUTH_TYPE_SCHANNEL:
1167                 ret = create_schannel_auth_rpc_bind_req(cli, &auth_token);
1168                 if (!NT_STATUS_IS_OK(ret)) {
1169                         return ret;
1170                 }
1171                 break;
1172
1173         case DCERPC_AUTH_TYPE_NTLMSSP:
1174                 ret = create_ntlmssp_auth_rpc_bind_req(cli, &auth_token);
1175                 if (!NT_STATUS_IS_OK(ret)) {
1176                         return ret;
1177                 }
1178                 break;
1179
1180         case DCERPC_AUTH_TYPE_SPNEGO:
1181                 ret = create_spnego_auth_bind_req(cli, auth, &auth_token);
1182                 if (!NT_STATUS_IS_OK(ret)) {
1183                         return ret;
1184                 }
1185                 break;
1186
1187         case DCERPC_AUTH_TYPE_KRB5:
1188                 ret = create_gssapi_auth_bind_req(mem_ctx, auth, &auth_token);
1189                 if (!NT_STATUS_IS_OK(ret)) {
1190                         return ret;
1191                 }
1192                 break;
1193
1194         case DCERPC_AUTH_TYPE_NCALRPC_AS_SYSTEM:
1195                 auth_token = data_blob_talloc(mem_ctx,
1196                                               "NCALRPC_AUTH_TOKEN",
1197                                               18);
1198                 break;
1199
1200         case DCERPC_AUTH_TYPE_NONE:
1201                 break;
1202
1203         default:
1204                 /* "Can't" happen. */
1205                 return NT_STATUS_INVALID_INFO_CLASS;
1206         }
1207
1208         if (auth_token.length != 0) {
1209                 ret = dcerpc_push_dcerpc_auth(cli,
1210                                                 auth->auth_type,
1211                                                 auth->auth_level,
1212                                                 0, /* auth_pad_length */
1213                                                 1, /* auth_context_id */
1214                                                 &auth_token,
1215                                                 &auth_info);
1216                 if (!NT_STATUS_IS_OK(ret)) {
1217                         return ret;
1218                 }
1219                 data_blob_free(&auth_token);
1220         }
1221
1222         ret = create_bind_or_alt_ctx_internal(mem_ctx,
1223                                               DCERPC_PKT_BIND,
1224                                               rpc_call_id,
1225                                               abstract,
1226                                               transfer,
1227                                               &auth_info,
1228                                               rpc_out);
1229         return ret;
1230 }
1231
1232 /*******************************************************************
1233  External interface.
1234  Does an rpc request on a pipe. Incoming data is NDR encoded in in_data.
1235  Reply is NDR encoded in out_data. Splits the data stream into RPC PDU's
1236  and deals with signing/sealing details.
1237  ********************************************************************/
1238
1239 struct rpc_api_pipe_req_state {
1240         struct event_context *ev;
1241         struct rpc_pipe_client *cli;
1242         uint8_t op_num;
1243         uint32_t call_id;
1244         DATA_BLOB *req_data;
1245         uint32_t req_data_sent;
1246         DATA_BLOB rpc_out;
1247         DATA_BLOB reply_pdu;
1248 };
1249
1250 static void rpc_api_pipe_req_write_done(struct tevent_req *subreq);
1251 static void rpc_api_pipe_req_done(struct tevent_req *subreq);
1252 static NTSTATUS prepare_next_frag(struct rpc_api_pipe_req_state *state,
1253                                   bool *is_last_frag);
1254
1255 struct tevent_req *rpc_api_pipe_req_send(TALLOC_CTX *mem_ctx,
1256                                          struct event_context *ev,
1257                                          struct rpc_pipe_client *cli,
1258                                          uint8_t op_num,
1259                                          DATA_BLOB *req_data)
1260 {
1261         struct tevent_req *req, *subreq;
1262         struct rpc_api_pipe_req_state *state;
1263         NTSTATUS status;
1264         bool is_last_frag;
1265
1266         req = tevent_req_create(mem_ctx, &state,
1267                                 struct rpc_api_pipe_req_state);
1268         if (req == NULL) {
1269                 return NULL;
1270         }
1271         state->ev = ev;
1272         state->cli = cli;
1273         state->op_num = op_num;
1274         state->req_data = req_data;
1275         state->req_data_sent = 0;
1276         state->call_id = get_rpc_call_id();
1277         state->reply_pdu = data_blob_null;
1278         state->rpc_out = data_blob_null;
1279
1280         if (cli->max_xmit_frag < DCERPC_REQUEST_LENGTH
1281                                         + RPC_MAX_SIGN_SIZE) {
1282                 /* Server is screwed up ! */
1283                 status = NT_STATUS_INVALID_PARAMETER;
1284                 goto post_status;
1285         }
1286
1287         status = prepare_next_frag(state, &is_last_frag);
1288         if (!NT_STATUS_IS_OK(status)) {
1289                 goto post_status;
1290         }
1291
1292         if (is_last_frag) {
1293                 subreq = rpc_api_pipe_send(state, ev, state->cli,
1294                                            &state->rpc_out,
1295                                            DCERPC_PKT_RESPONSE);
1296                 if (subreq == NULL) {
1297                         goto fail;
1298                 }
1299                 tevent_req_set_callback(subreq, rpc_api_pipe_req_done, req);
1300         } else {
1301                 subreq = rpc_write_send(state, ev, cli->transport,
1302                                         state->rpc_out.data,
1303                                         state->rpc_out.length);
1304                 if (subreq == NULL) {
1305                         goto fail;
1306                 }
1307                 tevent_req_set_callback(subreq, rpc_api_pipe_req_write_done,
1308                                         req);
1309         }
1310         return req;
1311
1312  post_status:
1313         tevent_req_nterror(req, status);
1314         return tevent_req_post(req, ev);
1315  fail:
1316         TALLOC_FREE(req);
1317         return NULL;
1318 }
1319
1320 static NTSTATUS prepare_next_frag(struct rpc_api_pipe_req_state *state,
1321                                   bool *is_last_frag)
1322 {
1323         size_t data_sent_thistime;
1324         size_t auth_len;
1325         size_t frag_len;
1326         uint8_t flags = 0;
1327         size_t pad_len;
1328         size_t data_left;
1329         NTSTATUS status;
1330         union dcerpc_payload u;
1331
1332         data_left = state->req_data->length - state->req_data_sent;
1333
1334         status = dcerpc_guess_sizes(state->cli->auth,
1335                                     DCERPC_REQUEST_LENGTH, data_left,
1336                                     state->cli->max_xmit_frag,
1337                                     CLIENT_NDR_PADDING_SIZE,
1338                                     &data_sent_thistime,
1339                                     &frag_len, &auth_len, &pad_len);
1340         if (!NT_STATUS_IS_OK(status)) {
1341                 return status;
1342         }
1343
1344         if (state->req_data_sent == 0) {
1345                 flags = DCERPC_PFC_FLAG_FIRST;
1346         }
1347
1348         if (data_sent_thistime == data_left) {
1349                 flags |= DCERPC_PFC_FLAG_LAST;
1350         }
1351
1352         data_blob_free(&state->rpc_out);
1353
1354         ZERO_STRUCT(u.request);
1355
1356         u.request.alloc_hint    = state->req_data->length;
1357         u.request.context_id    = 0;
1358         u.request.opnum         = state->op_num;
1359
1360         status = dcerpc_push_ncacn_packet(state,
1361                                           DCERPC_PKT_REQUEST,
1362                                           flags,
1363                                           auth_len,
1364                                           state->call_id,
1365                                           &u,
1366                                           &state->rpc_out);
1367         if (!NT_STATUS_IS_OK(status)) {
1368                 return status;
1369         }
1370
1371         /* explicitly set frag_len here as dcerpc_push_ncacn_packet() can't
1372          * compute it right for requests because the auth trailer is missing
1373          * at this stage */
1374         dcerpc_set_frag_length(&state->rpc_out, frag_len);
1375
1376         /* Copy in the data. */
1377         if (!data_blob_append(NULL, &state->rpc_out,
1378                                 state->req_data->data + state->req_data_sent,
1379                                 data_sent_thistime)) {
1380                 return NT_STATUS_NO_MEMORY;
1381         }
1382
1383         switch (state->cli->auth->auth_level) {
1384         case DCERPC_AUTH_LEVEL_NONE:
1385         case DCERPC_AUTH_LEVEL_CONNECT:
1386         case DCERPC_AUTH_LEVEL_PACKET:
1387                 break;
1388         case DCERPC_AUTH_LEVEL_INTEGRITY:
1389         case DCERPC_AUTH_LEVEL_PRIVACY:
1390                 status = dcerpc_add_auth_footer(state->cli->auth, pad_len,
1391                                                 &state->rpc_out);
1392                 if (!NT_STATUS_IS_OK(status)) {
1393                         return status;
1394                 }
1395                 break;
1396         default:
1397                 return NT_STATUS_INVALID_PARAMETER;
1398         }
1399
1400         state->req_data_sent += data_sent_thistime;
1401         *is_last_frag = ((flags & DCERPC_PFC_FLAG_LAST) != 0);
1402
1403         return status;
1404 }
1405
1406 static void rpc_api_pipe_req_write_done(struct tevent_req *subreq)
1407 {
1408         struct tevent_req *req = tevent_req_callback_data(
1409                 subreq, struct tevent_req);
1410         struct rpc_api_pipe_req_state *state = tevent_req_data(
1411                 req, struct rpc_api_pipe_req_state);
1412         NTSTATUS status;
1413         bool is_last_frag;
1414
1415         status = rpc_write_recv(subreq);
1416         TALLOC_FREE(subreq);
1417         if (!NT_STATUS_IS_OK(status)) {
1418                 tevent_req_nterror(req, status);
1419                 return;
1420         }
1421
1422         status = prepare_next_frag(state, &is_last_frag);
1423         if (!NT_STATUS_IS_OK(status)) {
1424                 tevent_req_nterror(req, status);
1425                 return;
1426         }
1427
1428         if (is_last_frag) {
1429                 subreq = rpc_api_pipe_send(state, state->ev, state->cli,
1430                                            &state->rpc_out,
1431                                            DCERPC_PKT_RESPONSE);
1432                 if (tevent_req_nomem(subreq, req)) {
1433                         return;
1434                 }
1435                 tevent_req_set_callback(subreq, rpc_api_pipe_req_done, req);
1436         } else {
1437                 subreq = rpc_write_send(state, state->ev,
1438                                         state->cli->transport,
1439                                         state->rpc_out.data,
1440                                         state->rpc_out.length);
1441                 if (tevent_req_nomem(subreq, req)) {
1442                         return;
1443                 }
1444                 tevent_req_set_callback(subreq, rpc_api_pipe_req_write_done,
1445                                         req);
1446         }
1447 }
1448
1449 static void rpc_api_pipe_req_done(struct tevent_req *subreq)
1450 {
1451         struct tevent_req *req = tevent_req_callback_data(
1452                 subreq, struct tevent_req);
1453         struct rpc_api_pipe_req_state *state = tevent_req_data(
1454                 req, struct rpc_api_pipe_req_state);
1455         NTSTATUS status;
1456
1457         status = rpc_api_pipe_recv(subreq, state, NULL, &state->reply_pdu);
1458         TALLOC_FREE(subreq);
1459         if (!NT_STATUS_IS_OK(status)) {
1460                 tevent_req_nterror(req, status);
1461                 return;
1462         }
1463         tevent_req_done(req);
1464 }
1465
1466 NTSTATUS rpc_api_pipe_req_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
1467                                DATA_BLOB *reply_pdu)
1468 {
1469         struct rpc_api_pipe_req_state *state = tevent_req_data(
1470                 req, struct rpc_api_pipe_req_state);
1471         NTSTATUS status;
1472
1473         if (tevent_req_is_nterror(req, &status)) {
1474                 /*
1475                  * We always have to initialize to reply pdu, even if there is
1476                  * none. The rpccli_* caller routines expect this.
1477                  */
1478                 *reply_pdu = data_blob_null;
1479                 return status;
1480         }
1481
1482         /* return data to caller and assign it ownership of memory */
1483         reply_pdu->data = talloc_move(mem_ctx, &state->reply_pdu.data);
1484         reply_pdu->length = state->reply_pdu.length;
1485         state->reply_pdu.length = 0;
1486
1487         return NT_STATUS_OK;
1488 }
1489
1490 /****************************************************************************
1491  Check the rpc bind acknowledge response.
1492 ****************************************************************************/
1493
1494 static bool check_bind_response(const struct dcerpc_bind_ack *r,
1495                                 const struct ndr_syntax_id *transfer)
1496 {
1497         struct dcerpc_ack_ctx ctx;
1498
1499         if (r->secondary_address_size == 0) {
1500                 DEBUG(4,("Ignoring length check -- ASU bug (server didn't fill in the pipe name correctly)"));
1501         }
1502
1503         if (r->num_results < 1 || !r->ctx_list) {
1504                 return false;
1505         }
1506
1507         ctx = r->ctx_list[0];
1508
1509         /* check the transfer syntax */
1510         if ((ctx.syntax.if_version != transfer->if_version) ||
1511              (memcmp(&ctx.syntax.uuid, &transfer->uuid, sizeof(transfer->uuid)) !=0)) {
1512                 DEBUG(2,("bind_rpc_pipe: transfer syntax differs\n"));
1513                 return False;
1514         }
1515
1516         if (r->num_results != 0x1 || ctx.result != 0) {
1517                 DEBUG(2,("bind_rpc_pipe: bind denied results: %d reason: %x\n",
1518                           r->num_results, ctx.reason));
1519         }
1520
1521         DEBUG(5,("check_bind_response: accepted!\n"));
1522         return True;
1523 }
1524
1525 /*******************************************************************
1526  Creates a DCE/RPC bind authentication response.
1527  This is the packet that is sent back to the server once we
1528  have received a BIND-ACK, to finish the third leg of
1529  the authentication handshake.
1530  ********************************************************************/
1531
1532 static NTSTATUS create_rpc_bind_auth3(TALLOC_CTX *mem_ctx,
1533                                 struct rpc_pipe_client *cli,
1534                                 uint32 rpc_call_id,
1535                                 enum dcerpc_AuthType auth_type,
1536                                 enum dcerpc_AuthLevel auth_level,
1537                                 DATA_BLOB *pauth_blob,
1538                                 DATA_BLOB *rpc_out)
1539 {
1540         NTSTATUS status;
1541         union dcerpc_payload u;
1542
1543         u.auth3._pad = 0;
1544
1545         status = dcerpc_push_dcerpc_auth(mem_ctx,
1546                                          auth_type,
1547                                          auth_level,
1548                                          0, /* auth_pad_length */
1549                                          1, /* auth_context_id */
1550                                          pauth_blob,
1551                                          &u.auth3.auth_info);
1552         if (!NT_STATUS_IS_OK(status)) {
1553                 return status;
1554         }
1555
1556         status = dcerpc_push_ncacn_packet(mem_ctx,
1557                                           DCERPC_PKT_AUTH3,
1558                                           DCERPC_PFC_FLAG_FIRST |
1559                                           DCERPC_PFC_FLAG_LAST,
1560                                           pauth_blob->length,
1561                                           rpc_call_id,
1562                                           &u,
1563                                           rpc_out);
1564         data_blob_free(&u.auth3.auth_info);
1565         if (!NT_STATUS_IS_OK(status)) {
1566                 DEBUG(0,("create_bind_or_alt_ctx_internal: failed to marshall RPC_HDR_RB.\n"));
1567                 return status;
1568         }
1569
1570         return NT_STATUS_OK;
1571 }
1572
1573 /*******************************************************************
1574  Creates a DCE/RPC bind alter context authentication request which
1575  may contain a spnego auth blobl
1576  ********************************************************************/
1577
1578 static NTSTATUS create_rpc_alter_context(TALLOC_CTX *mem_ctx,
1579                                         enum dcerpc_AuthType auth_type,
1580                                         enum dcerpc_AuthLevel auth_level,
1581                                         uint32 rpc_call_id,
1582                                         const struct ndr_syntax_id *abstract,
1583                                         const struct ndr_syntax_id *transfer,
1584                                         const DATA_BLOB *pauth_blob, /* spnego auth blob already created. */
1585                                         DATA_BLOB *rpc_out)
1586 {
1587         DATA_BLOB auth_info;
1588         NTSTATUS status;
1589
1590         status = dcerpc_push_dcerpc_auth(mem_ctx,
1591                                          auth_type,
1592                                          auth_level,
1593                                          0, /* auth_pad_length */
1594                                          1, /* auth_context_id */
1595                                          pauth_blob,
1596                                          &auth_info);
1597         if (!NT_STATUS_IS_OK(status)) {
1598                 return status;
1599         }
1600
1601         status = create_bind_or_alt_ctx_internal(mem_ctx,
1602                                                  DCERPC_PKT_ALTER,
1603                                                  rpc_call_id,
1604                                                  abstract,
1605                                                  transfer,
1606                                                  &auth_info,
1607                                                  rpc_out);
1608         data_blob_free(&auth_info);
1609         return status;
1610 }
1611
1612 /****************************************************************************
1613  Do an rpc bind.
1614 ****************************************************************************/
1615
1616 struct rpc_pipe_bind_state {
1617         struct event_context *ev;
1618         struct rpc_pipe_client *cli;
1619         DATA_BLOB rpc_out;
1620         bool auth3;
1621         uint32_t rpc_call_id;
1622 };
1623
1624 static void rpc_pipe_bind_step_one_done(struct tevent_req *subreq);
1625 static NTSTATUS rpc_bind_next_send(struct tevent_req *req,
1626                                    struct rpc_pipe_bind_state *state,
1627                                    DATA_BLOB *credentials);
1628 static NTSTATUS rpc_bind_finish_send(struct tevent_req *req,
1629                                      struct rpc_pipe_bind_state *state,
1630                                      DATA_BLOB *credentials);
1631
1632 struct tevent_req *rpc_pipe_bind_send(TALLOC_CTX *mem_ctx,
1633                                       struct event_context *ev,
1634                                       struct rpc_pipe_client *cli,
1635                                       struct pipe_auth_data *auth)
1636 {
1637         struct tevent_req *req, *subreq;
1638         struct rpc_pipe_bind_state *state;
1639         NTSTATUS status;
1640
1641         req = tevent_req_create(mem_ctx, &state, struct rpc_pipe_bind_state);
1642         if (req == NULL) {
1643                 return NULL;
1644         }
1645
1646         DEBUG(5,("Bind RPC Pipe: %s auth_type %u, auth_level %u\n",
1647                 rpccli_pipe_txt(talloc_tos(), cli),
1648                 (unsigned int)auth->auth_type,
1649                 (unsigned int)auth->auth_level ));
1650
1651         state->ev = ev;
1652         state->cli = cli;
1653         state->rpc_call_id = get_rpc_call_id();
1654
1655         cli->auth = talloc_move(cli, &auth);
1656
1657         /* Marshall the outgoing data. */
1658         status = create_rpc_bind_req(state, cli,
1659                                      cli->auth,
1660                                      state->rpc_call_id,
1661                                      &cli->abstract_syntax,
1662                                      &cli->transfer_syntax,
1663                                      &state->rpc_out);
1664
1665         if (!NT_STATUS_IS_OK(status)) {
1666                 goto post_status;
1667         }
1668
1669         subreq = rpc_api_pipe_send(state, ev, cli, &state->rpc_out,
1670                                    DCERPC_PKT_BIND_ACK);
1671         if (subreq == NULL) {
1672                 goto fail;
1673         }
1674         tevent_req_set_callback(subreq, rpc_pipe_bind_step_one_done, req);
1675         return req;
1676
1677  post_status:
1678         tevent_req_nterror(req, status);
1679         return tevent_req_post(req, ev);
1680  fail:
1681         TALLOC_FREE(req);
1682         return NULL;
1683 }
1684
1685 static void rpc_pipe_bind_step_one_done(struct tevent_req *subreq)
1686 {
1687         struct tevent_req *req = tevent_req_callback_data(
1688                 subreq, struct tevent_req);
1689         struct rpc_pipe_bind_state *state = tevent_req_data(
1690                 req, struct rpc_pipe_bind_state);
1691         struct pipe_auth_data *pauth = state->cli->auth;
1692         struct auth_ntlmssp_state *ntlmssp_ctx;
1693         struct spnego_context *spnego_ctx;
1694         struct gse_context *gse_ctx;
1695         struct ncacn_packet *pkt = NULL;
1696         struct dcerpc_auth auth;
1697         DATA_BLOB auth_token = data_blob_null;
1698         NTSTATUS status;
1699
1700         status = rpc_api_pipe_recv(subreq, talloc_tos(), &pkt, NULL);
1701         TALLOC_FREE(subreq);
1702         if (!NT_STATUS_IS_OK(status)) {
1703                 DEBUG(3, ("rpc_pipe_bind: %s bind request returned %s\n",
1704                           rpccli_pipe_txt(talloc_tos(), state->cli),
1705                           nt_errstr(status)));
1706                 tevent_req_nterror(req, status);
1707                 return;
1708         }
1709
1710         if (state->auth3) {
1711                 tevent_req_done(req);
1712                 return;
1713         }
1714
1715         if (!check_bind_response(&pkt->u.bind_ack, &state->cli->transfer_syntax)) {
1716                 DEBUG(2, ("rpc_pipe_bind: check_bind_response failed.\n"));
1717                 tevent_req_nterror(req, NT_STATUS_BUFFER_TOO_SMALL);
1718                 return;
1719         }
1720
1721         state->cli->max_xmit_frag = pkt->u.bind_ack.max_xmit_frag;
1722         state->cli->max_recv_frag = pkt->u.bind_ack.max_recv_frag;
1723
1724         switch(pauth->auth_type) {
1725
1726         case DCERPC_AUTH_TYPE_NONE:
1727         case DCERPC_AUTH_TYPE_NCALRPC_AS_SYSTEM:
1728         case DCERPC_AUTH_TYPE_SCHANNEL:
1729                 /* Bind complete. */
1730                 tevent_req_done(req);
1731                 return;
1732
1733         case DCERPC_AUTH_TYPE_NTLMSSP:
1734         case DCERPC_AUTH_TYPE_SPNEGO:
1735         case DCERPC_AUTH_TYPE_KRB5:
1736                 /* Paranoid lenght checks */
1737                 if (pkt->frag_length < DCERPC_AUTH_TRAILER_LENGTH
1738                                                 + pkt->auth_length) {
1739                         tevent_req_nterror(req,
1740                                         NT_STATUS_INFO_LENGTH_MISMATCH);
1741                         return;
1742                 }
1743                 /* get auth credentials */
1744                 status = dcerpc_pull_dcerpc_auth(talloc_tos(),
1745                                                  &pkt->u.bind_ack.auth_info,
1746                                                  &auth, false);
1747                 if (!NT_STATUS_IS_OK(status)) {
1748                         DEBUG(0, ("Failed to pull dcerpc auth: %s.\n",
1749                                   nt_errstr(status)));
1750                         tevent_req_nterror(req, status);
1751                         return;
1752                 }
1753                 break;
1754
1755         default:
1756                 goto err_out;
1757         }
1758
1759         /*
1760          * For authenticated binds we may need to do 3 or 4 leg binds.
1761          */
1762
1763         switch(pauth->auth_type) {
1764
1765         case DCERPC_AUTH_TYPE_NONE:
1766         case DCERPC_AUTH_TYPE_NCALRPC_AS_SYSTEM:
1767         case DCERPC_AUTH_TYPE_SCHANNEL:
1768                 /* Bind complete. */
1769                 tevent_req_done(req);
1770                 return;
1771
1772         case DCERPC_AUTH_TYPE_NTLMSSP:
1773                 ntlmssp_ctx = talloc_get_type_abort(pauth->auth_ctx,
1774                                                     struct auth_ntlmssp_state);
1775                 status = auth_ntlmssp_update(ntlmssp_ctx,
1776                                              auth.credentials, &auth_token);
1777                 if (NT_STATUS_EQUAL(status,
1778                                     NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1779                         status = rpc_bind_next_send(req, state,
1780                                                         &auth_token);
1781                 } else if (NT_STATUS_IS_OK(status)) {
1782                         status = rpc_bind_finish_send(req, state,
1783                                                         &auth_token);
1784                 }
1785                 break;
1786
1787         case DCERPC_AUTH_TYPE_SPNEGO:
1788                 spnego_ctx = talloc_get_type_abort(pauth->auth_ctx,
1789                                                    struct spnego_context);
1790                 status = spnego_get_client_auth_token(state,
1791                                                 spnego_ctx,
1792                                                 &auth.credentials,
1793                                                 &auth_token);
1794                 if (!NT_STATUS_IS_OK(status)) {
1795                         break;
1796                 }
1797                 if (auth_token.length == 0) {
1798                         /* Bind complete. */
1799                         tevent_req_done(req);
1800                         return;
1801                 }
1802                 if (spnego_require_more_processing(spnego_ctx)) {
1803                         status = rpc_bind_next_send(req, state,
1804                                                         &auth_token);
1805                 } else {
1806                         status = rpc_bind_finish_send(req, state,
1807                                                         &auth_token);
1808                 }
1809                 break;
1810
1811         case DCERPC_AUTH_TYPE_KRB5:
1812                 gse_ctx = talloc_get_type_abort(pauth->auth_ctx,
1813                                                 struct gse_context);
1814                 status = gse_get_client_auth_token(state,
1815                                                    gse_ctx,
1816                                                    &auth.credentials,
1817                                                    &auth_token);
1818                 if (!NT_STATUS_IS_OK(status)) {
1819                         break;
1820                 }
1821
1822                 if (gse_require_more_processing(gse_ctx)) {
1823                         status = rpc_bind_next_send(req, state, &auth_token);
1824                 } else {
1825                         status = rpc_bind_finish_send(req, state, &auth_token);
1826                 }
1827                 break;
1828
1829         default:
1830                 goto err_out;
1831         }
1832
1833         if (!NT_STATUS_IS_OK(status)) {
1834                 tevent_req_nterror(req, status);
1835         }
1836         return;
1837
1838 err_out:
1839         DEBUG(0,("cli_finish_bind_auth: unknown auth type %u\n",
1840                  (unsigned int)state->cli->auth->auth_type));
1841         tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
1842 }
1843
1844 static NTSTATUS rpc_bind_next_send(struct tevent_req *req,
1845                                    struct rpc_pipe_bind_state *state,
1846                                    DATA_BLOB *auth_token)
1847 {
1848         struct pipe_auth_data *auth = state->cli->auth;
1849         struct tevent_req *subreq;
1850         NTSTATUS status;
1851
1852         /* Now prepare the alter context pdu. */
1853         data_blob_free(&state->rpc_out);
1854
1855         status = create_rpc_alter_context(state,
1856                                           auth->auth_type,
1857                                           auth->auth_level,
1858                                           state->rpc_call_id,
1859                                           &state->cli->abstract_syntax,
1860                                           &state->cli->transfer_syntax,
1861                                           auth_token,
1862                                           &state->rpc_out);
1863         if (!NT_STATUS_IS_OK(status)) {
1864                 return status;
1865         }
1866
1867         subreq = rpc_api_pipe_send(state, state->ev, state->cli,
1868                                    &state->rpc_out, DCERPC_PKT_ALTER_RESP);
1869         if (subreq == NULL) {
1870                 return NT_STATUS_NO_MEMORY;
1871         }
1872         tevent_req_set_callback(subreq, rpc_pipe_bind_step_one_done, req);
1873         return NT_STATUS_OK;
1874 }
1875
1876 static NTSTATUS rpc_bind_finish_send(struct tevent_req *req,
1877                                      struct rpc_pipe_bind_state *state,
1878                                      DATA_BLOB *auth_token)
1879 {
1880         struct pipe_auth_data *auth = state->cli->auth;
1881         struct tevent_req *subreq;
1882         NTSTATUS status;
1883
1884         state->auth3 = true;
1885
1886         /* Now prepare the auth3 context pdu. */
1887         data_blob_free(&state->rpc_out);
1888
1889         status = create_rpc_bind_auth3(state, state->cli,
1890                                         state->rpc_call_id,
1891                                         auth->auth_type,
1892                                         auth->auth_level,
1893                                         auth_token,
1894                                         &state->rpc_out);
1895         if (!NT_STATUS_IS_OK(status)) {
1896                 return status;
1897         }
1898
1899         subreq = rpc_api_pipe_send(state, state->ev, state->cli,
1900                                    &state->rpc_out, DCERPC_PKT_AUTH3);
1901         if (subreq == NULL) {
1902                 return NT_STATUS_NO_MEMORY;
1903         }
1904         tevent_req_set_callback(subreq, rpc_pipe_bind_step_one_done, req);
1905         return NT_STATUS_OK;
1906 }
1907
1908 NTSTATUS rpc_pipe_bind_recv(struct tevent_req *req)
1909 {
1910         return tevent_req_simple_recv_ntstatus(req);
1911 }
1912
1913 NTSTATUS rpc_pipe_bind(struct rpc_pipe_client *cli,
1914                        struct pipe_auth_data *auth)
1915 {
1916         TALLOC_CTX *frame = talloc_stackframe();
1917         struct event_context *ev;
1918         struct tevent_req *req;
1919         NTSTATUS status = NT_STATUS_OK;
1920
1921         ev = event_context_init(frame);
1922         if (ev == NULL) {
1923                 status = NT_STATUS_NO_MEMORY;
1924                 goto fail;
1925         }
1926
1927         req = rpc_pipe_bind_send(frame, ev, cli, auth);
1928         if (req == NULL) {
1929                 status = NT_STATUS_NO_MEMORY;
1930                 goto fail;
1931         }
1932
1933         if (!tevent_req_poll(req, ev)) {
1934                 status = map_nt_error_from_unix(errno);
1935                 goto fail;
1936         }
1937
1938         status = rpc_pipe_bind_recv(req);
1939  fail:
1940         TALLOC_FREE(frame);
1941         return status;
1942 }
1943
1944 #define RPCCLI_DEFAULT_TIMEOUT 10000 /* 10 seconds. */
1945
1946 unsigned int rpccli_set_timeout(struct rpc_pipe_client *rpc_cli,
1947                                 unsigned int timeout)
1948 {
1949         unsigned int old;
1950
1951         if (rpc_cli->transport == NULL) {
1952                 return RPCCLI_DEFAULT_TIMEOUT;
1953         }
1954
1955         if (rpc_cli->transport->set_timeout == NULL) {
1956                 return RPCCLI_DEFAULT_TIMEOUT;
1957         }
1958
1959         old = rpc_cli->transport->set_timeout(rpc_cli->transport->priv, timeout);
1960         if (old == 0) {
1961                 return RPCCLI_DEFAULT_TIMEOUT;
1962         }
1963
1964         return old;
1965 }
1966
1967 bool rpccli_is_connected(struct rpc_pipe_client *rpc_cli)
1968 {
1969         if (rpc_cli == NULL) {
1970                 return false;
1971         }
1972
1973         if (rpc_cli->transport == NULL) {
1974                 return false;
1975         }
1976
1977         return rpc_cli->transport->is_connected(rpc_cli->transport->priv);
1978 }
1979
1980 struct rpccli_bh_state {
1981         struct rpc_pipe_client *rpc_cli;
1982 };
1983
1984 static bool rpccli_bh_is_connected(struct dcerpc_binding_handle *h)
1985 {
1986         struct rpccli_bh_state *hs = dcerpc_binding_handle_data(h,
1987                                      struct rpccli_bh_state);
1988
1989         return rpccli_is_connected(hs->rpc_cli);
1990 }
1991
1992 static uint32_t rpccli_bh_set_timeout(struct dcerpc_binding_handle *h,
1993                                       uint32_t timeout)
1994 {
1995         struct rpccli_bh_state *hs = dcerpc_binding_handle_data(h,
1996                                      struct rpccli_bh_state);
1997
1998         return rpccli_set_timeout(hs->rpc_cli, timeout);
1999 }
2000
2001 struct rpccli_bh_raw_call_state {
2002         DATA_BLOB in_data;
2003         DATA_BLOB out_data;
2004         uint32_t out_flags;
2005 };
2006
2007 static void rpccli_bh_raw_call_done(struct tevent_req *subreq);
2008
2009 static struct tevent_req *rpccli_bh_raw_call_send(TALLOC_CTX *mem_ctx,
2010                                                   struct tevent_context *ev,
2011                                                   struct dcerpc_binding_handle *h,
2012                                                   const struct GUID *object,
2013                                                   uint32_t opnum,
2014                                                   uint32_t in_flags,
2015                                                   const uint8_t *in_data,
2016                                                   size_t in_length)
2017 {
2018         struct rpccli_bh_state *hs = dcerpc_binding_handle_data(h,
2019                                      struct rpccli_bh_state);
2020         struct tevent_req *req;
2021         struct rpccli_bh_raw_call_state *state;
2022         bool ok;
2023         struct tevent_req *subreq;
2024
2025         req = tevent_req_create(mem_ctx, &state,
2026                                 struct rpccli_bh_raw_call_state);
2027         if (req == NULL) {
2028                 return NULL;
2029         }
2030         state->in_data.data = discard_const_p(uint8_t, in_data);
2031         state->in_data.length = in_length;
2032
2033         ok = rpccli_bh_is_connected(h);
2034         if (!ok) {
2035                 tevent_req_nterror(req, NT_STATUS_INVALID_CONNECTION);
2036                 return tevent_req_post(req, ev);
2037         }
2038
2039         subreq = rpc_api_pipe_req_send(state, ev, hs->rpc_cli,
2040                                        opnum, &state->in_data);
2041         if (tevent_req_nomem(subreq, req)) {
2042                 return tevent_req_post(req, ev);
2043         }
2044         tevent_req_set_callback(subreq, rpccli_bh_raw_call_done, req);
2045
2046         return req;
2047 }
2048
2049 static void rpccli_bh_raw_call_done(struct tevent_req *subreq)
2050 {
2051         struct tevent_req *req =
2052                 tevent_req_callback_data(subreq,
2053                 struct tevent_req);
2054         struct rpccli_bh_raw_call_state *state =
2055                 tevent_req_data(req,
2056                 struct rpccli_bh_raw_call_state);
2057         NTSTATUS status;
2058
2059         state->out_flags = 0;
2060
2061         /* TODO: support bigendian responses */
2062
2063         status = rpc_api_pipe_req_recv(subreq, state, &state->out_data);
2064         TALLOC_FREE(subreq);
2065         if (!NT_STATUS_IS_OK(status)) {
2066                 tevent_req_nterror(req, status);
2067                 return;
2068         }
2069
2070         tevent_req_done(req);
2071 }
2072
2073 static NTSTATUS rpccli_bh_raw_call_recv(struct tevent_req *req,
2074                                         TALLOC_CTX *mem_ctx,
2075                                         uint8_t **out_data,
2076                                         size_t *out_length,
2077                                         uint32_t *out_flags)
2078 {
2079         struct rpccli_bh_raw_call_state *state =
2080                 tevent_req_data(req,
2081                 struct rpccli_bh_raw_call_state);
2082         NTSTATUS status;
2083
2084         if (tevent_req_is_nterror(req, &status)) {
2085                 tevent_req_received(req);
2086                 return status;
2087         }
2088
2089         *out_data = talloc_move(mem_ctx, &state->out_data.data);
2090         *out_length = state->out_data.length;
2091         *out_flags = state->out_flags;
2092         tevent_req_received(req);
2093         return NT_STATUS_OK;
2094 }
2095
2096 struct rpccli_bh_disconnect_state {
2097         uint8_t _dummy;
2098 };
2099
2100 static struct tevent_req *rpccli_bh_disconnect_send(TALLOC_CTX *mem_ctx,
2101                                                 struct tevent_context *ev,
2102                                                 struct dcerpc_binding_handle *h)
2103 {
2104         struct rpccli_bh_state *hs = dcerpc_binding_handle_data(h,
2105                                      struct rpccli_bh_state);
2106         struct tevent_req *req;
2107         struct rpccli_bh_disconnect_state *state;
2108         bool ok;
2109
2110         req = tevent_req_create(mem_ctx, &state,
2111                                 struct rpccli_bh_disconnect_state);
2112         if (req == NULL) {
2113                 return NULL;
2114         }
2115
2116         ok = rpccli_bh_is_connected(h);
2117         if (!ok) {
2118                 tevent_req_nterror(req, NT_STATUS_INVALID_CONNECTION);
2119                 return tevent_req_post(req, ev);
2120         }
2121
2122         /*
2123          * TODO: do a real async disconnect ...
2124          *
2125          * For now the caller needs to free rpc_cli
2126          */
2127         hs->rpc_cli = NULL;
2128
2129         tevent_req_done(req);
2130         return tevent_req_post(req, ev);
2131 }
2132
2133 static NTSTATUS rpccli_bh_disconnect_recv(struct tevent_req *req)
2134 {
2135         NTSTATUS status;
2136
2137         if (tevent_req_is_nterror(req, &status)) {
2138                 tevent_req_received(req);
2139                 return status;
2140         }
2141
2142         tevent_req_received(req);
2143         return NT_STATUS_OK;
2144 }
2145
2146 static bool rpccli_bh_ref_alloc(struct dcerpc_binding_handle *h)
2147 {
2148         return true;
2149 }
2150
2151 static void rpccli_bh_do_ndr_print(struct dcerpc_binding_handle *h,
2152                                    int ndr_flags,
2153                                    const void *_struct_ptr,
2154                                    const struct ndr_interface_call *call)
2155 {
2156         void *struct_ptr = discard_const(_struct_ptr);
2157
2158         if (DEBUGLEVEL < 10) {
2159                 return;
2160         }
2161
2162         if (ndr_flags & NDR_IN) {
2163                 ndr_print_function_debug(call->ndr_print,
2164                                          call->name,
2165                                          ndr_flags,
2166                                          struct_ptr);
2167         }
2168         if (ndr_flags & NDR_OUT) {
2169                 ndr_print_function_debug(call->ndr_print,
2170                                          call->name,
2171                                          ndr_flags,
2172                                          struct_ptr);
2173         }
2174 }
2175
2176 static const struct dcerpc_binding_handle_ops rpccli_bh_ops = {
2177         .name                   = "rpccli",
2178         .is_connected           = rpccli_bh_is_connected,
2179         .set_timeout            = rpccli_bh_set_timeout,
2180         .raw_call_send          = rpccli_bh_raw_call_send,
2181         .raw_call_recv          = rpccli_bh_raw_call_recv,
2182         .disconnect_send        = rpccli_bh_disconnect_send,
2183         .disconnect_recv        = rpccli_bh_disconnect_recv,
2184
2185         .ref_alloc              = rpccli_bh_ref_alloc,
2186         .do_ndr_print           = rpccli_bh_do_ndr_print,
2187 };
2188
2189 /* initialise a rpc_pipe_client binding handle */
2190 struct dcerpc_binding_handle *rpccli_bh_create(struct rpc_pipe_client *c)
2191 {
2192         struct dcerpc_binding_handle *h;
2193         struct rpccli_bh_state *hs;
2194
2195         h = dcerpc_binding_handle_create(c,
2196                                          &rpccli_bh_ops,
2197                                          NULL,
2198                                          NULL, /* TODO */
2199                                          &hs,
2200                                          struct rpccli_bh_state,
2201                                          __location__);
2202         if (h == NULL) {
2203                 return NULL;
2204         }
2205         hs->rpc_cli = c;
2206
2207         return h;
2208 }
2209
2210 bool rpccli_get_pwd_hash(struct rpc_pipe_client *rpc_cli, uint8_t nt_hash[16])
2211 {
2212         struct auth_ntlmssp_state *a = NULL;
2213         struct cli_state *cli;
2214
2215         if (rpc_cli->auth->auth_type == DCERPC_AUTH_TYPE_NTLMSSP) {
2216                 a = talloc_get_type_abort(rpc_cli->auth->auth_ctx,
2217                                           struct auth_ntlmssp_state);
2218         } else if (rpc_cli->auth->auth_type == DCERPC_AUTH_TYPE_SPNEGO) {
2219                 struct spnego_context *spnego_ctx;
2220                 enum spnego_mech auth_type;
2221                 void *auth_ctx;
2222                 NTSTATUS status;
2223
2224                 spnego_ctx = talloc_get_type_abort(rpc_cli->auth->auth_ctx,
2225                                                    struct spnego_context);
2226                 status = spnego_get_negotiated_mech(spnego_ctx,
2227                                                     &auth_type, &auth_ctx);
2228                 if (!NT_STATUS_IS_OK(status)) {
2229                         return false;
2230                 }
2231
2232                 if (auth_type == SPNEGO_NTLMSSP) {
2233                         a = talloc_get_type_abort(auth_ctx,
2234                                                   struct auth_ntlmssp_state);
2235                 }
2236         }
2237
2238         if (a) {
2239                 memcpy(nt_hash, auth_ntlmssp_get_nt_hash(a), 16);
2240                 return true;
2241         }
2242
2243         cli = rpc_pipe_np_smb_conn(rpc_cli);
2244         if (cli == NULL) {
2245                 return false;
2246         }
2247         E_md4hash(cli->password ? cli->password : "", nt_hash);
2248         return true;
2249 }
2250
2251 NTSTATUS rpccli_ncalrpc_bind_data(TALLOC_CTX *mem_ctx,
2252                                   struct pipe_auth_data **presult)
2253 {
2254         struct pipe_auth_data *result;
2255
2256         result = talloc(mem_ctx, struct pipe_auth_data);
2257         if (result == NULL) {
2258                 return NT_STATUS_NO_MEMORY;
2259         }
2260
2261         result->auth_type = DCERPC_AUTH_TYPE_NCALRPC_AS_SYSTEM;
2262         result->auth_level = DCERPC_AUTH_LEVEL_CONNECT;
2263
2264         result->user_name = talloc_strdup(result, "");
2265         result->domain = talloc_strdup(result, "");
2266         if ((result->user_name == NULL) || (result->domain == NULL)) {
2267                 TALLOC_FREE(result);
2268                 return NT_STATUS_NO_MEMORY;
2269         }
2270
2271         *presult = result;
2272         return NT_STATUS_OK;
2273 }
2274
2275 NTSTATUS rpccli_anon_bind_data(TALLOC_CTX *mem_ctx,
2276                                struct pipe_auth_data **presult)
2277 {
2278         struct pipe_auth_data *result;
2279
2280         result = talloc(mem_ctx, struct pipe_auth_data);
2281         if (result == NULL) {
2282                 return NT_STATUS_NO_MEMORY;
2283         }
2284
2285         result->auth_type = DCERPC_AUTH_TYPE_NONE;
2286         result->auth_level = DCERPC_AUTH_LEVEL_NONE;
2287
2288         result->user_name = talloc_strdup(result, "");
2289         result->domain = talloc_strdup(result, "");
2290         if ((result->user_name == NULL) || (result->domain == NULL)) {
2291                 TALLOC_FREE(result);
2292                 return NT_STATUS_NO_MEMORY;
2293         }
2294
2295         *presult = result;
2296         return NT_STATUS_OK;
2297 }
2298
2299 static int cli_auth_ntlmssp_data_destructor(struct pipe_auth_data *auth)
2300 {
2301         TALLOC_FREE(auth->auth_ctx);
2302         return 0;
2303 }
2304
2305 static NTSTATUS rpccli_ntlmssp_bind_data(TALLOC_CTX *mem_ctx,
2306                                   enum dcerpc_AuthType auth_type,
2307                                   enum dcerpc_AuthLevel auth_level,
2308                                   const char *domain,
2309                                   const char *username,
2310                                   const char *password,
2311                                   struct pipe_auth_data **presult)
2312 {
2313         struct auth_ntlmssp_state *ntlmssp_ctx;
2314         struct pipe_auth_data *result;
2315         NTSTATUS status;
2316
2317         result = talloc(mem_ctx, struct pipe_auth_data);
2318         if (result == NULL) {
2319                 return NT_STATUS_NO_MEMORY;
2320         }
2321
2322         result->auth_type = auth_type;
2323         result->auth_level = auth_level;
2324
2325         result->user_name = talloc_strdup(result, username);
2326         result->domain = talloc_strdup(result, domain);
2327         if ((result->user_name == NULL) || (result->domain == NULL)) {
2328                 status = NT_STATUS_NO_MEMORY;
2329                 goto fail;
2330         }
2331
2332         status = auth_ntlmssp_client_start(NULL,
2333                                       global_myname(),
2334                                       lp_workgroup(),
2335                                       lp_client_ntlmv2_auth(),
2336                                       &ntlmssp_ctx);
2337         if (!NT_STATUS_IS_OK(status)) {
2338                 goto fail;
2339         }
2340
2341         talloc_set_destructor(result, cli_auth_ntlmssp_data_destructor);
2342
2343         status = auth_ntlmssp_set_username(ntlmssp_ctx, username);
2344         if (!NT_STATUS_IS_OK(status)) {
2345                 goto fail;
2346         }
2347
2348         status = auth_ntlmssp_set_domain(ntlmssp_ctx, domain);
2349         if (!NT_STATUS_IS_OK(status)) {
2350                 goto fail;
2351         }
2352
2353         status = auth_ntlmssp_set_password(ntlmssp_ctx, password);
2354         if (!NT_STATUS_IS_OK(status)) {
2355                 goto fail;
2356         }
2357
2358         /*
2359          * Turn off sign+seal to allow selected auth level to turn it back on.
2360          */
2361         auth_ntlmssp_and_flags(ntlmssp_ctx, ~(NTLMSSP_NEGOTIATE_SIGN |
2362                                                 NTLMSSP_NEGOTIATE_SEAL));
2363
2364         if (auth_level == DCERPC_AUTH_LEVEL_INTEGRITY) {
2365                 auth_ntlmssp_or_flags(ntlmssp_ctx, NTLMSSP_NEGOTIATE_SIGN);
2366         } else if (auth_level == DCERPC_AUTH_LEVEL_PRIVACY) {
2367                 auth_ntlmssp_or_flags(ntlmssp_ctx, NTLMSSP_NEGOTIATE_SEAL |
2368                                                      NTLMSSP_NEGOTIATE_SIGN);
2369         }
2370
2371         result->auth_ctx = ntlmssp_ctx;
2372         *presult = result;
2373         return NT_STATUS_OK;
2374
2375  fail:
2376         TALLOC_FREE(result);
2377         return status;
2378 }
2379
2380 NTSTATUS rpccli_schannel_bind_data(TALLOC_CTX *mem_ctx, const char *domain,
2381                                    enum dcerpc_AuthLevel auth_level,
2382                                    struct netlogon_creds_CredentialState *creds,
2383                                    struct pipe_auth_data **presult)
2384 {
2385         struct schannel_state *schannel_auth;
2386         struct pipe_auth_data *result;
2387
2388         result = talloc(mem_ctx, struct pipe_auth_data);
2389         if (result == NULL) {
2390                 return NT_STATUS_NO_MEMORY;
2391         }
2392
2393         result->auth_type = DCERPC_AUTH_TYPE_SCHANNEL;
2394         result->auth_level = auth_level;
2395
2396         result->user_name = talloc_strdup(result, "");
2397         result->domain = talloc_strdup(result, domain);
2398         if ((result->user_name == NULL) || (result->domain == NULL)) {
2399                 goto fail;
2400         }
2401
2402         schannel_auth = talloc(result, struct schannel_state);
2403         if (schannel_auth == NULL) {
2404                 goto fail;
2405         }
2406
2407         schannel_auth->state = SCHANNEL_STATE_START;
2408         schannel_auth->seq_num = 0;
2409         schannel_auth->initiator = true;
2410         schannel_auth->creds = netlogon_creds_copy(result, creds);
2411
2412         result->auth_ctx = schannel_auth;
2413         *presult = result;
2414         return NT_STATUS_OK;
2415
2416  fail:
2417         TALLOC_FREE(result);
2418         return NT_STATUS_NO_MEMORY;
2419 }
2420
2421 /**
2422  * Create an rpc pipe client struct, connecting to a tcp port.
2423  */
2424 static NTSTATUS rpc_pipe_open_tcp_port(TALLOC_CTX *mem_ctx, const char *host,
2425                                        uint16_t port,
2426                                        const struct ndr_syntax_id *abstract_syntax,
2427                                        struct rpc_pipe_client **presult)
2428 {
2429         struct rpc_pipe_client *result;
2430         struct sockaddr_storage addr;
2431         NTSTATUS status;
2432         int fd;
2433
2434         result = TALLOC_ZERO_P(mem_ctx, struct rpc_pipe_client);
2435         if (result == NULL) {
2436                 return NT_STATUS_NO_MEMORY;
2437         }
2438
2439         result->abstract_syntax = *abstract_syntax;
2440         result->transfer_syntax = ndr_transfer_syntax;
2441
2442         result->desthost = talloc_strdup(result, host);
2443         result->srv_name_slash = talloc_asprintf_strupper_m(
2444                 result, "\\\\%s", result->desthost);
2445         if ((result->desthost == NULL) || (result->srv_name_slash == NULL)) {
2446                 status = NT_STATUS_NO_MEMORY;
2447                 goto fail;
2448         }
2449
2450         result->max_xmit_frag = RPC_MAX_PDU_FRAG_LEN;
2451         result->max_recv_frag = RPC_MAX_PDU_FRAG_LEN;
2452
2453         if (!resolve_name(host, &addr, 0, false)) {
2454                 status = NT_STATUS_NOT_FOUND;
2455                 goto fail;
2456         }
2457
2458         status = open_socket_out(&addr, port, 60*1000, &fd);
2459         if (!NT_STATUS_IS_OK(status)) {
2460                 goto fail;
2461         }
2462         set_socket_options(fd, lp_socket_options());
2463
2464         status = rpc_transport_sock_init(result, fd, &result->transport);
2465         if (!NT_STATUS_IS_OK(status)) {
2466                 close(fd);
2467                 goto fail;
2468         }
2469
2470         result->transport->transport = NCACN_IP_TCP;
2471
2472         result->binding_handle = rpccli_bh_create(result);
2473         if (result->binding_handle == NULL) {
2474                 TALLOC_FREE(result);
2475                 return NT_STATUS_NO_MEMORY;
2476         }
2477
2478         *presult = result;
2479         return NT_STATUS_OK;
2480
2481  fail:
2482         TALLOC_FREE(result);
2483         return status;
2484 }
2485
2486 /**
2487  * Determine the tcp port on which a dcerpc interface is listening
2488  * for the ncacn_ip_tcp transport via the endpoint mapper of the
2489  * target host.
2490  */
2491 static NTSTATUS rpc_pipe_get_tcp_port(const char *host,
2492                                       const struct ndr_syntax_id *abstract_syntax,
2493                                       uint16_t *pport)
2494 {
2495         NTSTATUS status;
2496         struct rpc_pipe_client *epm_pipe = NULL;
2497         struct dcerpc_binding_handle *epm_handle = NULL;
2498         struct pipe_auth_data *auth = NULL;
2499         struct dcerpc_binding *map_binding = NULL;
2500         struct dcerpc_binding *res_binding = NULL;
2501         struct epm_twr_t *map_tower = NULL;
2502         struct epm_twr_t *res_towers = NULL;
2503         struct policy_handle *entry_handle = NULL;
2504         uint32_t num_towers = 0;
2505         uint32_t max_towers = 1;
2506         struct epm_twr_p_t towers;
2507         TALLOC_CTX *tmp_ctx = talloc_stackframe();
2508         uint32_t result = 0;
2509
2510         if (pport == NULL) {
2511                 status = NT_STATUS_INVALID_PARAMETER;
2512                 goto done;
2513         }
2514
2515         if (ndr_syntax_id_equal(abstract_syntax,
2516                                 &ndr_table_epmapper.syntax_id)) {
2517                 *pport = 135;
2518                 return NT_STATUS_OK;
2519         }
2520
2521         /* open the connection to the endpoint mapper */
2522         status = rpc_pipe_open_tcp_port(tmp_ctx, host, 135,
2523                                         &ndr_table_epmapper.syntax_id,
2524                                         &epm_pipe);
2525
2526         if (!NT_STATUS_IS_OK(status)) {
2527                 goto done;
2528         }
2529         epm_handle = epm_pipe->binding_handle;
2530
2531         status = rpccli_anon_bind_data(tmp_ctx, &auth);
2532         if (!NT_STATUS_IS_OK(status)) {
2533                 goto done;
2534         }
2535
2536         status = rpc_pipe_bind(epm_pipe, auth);
2537         if (!NT_STATUS_IS_OK(status)) {
2538                 goto done;
2539         }
2540
2541         /* create tower for asking the epmapper */
2542
2543         map_binding = TALLOC_ZERO_P(tmp_ctx, struct dcerpc_binding);
2544         if (map_binding == NULL) {
2545                 status = NT_STATUS_NO_MEMORY;
2546                 goto done;
2547         }
2548
2549         map_binding->transport = NCACN_IP_TCP;
2550         map_binding->object = *abstract_syntax;
2551         map_binding->host = host; /* needed? */
2552         map_binding->endpoint = "0"; /* correct? needed? */
2553
2554         map_tower = TALLOC_ZERO_P(tmp_ctx, struct epm_twr_t);
2555         if (map_tower == NULL) {
2556                 status = NT_STATUS_NO_MEMORY;
2557                 goto done;
2558         }
2559
2560         status = dcerpc_binding_build_tower(tmp_ctx, map_binding,
2561                                             &(map_tower->tower));
2562         if (!NT_STATUS_IS_OK(status)) {
2563                 goto done;
2564         }
2565
2566         /* allocate further parameters for the epm_Map call */
2567
2568         res_towers = TALLOC_ARRAY(tmp_ctx, struct epm_twr_t, max_towers);
2569         if (res_towers == NULL) {
2570                 status = NT_STATUS_NO_MEMORY;
2571                 goto done;
2572         }
2573         towers.twr = res_towers;
2574
2575         entry_handle = TALLOC_ZERO_P(tmp_ctx, struct policy_handle);
2576         if (entry_handle == NULL) {
2577                 status = NT_STATUS_NO_MEMORY;
2578                 goto done;
2579         }
2580
2581         /* ask the endpoint mapper for the port */
2582
2583         status = dcerpc_epm_Map(epm_handle,
2584                                 tmp_ctx,
2585                                 discard_const_p(struct GUID,
2586                                               &(abstract_syntax->uuid)),
2587                                 map_tower,
2588                                 entry_handle,
2589                                 max_towers,
2590                                 &num_towers,
2591                                 &towers,
2592                                 &result);
2593
2594         if (!NT_STATUS_IS_OK(status)) {
2595                 goto done;
2596         }
2597
2598         if (result != EPMAPPER_STATUS_OK) {
2599                 status = NT_STATUS_UNSUCCESSFUL;
2600                 goto done;
2601         }
2602
2603         if (num_towers != 1) {
2604                 status = NT_STATUS_UNSUCCESSFUL;
2605                 goto done;
2606         }
2607
2608         /* extract the port from the answer */
2609
2610         status = dcerpc_binding_from_tower(tmp_ctx,
2611                                            &(towers.twr->tower),
2612                                            &res_binding);
2613         if (!NT_STATUS_IS_OK(status)) {
2614                 goto done;
2615         }
2616
2617         /* are further checks here necessary? */
2618         if (res_binding->transport != NCACN_IP_TCP) {
2619                 status = NT_STATUS_UNSUCCESSFUL;
2620                 goto done;
2621         }
2622
2623         *pport = (uint16_t)atoi(res_binding->endpoint);
2624
2625 done:
2626         TALLOC_FREE(tmp_ctx);
2627         return status;
2628 }
2629
2630 /**
2631  * Create a rpc pipe client struct, connecting to a host via tcp.
2632  * The port is determined by asking the endpoint mapper on the given
2633  * host.
2634  */
2635 NTSTATUS rpc_pipe_open_tcp(TALLOC_CTX *mem_ctx, const char *host,
2636                            const struct ndr_syntax_id *abstract_syntax,
2637                            struct rpc_pipe_client **presult)
2638 {
2639         NTSTATUS status;
2640         uint16_t port = 0;
2641
2642         status = rpc_pipe_get_tcp_port(host, abstract_syntax, &port);
2643         if (!NT_STATUS_IS_OK(status)) {
2644                 return status;
2645         }
2646
2647         return rpc_pipe_open_tcp_port(mem_ctx, host, port,
2648                                         abstract_syntax, presult);
2649 }
2650
2651 /********************************************************************
2652  Create a rpc pipe client struct, connecting to a unix domain socket
2653  ********************************************************************/
2654 NTSTATUS rpc_pipe_open_ncalrpc(TALLOC_CTX *mem_ctx, const char *socket_path,
2655                                const struct ndr_syntax_id *abstract_syntax,
2656                                struct rpc_pipe_client **presult)
2657 {
2658         struct rpc_pipe_client *result;
2659         struct sockaddr_un addr;
2660         NTSTATUS status;
2661         int fd;
2662
2663         result = talloc_zero(mem_ctx, struct rpc_pipe_client);
2664         if (result == NULL) {
2665                 return NT_STATUS_NO_MEMORY;
2666         }
2667
2668         result->abstract_syntax = *abstract_syntax;
2669         result->transfer_syntax = ndr_transfer_syntax;
2670
2671         result->desthost = get_myname(result);
2672         result->srv_name_slash = talloc_asprintf_strupper_m(
2673                 result, "\\\\%s", result->desthost);
2674         if ((result->desthost == NULL) || (result->srv_name_slash == NULL)) {
2675                 status = NT_STATUS_NO_MEMORY;
2676                 goto fail;
2677         }
2678
2679         result->max_xmit_frag = RPC_MAX_PDU_FRAG_LEN;
2680         result->max_recv_frag = RPC_MAX_PDU_FRAG_LEN;
2681
2682         fd = socket(AF_UNIX, SOCK_STREAM, 0);
2683         if (fd == -1) {
2684                 status = map_nt_error_from_unix(errno);
2685                 goto fail;
2686         }
2687
2688         ZERO_STRUCT(addr);
2689         addr.sun_family = AF_UNIX;
2690         strlcpy(addr.sun_path, socket_path, sizeof(addr.sun_path));
2691
2692         if (sys_connect(fd, (struct sockaddr *)(void *)&addr) == -1) {
2693                 DEBUG(0, ("connect(%s) failed: %s\n", socket_path,
2694                           strerror(errno)));
2695                 close(fd);
2696                 return map_nt_error_from_unix(errno);
2697         }
2698
2699         status = rpc_transport_sock_init(result, fd, &result->transport);
2700         if (!NT_STATUS_IS_OK(status)) {
2701                 close(fd);
2702                 goto fail;
2703         }
2704
2705         result->transport->transport = NCALRPC;
2706
2707         result->binding_handle = rpccli_bh_create(result);
2708         if (result->binding_handle == NULL) {
2709                 TALLOC_FREE(result);
2710                 return NT_STATUS_NO_MEMORY;
2711         }
2712
2713         *presult = result;
2714         return NT_STATUS_OK;
2715
2716  fail:
2717         TALLOC_FREE(result);
2718         return status;
2719 }
2720
2721 struct rpc_pipe_client_np_ref {
2722         struct cli_state *cli;
2723         struct rpc_pipe_client *pipe;
2724 };
2725
2726 static int rpc_pipe_client_np_ref_destructor(struct rpc_pipe_client_np_ref *np_ref)
2727 {
2728         DLIST_REMOVE(np_ref->cli->pipe_list, np_ref->pipe);
2729         return 0;
2730 }
2731
2732 /****************************************************************************
2733  Open a named pipe over SMB to a remote server.
2734  *
2735  * CAVEAT CALLER OF THIS FUNCTION:
2736  *    The returned rpc_pipe_client saves a copy of the cli_state cli pointer,
2737  *    so be sure that this function is called AFTER any structure (vs pointer)
2738  *    assignment of the cli.  In particular, libsmbclient does structure
2739  *    assignments of cli, which invalidates the data in the returned
2740  *    rpc_pipe_client if this function is called before the structure assignment
2741  *    of cli.
2742  * 
2743  ****************************************************************************/
2744
2745 static NTSTATUS rpc_pipe_open_np(struct cli_state *cli,
2746                                  const struct ndr_syntax_id *abstract_syntax,
2747                                  struct rpc_pipe_client **presult)
2748 {
2749         struct rpc_pipe_client *result;
2750         NTSTATUS status;
2751         struct rpc_pipe_client_np_ref *np_ref;
2752
2753         /* sanity check to protect against crashes */
2754
2755         if ( !cli ) {
2756                 return NT_STATUS_INVALID_HANDLE;
2757         }
2758
2759         result = TALLOC_ZERO_P(NULL, struct rpc_pipe_client);
2760         if (result == NULL) {
2761                 return NT_STATUS_NO_MEMORY;
2762         }
2763
2764         result->abstract_syntax = *abstract_syntax;
2765         result->transfer_syntax = ndr_transfer_syntax;
2766         result->desthost = talloc_strdup(result, cli->desthost);
2767         result->srv_name_slash = talloc_asprintf_strupper_m(
2768                 result, "\\\\%s", result->desthost);
2769
2770         result->max_xmit_frag = RPC_MAX_PDU_FRAG_LEN;
2771         result->max_recv_frag = RPC_MAX_PDU_FRAG_LEN;
2772
2773         if ((result->desthost == NULL) || (result->srv_name_slash == NULL)) {
2774                 TALLOC_FREE(result);
2775                 return NT_STATUS_NO_MEMORY;
2776         }
2777
2778         status = rpc_transport_np_init(result, cli, abstract_syntax,
2779                                        &result->transport);
2780         if (!NT_STATUS_IS_OK(status)) {
2781                 TALLOC_FREE(result);
2782                 return status;
2783         }
2784
2785         result->transport->transport = NCACN_NP;
2786
2787         np_ref = talloc(result->transport, struct rpc_pipe_client_np_ref);
2788         if (np_ref == NULL) {
2789                 TALLOC_FREE(result);
2790                 return NT_STATUS_NO_MEMORY;
2791         }
2792         np_ref->cli = cli;
2793         np_ref->pipe = result;
2794
2795         DLIST_ADD(np_ref->cli->pipe_list, np_ref->pipe);
2796         talloc_set_destructor(np_ref, rpc_pipe_client_np_ref_destructor);
2797
2798         result->binding_handle = rpccli_bh_create(result);
2799         if (result->binding_handle == NULL) {
2800                 TALLOC_FREE(result);
2801                 return NT_STATUS_NO_MEMORY;
2802         }
2803
2804         *presult = result;
2805         return NT_STATUS_OK;
2806 }
2807
2808 /****************************************************************************
2809  Open a pipe to a remote server.
2810  ****************************************************************************/
2811
2812 static NTSTATUS cli_rpc_pipe_open(struct cli_state *cli,
2813                                   enum dcerpc_transport_t transport,
2814                                   const struct ndr_syntax_id *interface,
2815                                   struct rpc_pipe_client **presult)
2816 {
2817         switch (transport) {
2818         case NCACN_IP_TCP:
2819                 return rpc_pipe_open_tcp(NULL, cli->desthost, interface,
2820                                          presult);
2821         case NCACN_NP:
2822                 return rpc_pipe_open_np(cli, interface, presult);
2823         default:
2824                 return NT_STATUS_NOT_IMPLEMENTED;
2825         }
2826 }
2827
2828 /****************************************************************************
2829  Open a named pipe to an SMB server and bind anonymously.
2830  ****************************************************************************/
2831
2832 NTSTATUS cli_rpc_pipe_open_noauth_transport(struct cli_state *cli,
2833                                             enum dcerpc_transport_t transport,
2834                                             const struct ndr_syntax_id *interface,
2835                                             struct rpc_pipe_client **presult)
2836 {
2837         struct rpc_pipe_client *result;
2838         struct pipe_auth_data *auth;
2839         NTSTATUS status;
2840
2841         status = cli_rpc_pipe_open(cli, transport, interface, &result);
2842         if (!NT_STATUS_IS_OK(status)) {
2843                 return status;
2844         }
2845
2846         status = rpccli_anon_bind_data(result, &auth);
2847         if (!NT_STATUS_IS_OK(status)) {
2848                 DEBUG(0, ("rpccli_anon_bind_data returned %s\n",
2849                           nt_errstr(status)));
2850                 TALLOC_FREE(result);
2851                 return status;
2852         }
2853
2854         /*
2855          * This is a bit of an abstraction violation due to the fact that an
2856          * anonymous bind on an authenticated SMB inherits the user/domain
2857          * from the enclosing SMB creds
2858          */
2859
2860         TALLOC_FREE(auth->user_name);
2861         TALLOC_FREE(auth->domain);
2862
2863         auth->user_name = talloc_strdup(auth, cli->user_name);
2864         auth->domain = talloc_strdup(auth, cli->domain);
2865         auth->user_session_key = data_blob_talloc(auth,
2866                 cli->user_session_key.data,
2867                 cli->user_session_key.length);
2868
2869         if ((auth->user_name == NULL) || (auth->domain == NULL)) {
2870                 TALLOC_FREE(result);
2871                 return NT_STATUS_NO_MEMORY;
2872         }
2873
2874         status = rpc_pipe_bind(result, auth);
2875         if (!NT_STATUS_IS_OK(status)) {
2876                 int lvl = 0;
2877                 if (ndr_syntax_id_equal(interface,
2878                                         &ndr_table_dssetup.syntax_id)) {
2879                         /* non AD domains just don't have this pipe, avoid
2880                          * level 0 statement in that case - gd */
2881                         lvl = 3;
2882                 }
2883                 DEBUG(lvl, ("cli_rpc_pipe_open_noauth: rpc_pipe_bind for pipe "
2884                             "%s failed with error %s\n",
2885                             get_pipe_name_from_syntax(talloc_tos(), interface),
2886                             nt_errstr(status) ));
2887                 TALLOC_FREE(result);
2888                 return status;
2889         }
2890
2891         DEBUG(10,("cli_rpc_pipe_open_noauth: opened pipe %s to machine "
2892                   "%s and bound anonymously.\n",
2893                   get_pipe_name_from_syntax(talloc_tos(), interface),
2894                   cli->desthost));
2895
2896         *presult = result;
2897         return NT_STATUS_OK;
2898 }
2899
2900 /****************************************************************************
2901  ****************************************************************************/
2902
2903 NTSTATUS cli_rpc_pipe_open_noauth(struct cli_state *cli,
2904                                   const struct ndr_syntax_id *interface,
2905                                   struct rpc_pipe_client **presult)
2906 {
2907         return cli_rpc_pipe_open_noauth_transport(cli, NCACN_NP,
2908                                                   interface, presult);
2909 }
2910
2911 /****************************************************************************
2912  Open a named pipe to an SMB server and bind using NTLMSSP or SPNEGO NTLMSSP
2913  ****************************************************************************/
2914
2915 NTSTATUS cli_rpc_pipe_open_ntlmssp(struct cli_state *cli,
2916                                    const struct ndr_syntax_id *interface,
2917                                    enum dcerpc_transport_t transport,
2918                                    enum dcerpc_AuthLevel auth_level,
2919                                    const char *domain,
2920                                    const char *username,
2921                                    const char *password,
2922                                    struct rpc_pipe_client **presult)
2923 {
2924         struct rpc_pipe_client *result;
2925         struct pipe_auth_data *auth = NULL;
2926         enum dcerpc_AuthType auth_type = DCERPC_AUTH_TYPE_NTLMSSP;
2927         NTSTATUS status;
2928
2929         status = cli_rpc_pipe_open(cli, transport, interface, &result);
2930         if (!NT_STATUS_IS_OK(status)) {
2931                 return status;
2932         }
2933
2934         status = rpccli_ntlmssp_bind_data(result,
2935                                           auth_type, auth_level,
2936                                           domain, username, password,
2937                                           &auth);
2938         if (!NT_STATUS_IS_OK(status)) {
2939                 DEBUG(0, ("rpccli_ntlmssp_bind_data returned %s\n",
2940                           nt_errstr(status)));
2941                 goto err;
2942         }
2943
2944         status = rpc_pipe_bind(result, auth);
2945         if (!NT_STATUS_IS_OK(status)) {
2946                 DEBUG(0, ("cli_rpc_pipe_open_ntlmssp_internal: cli_rpc_pipe_bind failed with error %s\n",
2947                         nt_errstr(status) ));
2948                 goto err;
2949         }
2950
2951         DEBUG(10,("cli_rpc_pipe_open_ntlmssp_internal: opened pipe %s to "
2952                 "machine %s and bound NTLMSSP as user %s\\%s.\n",
2953                   get_pipe_name_from_syntax(talloc_tos(), interface),
2954                   cli->desthost, domain, username ));
2955
2956         *presult = result;
2957         return NT_STATUS_OK;
2958
2959   err:
2960
2961         TALLOC_FREE(result);
2962         return status;
2963 }
2964
2965 /****************************************************************************
2966  External interface.
2967  Open a named pipe to an SMB server and bind using schannel (bind type 68)
2968  using session_key. sign and seal.
2969
2970  The *pdc will be stolen onto this new pipe
2971  ****************************************************************************/
2972
2973 NTSTATUS cli_rpc_pipe_open_schannel_with_key(struct cli_state *cli,
2974                                              const struct ndr_syntax_id *interface,
2975                                              enum dcerpc_transport_t transport,
2976                                              enum dcerpc_AuthLevel auth_level,
2977                                              const char *domain,
2978                                              struct netlogon_creds_CredentialState **pdc,
2979                                              struct rpc_pipe_client **presult)
2980 {
2981         struct rpc_pipe_client *result;
2982         struct pipe_auth_data *auth;
2983         NTSTATUS status;
2984
2985         status = cli_rpc_pipe_open(cli, transport, interface, &result);
2986         if (!NT_STATUS_IS_OK(status)) {
2987                 return status;
2988         }
2989
2990         status = rpccli_schannel_bind_data(result, domain, auth_level,
2991                                            *pdc, &auth);
2992         if (!NT_STATUS_IS_OK(status)) {
2993                 DEBUG(0, ("rpccli_schannel_bind_data returned %s\n",
2994                           nt_errstr(status)));
2995                 TALLOC_FREE(result);
2996                 return status;
2997         }
2998
2999         status = rpc_pipe_bind(result, auth);
3000         if (!NT_STATUS_IS_OK(status)) {
3001                 DEBUG(0, ("cli_rpc_pipe_open_schannel_with_key: "
3002                           "cli_rpc_pipe_bind failed with error %s\n",
3003                           nt_errstr(status) ));
3004                 TALLOC_FREE(result);
3005                 return status;
3006         }
3007
3008         /*
3009          * The credentials on a new netlogon pipe are the ones we are passed
3010          * in - copy them over
3011          */
3012         result->dc = netlogon_creds_copy(result, *pdc);
3013         if (result->dc == NULL) {
3014                 TALLOC_FREE(result);
3015                 return NT_STATUS_NO_MEMORY;
3016         }
3017
3018         DEBUG(10,("cli_rpc_pipe_open_schannel_with_key: opened pipe %s to machine %s "
3019                   "for domain %s and bound using schannel.\n",
3020                   get_pipe_name_from_syntax(talloc_tos(), interface),
3021                   cli->desthost, domain ));
3022
3023         *presult = result;
3024         return NT_STATUS_OK;
3025 }
3026
3027 /****************************************************************************
3028  Open a named pipe to an SMB server and bind using krb5 (bind type 16).
3029  The idea is this can be called with service_princ, username and password all
3030  NULL so long as the caller has a TGT.
3031  ****************************************************************************/
3032
3033 NTSTATUS cli_rpc_pipe_open_krb5(struct cli_state *cli,
3034                                 const struct ndr_syntax_id *interface,
3035                                 enum dcerpc_transport_t transport,
3036                                 enum dcerpc_AuthLevel auth_level,
3037                                 const char *server,
3038                                 const char *username,
3039                                 const char *password,
3040                                 struct rpc_pipe_client **presult)
3041 {
3042         struct rpc_pipe_client *result;
3043         struct pipe_auth_data *auth;
3044         struct gse_context *gse_ctx;
3045         NTSTATUS status;
3046
3047         status = cli_rpc_pipe_open(cli, transport, interface, &result);
3048         if (!NT_STATUS_IS_OK(status)) {
3049                 return status;
3050         }
3051
3052         auth = talloc(result, struct pipe_auth_data);
3053         if (auth == NULL) {
3054                 status = NT_STATUS_NO_MEMORY;
3055                 goto err_out;
3056         }
3057         auth->auth_type = DCERPC_AUTH_TYPE_KRB5;
3058         auth->auth_level = auth_level;
3059
3060         if (!username) {
3061                 username = "";
3062         }
3063         auth->user_name = talloc_strdup(auth, username);
3064         if (!auth->user_name) {
3065                 status = NT_STATUS_NO_MEMORY;
3066                 goto err_out;
3067         }
3068
3069         /* Fixme, should we fetch/set the Realm ? */
3070         auth->domain = talloc_strdup(auth, "");
3071         if (!auth->domain) {
3072                 status = NT_STATUS_NO_MEMORY;
3073                 goto err_out;
3074         }
3075
3076         status = gse_init_client(auth,
3077                                  (auth_level == DCERPC_AUTH_LEVEL_INTEGRITY),
3078                                  (auth_level == DCERPC_AUTH_LEVEL_PRIVACY),
3079                                  NULL, server, "cifs", username, password,
3080                                  GSS_C_DCE_STYLE, &gse_ctx);
3081         if (!NT_STATUS_IS_OK(status)) {
3082                 DEBUG(0, ("gse_init_client returned %s\n",
3083                           nt_errstr(status)));
3084                 goto err_out;
3085         }
3086         auth->auth_ctx = gse_ctx;
3087
3088         status = rpc_pipe_bind(result, auth);
3089         if (!NT_STATUS_IS_OK(status)) {
3090                 DEBUG(0, ("cli_rpc_pipe_bind failed with error %s\n",
3091                           nt_errstr(status)));
3092                 goto err_out;
3093         }
3094
3095         *presult = result;
3096         return NT_STATUS_OK;
3097
3098 err_out:
3099         TALLOC_FREE(result);
3100         return status;
3101 }
3102
3103 NTSTATUS cli_rpc_pipe_open_spnego_krb5(struct cli_state *cli,
3104                                         const struct ndr_syntax_id *interface,
3105                                         enum dcerpc_transport_t transport,
3106                                         enum dcerpc_AuthLevel auth_level,
3107                                         const char *server,
3108                                         const char *username,
3109                                         const char *password,
3110                                         struct rpc_pipe_client **presult)
3111 {
3112         struct rpc_pipe_client *result;
3113         struct pipe_auth_data *auth;
3114         struct spnego_context *spnego_ctx;
3115         NTSTATUS status;
3116
3117         status = cli_rpc_pipe_open(cli, transport, interface, &result);
3118         if (!NT_STATUS_IS_OK(status)) {
3119                 return status;
3120         }
3121
3122         auth = talloc(result, struct pipe_auth_data);
3123         if (auth == NULL) {
3124                 status = NT_STATUS_NO_MEMORY;
3125                 goto err_out;
3126         }
3127         auth->auth_type = DCERPC_AUTH_TYPE_SPNEGO;
3128         auth->auth_level = auth_level;
3129
3130         if (!username) {
3131                 username = "";
3132         }
3133         auth->user_name = talloc_strdup(auth, username);
3134         if (!auth->user_name) {
3135                 status = NT_STATUS_NO_MEMORY;
3136                 goto err_out;
3137         }
3138
3139         /* Fixme, should we fetch/set the Realm ? */
3140         auth->domain = talloc_strdup(auth, "");
3141         if (!auth->domain) {
3142                 status = NT_STATUS_NO_MEMORY;
3143                 goto err_out;
3144         }
3145
3146         status = spnego_gssapi_init_client(auth,
3147                                            (auth->auth_level ==
3148                                                 DCERPC_AUTH_LEVEL_INTEGRITY),
3149                                            (auth->auth_level ==
3150                                                 DCERPC_AUTH_LEVEL_PRIVACY),
3151                                            true,
3152                                            NULL, server, "cifs",
3153                                            username, password,
3154                                            &spnego_ctx);
3155         if (!NT_STATUS_IS_OK(status)) {
3156                 DEBUG(0, ("spnego_init_client returned %s\n",
3157                           nt_errstr(status)));
3158                 goto err_out;
3159         }
3160         auth->auth_ctx = spnego_ctx;
3161
3162         status = rpc_pipe_bind(result, auth);
3163         if (!NT_STATUS_IS_OK(status)) {
3164                 DEBUG(0, ("cli_rpc_pipe_bind failed with error %s\n",
3165                           nt_errstr(status)));
3166                 goto err_out;
3167         }
3168
3169         *presult = result;
3170         return NT_STATUS_OK;
3171
3172 err_out:
3173         TALLOC_FREE(result);
3174         return status;
3175 }
3176
3177 NTSTATUS cli_rpc_pipe_open_spnego_ntlmssp(struct cli_state *cli,
3178                                           const struct ndr_syntax_id *interface,
3179                                           enum dcerpc_transport_t transport,
3180                                           enum dcerpc_AuthLevel auth_level,
3181                                           const char *domain,
3182                                           const char *username,
3183                                           const char *password,
3184                                           struct rpc_pipe_client **presult)
3185 {
3186         struct rpc_pipe_client *result;
3187         struct pipe_auth_data *auth;
3188         struct spnego_context *spnego_ctx;
3189         NTSTATUS status;
3190
3191         status = cli_rpc_pipe_open(cli, transport, interface, &result);
3192         if (!NT_STATUS_IS_OK(status)) {
3193                 return status;
3194         }
3195
3196         auth = talloc(result, struct pipe_auth_data);
3197         if (auth == NULL) {
3198                 status = NT_STATUS_NO_MEMORY;
3199                 goto err_out;
3200         }
3201         auth->auth_type = DCERPC_AUTH_TYPE_SPNEGO;
3202         auth->auth_level = auth_level;
3203
3204         if (!username) {
3205                 username = "";
3206         }
3207         auth->user_name = talloc_strdup(auth, username);
3208         if (!auth->user_name) {
3209                 status = NT_STATUS_NO_MEMORY;
3210                 goto err_out;
3211         }
3212
3213         if (!domain) {
3214                 domain = "";
3215         }
3216         auth->domain = talloc_strdup(auth, domain);
3217         if (!auth->domain) {
3218                 status = NT_STATUS_NO_MEMORY;
3219                 goto err_out;
3220         }
3221
3222         status = spnego_ntlmssp_init_client(auth,
3223                                             (auth->auth_level ==
3224                                                 DCERPC_AUTH_LEVEL_INTEGRITY),
3225                                             (auth->auth_level ==
3226                                                 DCERPC_AUTH_LEVEL_PRIVACY),
3227                                             true,
3228                                             domain, username, password,
3229                                             &spnego_ctx);
3230         if (!NT_STATUS_IS_OK(status)) {
3231                 DEBUG(0, ("spnego_init_client returned %s\n",
3232                           nt_errstr(status)));
3233                 goto err_out;
3234         }
3235         auth->auth_ctx = spnego_ctx;
3236
3237         status = rpc_pipe_bind(result, auth);
3238         if (!NT_STATUS_IS_OK(status)) {
3239                 DEBUG(0, ("cli_rpc_pipe_bind failed with error %s\n",
3240                           nt_errstr(status)));
3241                 goto err_out;
3242         }
3243
3244         *presult = result;
3245         return NT_STATUS_OK;
3246
3247 err_out:
3248         TALLOC_FREE(result);
3249         return status;
3250 }
3251
3252 NTSTATUS cli_get_session_key(TALLOC_CTX *mem_ctx,
3253                              struct rpc_pipe_client *cli,
3254                              DATA_BLOB *session_key)
3255 {
3256         struct pipe_auth_data *a;
3257         struct schannel_state *schannel_auth;
3258         struct auth_ntlmssp_state *ntlmssp_ctx;
3259         struct spnego_context *spnego_ctx;
3260         struct gse_context *gse_ctx;
3261         DATA_BLOB sk = data_blob_null;
3262         bool make_dup = false;
3263
3264         if (!session_key || !cli) {
3265                 return NT_STATUS_INVALID_PARAMETER;
3266         }
3267
3268         a = cli->auth;
3269
3270         if (a == NULL) {
3271                 return NT_STATUS_INVALID_PARAMETER;
3272         }
3273
3274         switch (cli->auth->auth_type) {
3275         case DCERPC_AUTH_TYPE_SCHANNEL:
3276                 schannel_auth = talloc_get_type_abort(a->auth_ctx,
3277                                                       struct schannel_state);
3278                 sk = data_blob_const(schannel_auth->creds->session_key, 16);
3279                 make_dup = true;
3280                 break;
3281         case DCERPC_AUTH_TYPE_SPNEGO:
3282                 spnego_ctx = talloc_get_type_abort(a->auth_ctx,
3283                                                    struct spnego_context);
3284                 sk = spnego_get_session_key(mem_ctx, spnego_ctx);
3285                 make_dup = false;
3286                 break;
3287         case DCERPC_AUTH_TYPE_NTLMSSP:
3288                 ntlmssp_ctx = talloc_get_type_abort(a->auth_ctx,
3289                                                     struct auth_ntlmssp_state);
3290                 sk = auth_ntlmssp_get_session_key(ntlmssp_ctx);
3291                 make_dup = true;
3292                 break;
3293         case DCERPC_AUTH_TYPE_KRB5:
3294                 gse_ctx = talloc_get_type_abort(a->auth_ctx,
3295                                                 struct gse_context);
3296                 sk = gse_get_session_key(mem_ctx, gse_ctx);
3297                 make_dup = false;
3298                 break;
3299         case DCERPC_AUTH_TYPE_NCALRPC_AS_SYSTEM:
3300         case DCERPC_AUTH_TYPE_NONE:
3301                 sk = data_blob_const(a->user_session_key.data,
3302                                      a->user_session_key.length);
3303                 make_dup = true;
3304                 break;
3305         default:
3306                 break;
3307         }
3308
3309         if (!sk.data) {
3310                 return NT_STATUS_NO_USER_SESSION_KEY;
3311         }
3312
3313         if (make_dup) {
3314                 *session_key = data_blob_dup_talloc(mem_ctx, &sk);
3315         } else {
3316                 *session_key = sk;
3317         }
3318
3319         return NT_STATUS_OK;
3320 }