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