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