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