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