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