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