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