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