s3-dcerpc: Use dcerpc_check_auth in client code too
[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                                     uint32 rpc_call_id,
1202                                     const struct ndr_syntax_id *abstract,
1203                                     const struct ndr_syntax_id *transfer,
1204                                     enum pipe_auth_type auth_type,
1205                                     enum dcerpc_AuthLevel auth_level,
1206                                     DATA_BLOB *rpc_out)
1207 {
1208         DATA_BLOB auth_info = data_blob_null;
1209         NTSTATUS ret = NT_STATUS_OK;
1210
1211         switch (auth_type) {
1212                 case PIPE_AUTH_TYPE_SCHANNEL:
1213                         ret = create_schannel_auth_rpc_bind_req(cli, auth_level, &auth_info);
1214                         if (!NT_STATUS_IS_OK(ret)) {
1215                                 return ret;
1216                         }
1217                         break;
1218
1219                 case PIPE_AUTH_TYPE_NTLMSSP:
1220                         ret = create_ntlmssp_auth_rpc_bind_req(cli, auth_level, &auth_info);
1221                         if (!NT_STATUS_IS_OK(ret)) {
1222                                 return ret;
1223                         }
1224                         break;
1225
1226                 case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP:
1227                         ret = create_spnego_ntlmssp_auth_rpc_bind_req(cli, auth_level, &auth_info);
1228                         if (!NT_STATUS_IS_OK(ret)) {
1229                                 return ret;
1230                         }
1231                         break;
1232
1233                 case PIPE_AUTH_TYPE_KRB5:
1234                         ret = create_krb5_auth_bind_req(cli, auth_level, &auth_info);
1235                         if (!NT_STATUS_IS_OK(ret)) {
1236                                 return ret;
1237                         }
1238                         break;
1239
1240                 case PIPE_AUTH_TYPE_NONE:
1241                         break;
1242
1243                 default:
1244                         /* "Can't" happen. */
1245                         return NT_STATUS_INVALID_INFO_CLASS;
1246         }
1247
1248         ret = create_bind_or_alt_ctx_internal(mem_ctx,
1249                                               DCERPC_PKT_BIND,
1250                                               rpc_call_id,
1251                                               abstract,
1252                                               transfer,
1253                                               &auth_info,
1254                                               rpc_out);
1255         return ret;
1256 }
1257
1258 /*******************************************************************
1259  Calculate how much data we're going to send in this packet, also
1260  work out any sign/seal padding length.
1261  ********************************************************************/
1262
1263 static uint32 calculate_data_len_tosend(struct rpc_pipe_client *cli,
1264                                         uint32 data_left,
1265                                         uint16 *p_frag_len,
1266                                         uint16 *p_auth_len,
1267                                         uint32 *p_ss_padding)
1268 {
1269         uint32 data_space, data_len;
1270
1271 #if 0
1272         if ((data_left > 0) && (sys_random() % 2)) {
1273                 data_left = MAX(data_left/2, 1);
1274         }
1275 #endif
1276
1277         switch (cli->auth->auth_level) {
1278                 case DCERPC_AUTH_LEVEL_NONE:
1279                 case DCERPC_AUTH_LEVEL_CONNECT:
1280                         data_space = cli->max_xmit_frag - DCERPC_REQUEST_LENGTH;
1281                         data_len = MIN(data_space, data_left);
1282                         *p_ss_padding = 0;
1283                         *p_auth_len = 0;
1284                         *p_frag_len = DCERPC_REQUEST_LENGTH + data_len;
1285                         return data_len;
1286
1287                 case DCERPC_AUTH_LEVEL_INTEGRITY:
1288                 case DCERPC_AUTH_LEVEL_PRIVACY:
1289                         /* Treat the same for all authenticated rpc requests. */
1290                         switch(cli->auth->auth_type) {
1291                                 case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP:
1292                                 case PIPE_AUTH_TYPE_NTLMSSP:
1293                                         *p_auth_len = NTLMSSP_SIG_SIZE;
1294                                         break;
1295                                 case PIPE_AUTH_TYPE_SCHANNEL:
1296                                         *p_auth_len = NL_AUTH_SIGNATURE_SIZE;
1297                                         break;
1298                                 default:
1299                                         smb_panic("bad auth type");
1300                                         break;
1301                         }
1302
1303                         data_space = cli->max_xmit_frag
1304                                         - DCERPC_REQUEST_LENGTH
1305                                         - DCERPC_AUTH_TRAILER_LENGTH
1306                                         - *p_auth_len;
1307
1308                         data_len = MIN(data_space, data_left);
1309                         *p_ss_padding = 0;
1310                         if (data_len % CLIENT_NDR_PADDING_SIZE) {
1311                                 *p_ss_padding = CLIENT_NDR_PADDING_SIZE - (data_len % CLIENT_NDR_PADDING_SIZE);
1312                         }
1313                         *p_frag_len = DCERPC_REQUEST_LENGTH
1314                                         + data_len + *p_ss_padding
1315                                         + DCERPC_AUTH_TRAILER_LENGTH
1316                                         + *p_auth_len;
1317                         return data_len;
1318
1319                 default:
1320                         smb_panic("bad auth level");
1321                         /* Notreached. */
1322                         return 0;
1323         }
1324 }
1325
1326 /*******************************************************************
1327  External interface.
1328  Does an rpc request on a pipe. Incoming data is NDR encoded in in_data.
1329  Reply is NDR encoded in out_data. Splits the data stream into RPC PDU's
1330  and deals with signing/sealing details.
1331  ********************************************************************/
1332
1333 struct rpc_api_pipe_req_state {
1334         struct event_context *ev;
1335         struct rpc_pipe_client *cli;
1336         uint8_t op_num;
1337         uint32_t call_id;
1338         DATA_BLOB *req_data;
1339         uint32_t req_data_sent;
1340         DATA_BLOB rpc_out;
1341         DATA_BLOB reply_pdu;
1342 };
1343
1344 static void rpc_api_pipe_req_write_done(struct tevent_req *subreq);
1345 static void rpc_api_pipe_req_done(struct tevent_req *subreq);
1346 static NTSTATUS prepare_next_frag(struct rpc_api_pipe_req_state *state,
1347                                   bool *is_last_frag);
1348
1349 struct tevent_req *rpc_api_pipe_req_send(TALLOC_CTX *mem_ctx,
1350                                          struct event_context *ev,
1351                                          struct rpc_pipe_client *cli,
1352                                          uint8_t op_num,
1353                                          DATA_BLOB *req_data)
1354 {
1355         struct tevent_req *req, *subreq;
1356         struct rpc_api_pipe_req_state *state;
1357         NTSTATUS status;
1358         bool is_last_frag;
1359
1360         req = tevent_req_create(mem_ctx, &state,
1361                                 struct rpc_api_pipe_req_state);
1362         if (req == NULL) {
1363                 return NULL;
1364         }
1365         state->ev = ev;
1366         state->cli = cli;
1367         state->op_num = op_num;
1368         state->req_data = req_data;
1369         state->req_data_sent = 0;
1370         state->call_id = get_rpc_call_id();
1371         state->reply_pdu = data_blob_null;
1372         state->rpc_out = data_blob_null;
1373
1374         if (cli->max_xmit_frag < DCERPC_REQUEST_LENGTH
1375                                         + RPC_MAX_SIGN_SIZE) {
1376                 /* Server is screwed up ! */
1377                 status = NT_STATUS_INVALID_PARAMETER;
1378                 goto post_status;
1379         }
1380
1381         status = prepare_next_frag(state, &is_last_frag);
1382         if (!NT_STATUS_IS_OK(status)) {
1383                 goto post_status;
1384         }
1385
1386         if (is_last_frag) {
1387                 subreq = rpc_api_pipe_send(state, ev, state->cli,
1388                                            &state->rpc_out,
1389                                            DCERPC_PKT_RESPONSE);
1390                 if (subreq == NULL) {
1391                         goto fail;
1392                 }
1393                 tevent_req_set_callback(subreq, rpc_api_pipe_req_done, req);
1394         } else {
1395                 subreq = rpc_write_send(state, ev, cli->transport,
1396                                         state->rpc_out.data,
1397                                         state->rpc_out.length);
1398                 if (subreq == NULL) {
1399                         goto fail;
1400                 }
1401                 tevent_req_set_callback(subreq, rpc_api_pipe_req_write_done,
1402                                         req);
1403         }
1404         return req;
1405
1406  post_status:
1407         tevent_req_nterror(req, status);
1408         return tevent_req_post(req, ev);
1409  fail:
1410         TALLOC_FREE(req);
1411         return NULL;
1412 }
1413
1414 static NTSTATUS prepare_next_frag(struct rpc_api_pipe_req_state *state,
1415                                   bool *is_last_frag)
1416 {
1417         uint32_t data_sent_thistime;
1418         uint16_t auth_len;
1419         uint16_t frag_len;
1420         uint8_t flags = 0;
1421         uint32_t ss_padding;
1422         uint32_t data_left;
1423         NTSTATUS status;
1424         union dcerpc_payload u;
1425
1426         data_left = state->req_data->length - state->req_data_sent;
1427
1428         data_sent_thistime = calculate_data_len_tosend(
1429                 state->cli, data_left, &frag_len, &auth_len, &ss_padding);
1430
1431         if (state->req_data_sent == 0) {
1432                 flags = DCERPC_PFC_FLAG_FIRST;
1433         }
1434
1435         if (data_sent_thistime == data_left) {
1436                 flags |= DCERPC_PFC_FLAG_LAST;
1437         }
1438
1439         data_blob_free(&state->rpc_out);
1440
1441         ZERO_STRUCT(u.request);
1442
1443         u.request.alloc_hint    = state->req_data->length;
1444         u.request.context_id    = 0;
1445         u.request.opnum         = state->op_num;
1446
1447         status = dcerpc_push_ncacn_packet(state,
1448                                           DCERPC_PKT_REQUEST,
1449                                           flags,
1450                                           auth_len,
1451                                           state->call_id,
1452                                           &u,
1453                                           &state->rpc_out);
1454         if (!NT_STATUS_IS_OK(status)) {
1455                 return status;
1456         }
1457
1458         /* explicitly set frag_len here as dcerpc_push_ncacn_packet() can't
1459          * compute it right for requests because the auth trailer is missing
1460          * at this stage */
1461         dcerpc_set_frag_length(&state->rpc_out, frag_len);
1462
1463         /* Copy in the data. */
1464         if (!data_blob_append(NULL, &state->rpc_out,
1465                                 state->req_data->data + state->req_data_sent,
1466                                 data_sent_thistime)) {
1467                 return NT_STATUS_NO_MEMORY;
1468         }
1469
1470         status = dcerpc_add_auth_footer(state->cli->auth, ss_padding,
1471                                         &state->rpc_out);
1472         if (!NT_STATUS_IS_OK(status)) {
1473                 return status;
1474         }
1475
1476         state->req_data_sent += data_sent_thistime;
1477         *is_last_frag = ((flags & DCERPC_PFC_FLAG_LAST) != 0);
1478
1479         return status;
1480 }
1481
1482 static void rpc_api_pipe_req_write_done(struct tevent_req *subreq)
1483 {
1484         struct tevent_req *req = tevent_req_callback_data(
1485                 subreq, struct tevent_req);
1486         struct rpc_api_pipe_req_state *state = tevent_req_data(
1487                 req, struct rpc_api_pipe_req_state);
1488         NTSTATUS status;
1489         bool is_last_frag;
1490
1491         status = rpc_write_recv(subreq);
1492         TALLOC_FREE(subreq);
1493         if (!NT_STATUS_IS_OK(status)) {
1494                 tevent_req_nterror(req, status);
1495                 return;
1496         }
1497
1498         status = prepare_next_frag(state, &is_last_frag);
1499         if (!NT_STATUS_IS_OK(status)) {
1500                 tevent_req_nterror(req, status);
1501                 return;
1502         }
1503
1504         if (is_last_frag) {
1505                 subreq = rpc_api_pipe_send(state, state->ev, state->cli,
1506                                            &state->rpc_out,
1507                                            DCERPC_PKT_RESPONSE);
1508                 if (tevent_req_nomem(subreq, req)) {
1509                         return;
1510                 }
1511                 tevent_req_set_callback(subreq, rpc_api_pipe_req_done, req);
1512         } else {
1513                 subreq = rpc_write_send(state, state->ev,
1514                                         state->cli->transport,
1515                                         state->rpc_out.data,
1516                                         state->rpc_out.length);
1517                 if (tevent_req_nomem(subreq, req)) {
1518                         return;
1519                 }
1520                 tevent_req_set_callback(subreq, rpc_api_pipe_req_write_done,
1521                                         req);
1522         }
1523 }
1524
1525 static void rpc_api_pipe_req_done(struct tevent_req *subreq)
1526 {
1527         struct tevent_req *req = tevent_req_callback_data(
1528                 subreq, struct tevent_req);
1529         struct rpc_api_pipe_req_state *state = tevent_req_data(
1530                 req, struct rpc_api_pipe_req_state);
1531         NTSTATUS status;
1532
1533         status = rpc_api_pipe_recv(subreq, state, NULL, &state->reply_pdu);
1534         TALLOC_FREE(subreq);
1535         if (!NT_STATUS_IS_OK(status)) {
1536                 tevent_req_nterror(req, status);
1537                 return;
1538         }
1539         tevent_req_done(req);
1540 }
1541
1542 NTSTATUS rpc_api_pipe_req_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
1543                                DATA_BLOB *reply_pdu)
1544 {
1545         struct rpc_api_pipe_req_state *state = tevent_req_data(
1546                 req, struct rpc_api_pipe_req_state);
1547         NTSTATUS status;
1548
1549         if (tevent_req_is_nterror(req, &status)) {
1550                 /*
1551                  * We always have to initialize to reply pdu, even if there is
1552                  * none. The rpccli_* caller routines expect this.
1553                  */
1554                 *reply_pdu = data_blob_null;
1555                 return status;
1556         }
1557
1558         /* return data to caller and assign it ownership of memory */
1559         reply_pdu->data = talloc_move(mem_ctx, &state->reply_pdu.data);
1560         reply_pdu->length = state->reply_pdu.length;
1561         state->reply_pdu.length = 0;
1562
1563         return NT_STATUS_OK;
1564 }
1565
1566 #if 0
1567 /****************************************************************************
1568  Set the handle state.
1569 ****************************************************************************/
1570
1571 static bool rpc_pipe_set_hnd_state(struct rpc_pipe_client *cli,
1572                                    const char *pipe_name, uint16 device_state)
1573 {
1574         bool state_set = False;
1575         char param[2];
1576         uint16 setup[2]; /* only need 2 uint16 setup parameters */
1577         char *rparam = NULL;
1578         char *rdata = NULL;
1579         uint32 rparam_len, rdata_len;
1580
1581         if (pipe_name == NULL)
1582                 return False;
1583
1584         DEBUG(5,("Set Handle state Pipe[%x]: %s - device state:%x\n",
1585                  cli->fnum, pipe_name, device_state));
1586
1587         /* create parameters: device state */
1588         SSVAL(param, 0, device_state);
1589
1590         /* create setup parameters. */
1591         setup[0] = 0x0001; 
1592         setup[1] = cli->fnum; /* pipe file handle.  got this from an SMBOpenX. */
1593
1594         /* send the data on \PIPE\ */
1595         if (cli_api_pipe(cli->cli, "\\PIPE\\",
1596                     setup, 2, 0,                /* setup, length, max */
1597                     param, 2, 0,                /* param, length, max */
1598                     NULL, 0, 1024,              /* data, length, max */
1599                     &rparam, &rparam_len,        /* return param, length */
1600                     &rdata, &rdata_len))         /* return data, length */
1601         {
1602                 DEBUG(5, ("Set Handle state: return OK\n"));
1603                 state_set = True;
1604         }
1605
1606         SAFE_FREE(rparam);
1607         SAFE_FREE(rdata);
1608
1609         return state_set;
1610 }
1611 #endif
1612
1613 /****************************************************************************
1614  Check the rpc bind acknowledge response.
1615 ****************************************************************************/
1616
1617 static bool check_bind_response(const struct dcerpc_bind_ack *r,
1618                                 const struct ndr_syntax_id *transfer)
1619 {
1620         struct dcerpc_ack_ctx ctx;
1621
1622         if (r->secondary_address_size == 0) {
1623                 DEBUG(4,("Ignoring length check -- ASU bug (server didn't fill in the pipe name correctly)"));
1624         }
1625
1626         if (r->num_results < 1 || !r->ctx_list) {
1627                 return false;
1628         }
1629
1630         ctx = r->ctx_list[0];
1631
1632         /* check the transfer syntax */
1633         if ((ctx.syntax.if_version != transfer->if_version) ||
1634              (memcmp(&ctx.syntax.uuid, &transfer->uuid, sizeof(transfer->uuid)) !=0)) {
1635                 DEBUG(2,("bind_rpc_pipe: transfer syntax differs\n"));
1636                 return False;
1637         }
1638
1639         if (r->num_results != 0x1 || ctx.result != 0) {
1640                 DEBUG(2,("bind_rpc_pipe: bind denied results: %d reason: %x\n",
1641                           r->num_results, ctx.reason));
1642         }
1643
1644         DEBUG(5,("check_bind_response: accepted!\n"));
1645         return True;
1646 }
1647
1648 /*******************************************************************
1649  Creates a DCE/RPC bind authentication response.
1650  This is the packet that is sent back to the server once we
1651  have received a BIND-ACK, to finish the third leg of
1652  the authentication handshake.
1653  ********************************************************************/
1654
1655 static NTSTATUS create_rpc_bind_auth3(TALLOC_CTX *mem_ctx,
1656                                 struct rpc_pipe_client *cli,
1657                                 uint32 rpc_call_id,
1658                                 enum pipe_auth_type auth_type,
1659                                 enum dcerpc_AuthLevel auth_level,
1660                                 DATA_BLOB *pauth_blob,
1661                                 DATA_BLOB *rpc_out)
1662 {
1663         NTSTATUS status;
1664         union dcerpc_payload u;
1665
1666         u.auth3._pad = 0;
1667
1668         status = dcerpc_push_dcerpc_auth(mem_ctx,
1669                         map_pipe_auth_type_to_rpc_auth_type(auth_type),
1670                                          auth_level,
1671                                          0, /* auth_pad_length */
1672                                          1, /* auth_context_id */
1673                                          pauth_blob,
1674                                          &u.auth3.auth_info);
1675         if (!NT_STATUS_IS_OK(status)) {
1676                 return status;
1677         }
1678
1679         status = dcerpc_push_ncacn_packet(mem_ctx,
1680                                           DCERPC_PKT_AUTH3,
1681                                           DCERPC_PFC_FLAG_FIRST |
1682                                           DCERPC_PFC_FLAG_LAST,
1683                                           pauth_blob->length,
1684                                           rpc_call_id,
1685                                           &u,
1686                                           rpc_out);
1687         data_blob_free(&u.auth3.auth_info);
1688         if (!NT_STATUS_IS_OK(status)) {
1689                 DEBUG(0,("create_bind_or_alt_ctx_internal: failed to marshall RPC_HDR_RB.\n"));
1690                 return status;
1691         }
1692
1693         return NT_STATUS_OK;
1694 }
1695
1696 /*******************************************************************
1697  Creates a DCE/RPC bind alter context authentication request which
1698  may contain a spnego auth blobl
1699  ********************************************************************/
1700
1701 static NTSTATUS create_rpc_alter_context(TALLOC_CTX *mem_ctx,
1702                                         uint32 rpc_call_id,
1703                                         const struct ndr_syntax_id *abstract,
1704                                         const struct ndr_syntax_id *transfer,
1705                                         enum dcerpc_AuthLevel auth_level,
1706                                         const DATA_BLOB *pauth_blob, /* spnego auth blob already created. */
1707                                         DATA_BLOB *rpc_out)
1708 {
1709         DATA_BLOB auth_info;
1710         NTSTATUS status;
1711
1712         status = dcerpc_push_dcerpc_auth(mem_ctx,
1713                                          DCERPC_AUTH_TYPE_SPNEGO,
1714                                          auth_level,
1715                                          0, /* auth_pad_length */
1716                                          1, /* auth_context_id */
1717                                          pauth_blob,
1718                                          &auth_info);
1719         if (!NT_STATUS_IS_OK(status)) {
1720                 return status;
1721         }
1722
1723         status = create_bind_or_alt_ctx_internal(mem_ctx,
1724                                                  DCERPC_PKT_ALTER,
1725                                                  rpc_call_id,
1726                                                  abstract,
1727                                                  transfer,
1728                                                  &auth_info,
1729                                                  rpc_out);
1730         data_blob_free(&auth_info);
1731         return status;
1732 }
1733
1734 /****************************************************************************
1735  Do an rpc bind.
1736 ****************************************************************************/
1737
1738 struct rpc_pipe_bind_state {
1739         struct event_context *ev;
1740         struct rpc_pipe_client *cli;
1741         DATA_BLOB rpc_out;
1742         uint32_t rpc_call_id;
1743 };
1744
1745 static void rpc_pipe_bind_step_one_done(struct tevent_req *subreq);
1746 static NTSTATUS rpc_finish_auth3_bind_send(struct tevent_req *req,
1747                                            struct rpc_pipe_bind_state *state,
1748                                            struct ncacn_packet *r);
1749 static void rpc_bind_auth3_write_done(struct tevent_req *subreq);
1750 static NTSTATUS rpc_finish_spnego_ntlmssp_bind_send(struct tevent_req *req,
1751                                                     struct rpc_pipe_bind_state *state,
1752                                                     struct ncacn_packet *r,
1753                                                     DATA_BLOB *reply_pdu);
1754 static void rpc_bind_ntlmssp_api_done(struct tevent_req *subreq);
1755
1756 struct tevent_req *rpc_pipe_bind_send(TALLOC_CTX *mem_ctx,
1757                                       struct event_context *ev,
1758                                       struct rpc_pipe_client *cli,
1759                                       struct pipe_auth_data *auth)
1760 {
1761         struct tevent_req *req, *subreq;
1762         struct rpc_pipe_bind_state *state;
1763         NTSTATUS status;
1764
1765         req = tevent_req_create(mem_ctx, &state, struct rpc_pipe_bind_state);
1766         if (req == NULL) {
1767                 return NULL;
1768         }
1769
1770         DEBUG(5,("Bind RPC Pipe: %s auth_type %u, auth_level %u\n",
1771                 rpccli_pipe_txt(talloc_tos(), cli),
1772                 (unsigned int)auth->auth_type,
1773                 (unsigned int)auth->auth_level ));
1774
1775         state->ev = ev;
1776         state->cli = cli;
1777         state->rpc_call_id = get_rpc_call_id();
1778         state->rpc_out = data_blob_null;
1779
1780         cli->auth = talloc_move(cli, &auth);
1781
1782         /* Marshall the outgoing data. */
1783         status = create_rpc_bind_req(state, cli,
1784                                      state->rpc_call_id,
1785                                      &cli->abstract_syntax,
1786                                      &cli->transfer_syntax,
1787                                      cli->auth->auth_type,
1788                                      cli->auth->auth_level,
1789                                      &state->rpc_out);
1790
1791         if (!NT_STATUS_IS_OK(status)) {
1792                 goto post_status;
1793         }
1794
1795         subreq = rpc_api_pipe_send(state, ev, cli, &state->rpc_out,
1796                                    DCERPC_PKT_BIND_ACK);
1797         if (subreq == NULL) {
1798                 goto fail;
1799         }
1800         tevent_req_set_callback(subreq, rpc_pipe_bind_step_one_done, req);
1801         return req;
1802
1803  post_status:
1804         tevent_req_nterror(req, status);
1805         return tevent_req_post(req, ev);
1806  fail:
1807         TALLOC_FREE(req);
1808         return NULL;
1809 }
1810
1811 static void rpc_pipe_bind_step_one_done(struct tevent_req *subreq)
1812 {
1813         struct tevent_req *req = tevent_req_callback_data(
1814                 subreq, struct tevent_req);
1815         struct rpc_pipe_bind_state *state = tevent_req_data(
1816                 req, struct rpc_pipe_bind_state);
1817         DATA_BLOB reply_pdu;
1818         struct ncacn_packet *pkt;
1819         NTSTATUS status;
1820
1821         status = rpc_api_pipe_recv(subreq, talloc_tos(), &pkt, &reply_pdu);
1822         TALLOC_FREE(subreq);
1823         if (!NT_STATUS_IS_OK(status)) {
1824                 DEBUG(3, ("rpc_pipe_bind: %s bind request returned %s\n",
1825                           rpccli_pipe_txt(talloc_tos(), state->cli),
1826                           nt_errstr(status)));
1827                 tevent_req_nterror(req, status);
1828                 return;
1829         }
1830
1831         if (!check_bind_response(&pkt->u.bind_ack, &state->cli->transfer_syntax)) {
1832                 DEBUG(2, ("rpc_pipe_bind: check_bind_response failed.\n"));
1833                 tevent_req_nterror(req, NT_STATUS_BUFFER_TOO_SMALL);
1834                 return;
1835         }
1836
1837         state->cli->max_xmit_frag = pkt->u.bind_ack.max_xmit_frag;
1838         state->cli->max_recv_frag = pkt->u.bind_ack.max_recv_frag;
1839
1840         /*
1841          * For authenticated binds we may need to do 3 or 4 leg binds.
1842          */
1843
1844         switch(state->cli->auth->auth_type) {
1845
1846         case PIPE_AUTH_TYPE_NONE:
1847         case PIPE_AUTH_TYPE_SCHANNEL:
1848                 /* Bind complete. */
1849                 tevent_req_done(req);
1850                 break;
1851
1852         case PIPE_AUTH_TYPE_NTLMSSP:
1853                 /* Need to send AUTH3 packet - no reply. */
1854                 status = rpc_finish_auth3_bind_send(req, state, pkt);
1855                 if (!NT_STATUS_IS_OK(status)) {
1856                         tevent_req_nterror(req, status);
1857                 }
1858                 break;
1859
1860         case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP:
1861                 /* Need to send alter context request and reply. */
1862                 status = rpc_finish_spnego_ntlmssp_bind_send(req, state, pkt,
1863                                                              &reply_pdu);
1864                 if (!NT_STATUS_IS_OK(status)) {
1865                         tevent_req_nterror(req, status);
1866                 }
1867                 break;
1868
1869         case PIPE_AUTH_TYPE_KRB5:
1870                 /* */
1871
1872         default:
1873                 DEBUG(0,("cli_finish_bind_auth: unknown auth type %u\n",
1874                          (unsigned int)state->cli->auth->auth_type));
1875                 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
1876         }
1877 }
1878
1879 static NTSTATUS rpc_finish_auth3_bind_send(struct tevent_req *req,
1880                                            struct rpc_pipe_bind_state *state,
1881                                            struct ncacn_packet *r)
1882 {
1883         DATA_BLOB client_reply = data_blob_null;
1884         struct dcerpc_auth auth;
1885         struct tevent_req *subreq;
1886         NTSTATUS status;
1887
1888         if ((r->auth_length == 0)
1889             || (r->frag_length < DCERPC_AUTH_TRAILER_LENGTH
1890                                         + r->auth_length)) {
1891                 return NT_STATUS_INVALID_PARAMETER;
1892         }
1893
1894         status = dcerpc_pull_dcerpc_auth(talloc_tos(),
1895                                          &r->u.bind_ack.auth_info,
1896                                          &auth, false);
1897         if (!NT_STATUS_IS_OK(status)) {
1898                 DEBUG(0, ("Failed to pull dcerpc auth: %s.\n",
1899                           nt_errstr(status)));
1900                 return status;
1901         }
1902
1903         /* TODO - check auth_type/auth_level match. */
1904
1905         status = auth_ntlmssp_update(state->cli->auth->a_u.auth_ntlmssp_state,
1906                                 auth.credentials, &client_reply);
1907
1908         if (!NT_STATUS_IS_OK(status)) {
1909                 DEBUG(0, ("rpc_finish_auth3_bind: NTLMSSP update using server "
1910                           "blob failed: %s.\n", nt_errstr(status)));
1911                 return status;
1912         }
1913
1914         data_blob_free(&state->rpc_out);
1915
1916         status = create_rpc_bind_auth3(state,
1917                                        state->cli, state->rpc_call_id,
1918                                        state->cli->auth->auth_type,
1919                                        state->cli->auth->auth_level,
1920                                        &client_reply, &state->rpc_out);
1921         data_blob_free(&client_reply);
1922
1923         if (!NT_STATUS_IS_OK(status)) {
1924                 return status;
1925         }
1926
1927         subreq = rpc_write_send(state, state->ev, state->cli->transport,
1928                                 state->rpc_out.data, state->rpc_out.length);
1929         if (subreq == NULL) {
1930                 return NT_STATUS_NO_MEMORY;
1931         }
1932         tevent_req_set_callback(subreq, rpc_bind_auth3_write_done, req);
1933         return NT_STATUS_OK;
1934 }
1935
1936 static void rpc_bind_auth3_write_done(struct tevent_req *subreq)
1937 {
1938         struct tevent_req *req = tevent_req_callback_data(
1939                 subreq, struct tevent_req);
1940         NTSTATUS status;
1941
1942         status = rpc_write_recv(subreq);
1943         TALLOC_FREE(subreq);
1944         if (!NT_STATUS_IS_OK(status)) {
1945                 tevent_req_nterror(req, status);
1946                 return;
1947         }
1948         tevent_req_done(req);
1949 }
1950
1951 static NTSTATUS rpc_finish_spnego_ntlmssp_bind_send(struct tevent_req *req,
1952                                                     struct rpc_pipe_bind_state *state,
1953                                                     struct ncacn_packet *r,
1954                                                     DATA_BLOB *reply_pdu)
1955 {
1956         DATA_BLOB server_ntlm_response = data_blob_null;
1957         DATA_BLOB client_reply = data_blob_null;
1958         DATA_BLOB tmp_blob = data_blob_null;
1959         struct dcerpc_auth auth_info;
1960         DATA_BLOB auth_blob;
1961         struct tevent_req *subreq;
1962         NTSTATUS status;
1963
1964         if ((r->auth_length == 0)
1965             || (r->frag_length < DCERPC_AUTH_TRAILER_LENGTH
1966                                         + r->auth_length)) {
1967                 return NT_STATUS_INVALID_PARAMETER;
1968         }
1969
1970         /* Process the returned NTLMSSP blob first. */
1971         auth_blob = data_blob_const(reply_pdu->data
1972                                         + r->frag_length
1973                                         - DCERPC_AUTH_TRAILER_LENGTH
1974                                         - r->auth_length,
1975                                     DCERPC_AUTH_TRAILER_LENGTH
1976                                         + r->auth_length);
1977
1978         status = dcerpc_pull_dcerpc_auth(state, &auth_blob, &auth_info, false);
1979         if (!NT_STATUS_IS_OK(status)) {
1980                 DEBUG(0, ("Failed to unmarshall dcerpc_auth.\n"));
1981                 return status;
1982         }
1983
1984         /*
1985          * The server might give us back two challenges - tmp_blob is for the
1986          * second.
1987          */
1988         if (!spnego_parse_challenge(state, auth_info.credentials,
1989                                     &server_ntlm_response, &tmp_blob)) {
1990                 data_blob_free(&server_ntlm_response);
1991                 data_blob_free(&tmp_blob);
1992                 return NT_STATUS_INVALID_PARAMETER;
1993         }
1994
1995         /* We're finished with the server spnego response and the tmp_blob. */
1996         data_blob_free(&tmp_blob);
1997
1998         status = auth_ntlmssp_update(state->cli->auth->a_u.auth_ntlmssp_state,
1999                                 server_ntlm_response, &client_reply);
2000
2001         /* Finished with the server_ntlm response */
2002         data_blob_free(&server_ntlm_response);
2003
2004         if (!NT_STATUS_IS_OK(status)) {
2005                 DEBUG(0, ("rpc_finish_spnego_ntlmssp_bind: NTLMSSP update "
2006                           "using server blob failed.\n"));
2007                 data_blob_free(&client_reply);
2008                 return status;
2009         }
2010
2011         /* SPNEGO wrap the client reply. */
2012         tmp_blob = spnego_gen_auth(state, client_reply);
2013         data_blob_free(&client_reply);
2014         client_reply = tmp_blob;
2015         tmp_blob = data_blob_null;
2016
2017         /* Now prepare the alter context pdu. */
2018         data_blob_free(&state->rpc_out);
2019
2020         status = create_rpc_alter_context(state,
2021                                           state->rpc_call_id,
2022                                           &state->cli->abstract_syntax,
2023                                           &state->cli->transfer_syntax,
2024                                           state->cli->auth->auth_level,
2025                                           &client_reply,
2026                                           &state->rpc_out);
2027         data_blob_free(&client_reply);
2028
2029         if (!NT_STATUS_IS_OK(status)) {
2030                 return status;
2031         }
2032
2033         subreq = rpc_api_pipe_send(state, state->ev, state->cli,
2034                                    &state->rpc_out, DCERPC_PKT_ALTER_RESP);
2035         if (subreq == NULL) {
2036                 return NT_STATUS_NO_MEMORY;
2037         }
2038         tevent_req_set_callback(subreq, rpc_bind_ntlmssp_api_done, req);
2039         return NT_STATUS_OK;
2040 }
2041
2042 static void rpc_bind_ntlmssp_api_done(struct tevent_req *subreq)
2043 {
2044         struct tevent_req *req = tevent_req_callback_data(
2045                 subreq, struct tevent_req);
2046         struct rpc_pipe_bind_state *state = tevent_req_data(
2047                 req, struct rpc_pipe_bind_state);
2048         DATA_BLOB tmp_blob = data_blob_null;
2049         struct ncacn_packet *pkt;
2050         struct dcerpc_auth auth;
2051         NTSTATUS status;
2052
2053         status = rpc_api_pipe_recv(subreq, talloc_tos(), &pkt, NULL);
2054         TALLOC_FREE(subreq);
2055         if (!NT_STATUS_IS_OK(status)) {
2056                 tevent_req_nterror(req, status);
2057                 return;
2058         }
2059
2060         status = dcerpc_pull_dcerpc_auth(pkt,
2061                                          &pkt->u.alter_resp.auth_info,
2062                                          &auth, false);
2063         if (!NT_STATUS_IS_OK(status)) {
2064                 tevent_req_nterror(req, status);
2065                 return;
2066         }
2067
2068         /* Check we got a valid auth response. */
2069         if (!spnego_parse_auth_response(talloc_tos(), auth.credentials,
2070                                         NT_STATUS_OK,
2071                                         OID_NTLMSSP, &tmp_blob)) {
2072                 data_blob_free(&tmp_blob);
2073                 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
2074                 return;
2075         }
2076
2077         data_blob_free(&tmp_blob);
2078
2079         DEBUG(5,("rpc_finish_spnego_ntlmssp_bind: alter context request to "
2080                  "%s.\n", rpccli_pipe_txt(talloc_tos(), state->cli)));
2081         tevent_req_done(req);
2082 }
2083
2084 NTSTATUS rpc_pipe_bind_recv(struct tevent_req *req)
2085 {
2086         return tevent_req_simple_recv_ntstatus(req);
2087 }
2088
2089 NTSTATUS rpc_pipe_bind(struct rpc_pipe_client *cli,
2090                        struct pipe_auth_data *auth)
2091 {
2092         TALLOC_CTX *frame = talloc_stackframe();
2093         struct event_context *ev;
2094         struct tevent_req *req;
2095         NTSTATUS status = NT_STATUS_OK;
2096
2097         ev = event_context_init(frame);
2098         if (ev == NULL) {
2099                 status = NT_STATUS_NO_MEMORY;
2100                 goto fail;
2101         }
2102
2103         req = rpc_pipe_bind_send(frame, ev, cli, auth);
2104         if (req == NULL) {
2105                 status = NT_STATUS_NO_MEMORY;
2106                 goto fail;
2107         }
2108
2109         if (!tevent_req_poll(req, ev)) {
2110                 status = map_nt_error_from_unix(errno);
2111                 goto fail;
2112         }
2113
2114         status = rpc_pipe_bind_recv(req);
2115  fail:
2116         TALLOC_FREE(frame);
2117         return status;
2118 }
2119
2120 #define RPCCLI_DEFAULT_TIMEOUT 10000 /* 10 seconds. */
2121
2122 unsigned int rpccli_set_timeout(struct rpc_pipe_client *rpc_cli,
2123                                 unsigned int timeout)
2124 {
2125         unsigned int old;
2126
2127         if (rpc_cli->transport == NULL) {
2128                 return RPCCLI_DEFAULT_TIMEOUT;
2129         }
2130
2131         if (rpc_cli->transport->set_timeout == NULL) {
2132                 return RPCCLI_DEFAULT_TIMEOUT;
2133         }
2134
2135         old = rpc_cli->transport->set_timeout(rpc_cli->transport->priv, timeout);
2136         if (old == 0) {
2137                 return RPCCLI_DEFAULT_TIMEOUT;
2138         }
2139
2140         return old;
2141 }
2142
2143 bool rpccli_is_connected(struct rpc_pipe_client *rpc_cli)
2144 {
2145         if (rpc_cli == NULL) {
2146                 return false;
2147         }
2148
2149         if (rpc_cli->transport == NULL) {
2150                 return false;
2151         }
2152
2153         return rpc_cli->transport->is_connected(rpc_cli->transport->priv);
2154 }
2155
2156 bool rpccli_get_pwd_hash(struct rpc_pipe_client *rpc_cli, uint8_t nt_hash[16])
2157 {
2158         struct cli_state *cli;
2159
2160         if ((rpc_cli->auth->auth_type == PIPE_AUTH_TYPE_NTLMSSP)
2161             || (rpc_cli->auth->auth_type == PIPE_AUTH_TYPE_SPNEGO_NTLMSSP)) {
2162                 memcpy(nt_hash, auth_ntlmssp_get_nt_hash(rpc_cli->auth->a_u.auth_ntlmssp_state), 16);
2163                 return true;
2164         }
2165
2166         cli = rpc_pipe_np_smb_conn(rpc_cli);
2167         if (cli == NULL) {
2168                 return false;
2169         }
2170         E_md4hash(cli->password ? cli->password : "", nt_hash);
2171         return true;
2172 }
2173
2174 NTSTATUS rpccli_anon_bind_data(TALLOC_CTX *mem_ctx,
2175                                struct pipe_auth_data **presult)
2176 {
2177         struct pipe_auth_data *result;
2178
2179         result = talloc(mem_ctx, struct pipe_auth_data);
2180         if (result == NULL) {
2181                 return NT_STATUS_NO_MEMORY;
2182         }
2183
2184         result->auth_type = PIPE_AUTH_TYPE_NONE;
2185         result->auth_level = DCERPC_AUTH_LEVEL_NONE;
2186
2187         result->user_name = talloc_strdup(result, "");
2188         result->domain = talloc_strdup(result, "");
2189         if ((result->user_name == NULL) || (result->domain == NULL)) {
2190                 TALLOC_FREE(result);
2191                 return NT_STATUS_NO_MEMORY;
2192         }
2193
2194         *presult = result;
2195         return NT_STATUS_OK;
2196 }
2197
2198 static int cli_auth_ntlmssp_data_destructor(struct pipe_auth_data *auth)
2199 {
2200         TALLOC_FREE(auth->a_u.auth_ntlmssp_state);
2201         return 0;
2202 }
2203
2204 static NTSTATUS rpccli_ntlmssp_bind_data(TALLOC_CTX *mem_ctx,
2205                                   enum pipe_auth_type auth_type,
2206                                   enum dcerpc_AuthLevel auth_level,
2207                                   const char *domain,
2208                                   const char *username,
2209                                   const char *password,
2210                                   struct pipe_auth_data **presult)
2211 {
2212         struct pipe_auth_data *result;
2213         NTSTATUS status;
2214
2215         result = talloc(mem_ctx, struct pipe_auth_data);
2216         if (result == NULL) {
2217                 return NT_STATUS_NO_MEMORY;
2218         }
2219
2220         result->auth_type = auth_type;
2221         result->auth_level = auth_level;
2222
2223         result->user_name = talloc_strdup(result, username);
2224         result->domain = talloc_strdup(result, domain);
2225         if ((result->user_name == NULL) || (result->domain == NULL)) {
2226                 status = NT_STATUS_NO_MEMORY;
2227                 goto fail;
2228         }
2229
2230         status = auth_ntlmssp_client_start(NULL,
2231                                       global_myname(),
2232                                       lp_workgroup(),
2233                                       lp_client_ntlmv2_auth(),
2234                                       &result->a_u.auth_ntlmssp_state);
2235         if (!NT_STATUS_IS_OK(status)) {
2236                 goto fail;
2237         }
2238
2239         talloc_set_destructor(result, cli_auth_ntlmssp_data_destructor);
2240
2241         status = auth_ntlmssp_set_username(result->a_u.auth_ntlmssp_state,
2242                                            username);
2243         if (!NT_STATUS_IS_OK(status)) {
2244                 goto fail;
2245         }
2246
2247         status = auth_ntlmssp_set_domain(result->a_u.auth_ntlmssp_state,
2248                                          domain);
2249         if (!NT_STATUS_IS_OK(status)) {
2250                 goto fail;
2251         }
2252
2253         status = auth_ntlmssp_set_password(result->a_u.auth_ntlmssp_state,
2254                                            password);
2255         if (!NT_STATUS_IS_OK(status)) {
2256                 goto fail;
2257         }
2258
2259         /*
2260          * Turn off sign+seal to allow selected auth level to turn it back on.
2261          */
2262         auth_ntlmssp_and_flags(result->a_u.auth_ntlmssp_state,
2263                                                 ~(NTLMSSP_NEGOTIATE_SIGN |
2264                                                   NTLMSSP_NEGOTIATE_SEAL));
2265
2266         if (auth_level == DCERPC_AUTH_LEVEL_INTEGRITY) {
2267                 auth_ntlmssp_or_flags(result->a_u.auth_ntlmssp_state,
2268                                                 NTLMSSP_NEGOTIATE_SIGN);
2269         } else if (auth_level == DCERPC_AUTH_LEVEL_PRIVACY) {
2270                 auth_ntlmssp_or_flags(result->a_u.auth_ntlmssp_state,
2271                                                 NTLMSSP_NEGOTIATE_SEAL |
2272                                                 NTLMSSP_NEGOTIATE_SIGN);
2273         }
2274
2275         *presult = result;
2276         return NT_STATUS_OK;
2277
2278  fail:
2279         TALLOC_FREE(result);
2280         return status;
2281 }
2282
2283 NTSTATUS rpccli_schannel_bind_data(TALLOC_CTX *mem_ctx, const char *domain,
2284                                    enum dcerpc_AuthLevel auth_level,
2285                                    struct netlogon_creds_CredentialState *creds,
2286                                    struct pipe_auth_data **presult)
2287 {
2288         struct pipe_auth_data *result;
2289
2290         result = talloc(mem_ctx, struct pipe_auth_data);
2291         if (result == NULL) {
2292                 return NT_STATUS_NO_MEMORY;
2293         }
2294
2295         result->auth_type = PIPE_AUTH_TYPE_SCHANNEL;
2296         result->auth_level = auth_level;
2297
2298         result->user_name = talloc_strdup(result, "");
2299         result->domain = talloc_strdup(result, domain);
2300         if ((result->user_name == NULL) || (result->domain == NULL)) {
2301                 goto fail;
2302         }
2303
2304         result->a_u.schannel_auth = talloc(result, struct schannel_state);
2305         if (result->a_u.schannel_auth == NULL) {
2306                 goto fail;
2307         }
2308
2309         result->a_u.schannel_auth->state = SCHANNEL_STATE_START;
2310         result->a_u.schannel_auth->seq_num = 0;
2311         result->a_u.schannel_auth->initiator = true;
2312         result->a_u.schannel_auth->creds = creds;
2313
2314         *presult = result;
2315         return NT_STATUS_OK;
2316
2317  fail:
2318         TALLOC_FREE(result);
2319         return NT_STATUS_NO_MEMORY;
2320 }
2321
2322 #ifdef HAVE_KRB5
2323 static int cli_auth_kerberos_data_destructor(struct kerberos_auth_struct *auth)
2324 {
2325         data_blob_free(&auth->session_key);
2326         return 0;
2327 }
2328 #endif
2329
2330 static NTSTATUS rpccli_kerberos_bind_data(TALLOC_CTX *mem_ctx,
2331                                    enum dcerpc_AuthLevel auth_level,
2332                                    const char *service_princ,
2333                                    const char *username,
2334                                    const char *password,
2335                                    struct pipe_auth_data **presult)
2336 {
2337 #ifdef HAVE_KRB5
2338         struct pipe_auth_data *result;
2339
2340         if ((username != NULL) && (password != NULL)) {
2341                 int ret = kerberos_kinit_password(username, password, 0, NULL);
2342                 if (ret != 0) {
2343                         return NT_STATUS_ACCESS_DENIED;
2344                 }
2345         }
2346
2347         result = talloc(mem_ctx, struct pipe_auth_data);
2348         if (result == NULL) {
2349                 return NT_STATUS_NO_MEMORY;
2350         }
2351
2352         result->auth_type = PIPE_AUTH_TYPE_KRB5;
2353         result->auth_level = auth_level;
2354
2355         /*
2356          * Username / domain need fixing!
2357          */
2358         result->user_name = talloc_strdup(result, "");
2359         result->domain = talloc_strdup(result, "");
2360         if ((result->user_name == NULL) || (result->domain == NULL)) {
2361                 goto fail;
2362         }
2363
2364         result->a_u.kerberos_auth = TALLOC_ZERO_P(
2365                 result, struct kerberos_auth_struct);
2366         if (result->a_u.kerberos_auth == NULL) {
2367                 goto fail;
2368         }
2369         talloc_set_destructor(result->a_u.kerberos_auth,
2370                               cli_auth_kerberos_data_destructor);
2371
2372         result->a_u.kerberos_auth->service_principal = talloc_strdup(
2373                 result, service_princ);
2374         if (result->a_u.kerberos_auth->service_principal == NULL) {
2375                 goto fail;
2376         }
2377
2378         *presult = result;
2379         return NT_STATUS_OK;
2380
2381  fail:
2382         TALLOC_FREE(result);
2383         return NT_STATUS_NO_MEMORY;
2384 #else
2385         return NT_STATUS_NOT_SUPPORTED;
2386 #endif
2387 }
2388
2389 /**
2390  * Create an rpc pipe client struct, connecting to a tcp port.
2391  */
2392 static NTSTATUS rpc_pipe_open_tcp_port(TALLOC_CTX *mem_ctx, const char *host,
2393                                        uint16_t port,
2394                                        const struct ndr_syntax_id *abstract_syntax,
2395                                        struct rpc_pipe_client **presult)
2396 {
2397         struct rpc_pipe_client *result;
2398         struct sockaddr_storage addr;
2399         NTSTATUS status;
2400         int fd;
2401
2402         result = TALLOC_ZERO_P(mem_ctx, struct rpc_pipe_client);
2403         if (result == NULL) {
2404                 return NT_STATUS_NO_MEMORY;
2405         }
2406
2407         result->abstract_syntax = *abstract_syntax;
2408         result->transfer_syntax = ndr_transfer_syntax;
2409         result->dispatch = cli_do_rpc_ndr;
2410         result->dispatch_send = cli_do_rpc_ndr_send;
2411         result->dispatch_recv = cli_do_rpc_ndr_recv;
2412
2413         result->desthost = talloc_strdup(result, host);
2414         result->srv_name_slash = talloc_asprintf_strupper_m(
2415                 result, "\\\\%s", result->desthost);
2416         if ((result->desthost == NULL) || (result->srv_name_slash == NULL)) {
2417                 status = NT_STATUS_NO_MEMORY;
2418                 goto fail;
2419         }
2420
2421         result->max_xmit_frag = RPC_MAX_PDU_FRAG_LEN;
2422         result->max_recv_frag = RPC_MAX_PDU_FRAG_LEN;
2423
2424         if (!resolve_name(host, &addr, 0, false)) {
2425                 status = NT_STATUS_NOT_FOUND;
2426                 goto fail;
2427         }
2428
2429         status = open_socket_out(&addr, port, 60, &fd);
2430         if (!NT_STATUS_IS_OK(status)) {
2431                 goto fail;
2432         }
2433         set_socket_options(fd, lp_socket_options());
2434
2435         status = rpc_transport_sock_init(result, fd, &result->transport);
2436         if (!NT_STATUS_IS_OK(status)) {
2437                 close(fd);
2438                 goto fail;
2439         }
2440
2441         result->transport->transport = NCACN_IP_TCP;
2442
2443         *presult = result;
2444         return NT_STATUS_OK;
2445
2446  fail:
2447         TALLOC_FREE(result);
2448         return status;
2449 }
2450
2451 /**
2452  * Determine the tcp port on which a dcerpc interface is listening
2453  * for the ncacn_ip_tcp transport via the endpoint mapper of the
2454  * target host.
2455  */
2456 static NTSTATUS rpc_pipe_get_tcp_port(const char *host,
2457                                       const struct ndr_syntax_id *abstract_syntax,
2458                                       uint16_t *pport)
2459 {
2460         NTSTATUS status;
2461         struct rpc_pipe_client *epm_pipe = NULL;
2462         struct pipe_auth_data *auth = NULL;
2463         struct dcerpc_binding *map_binding = NULL;
2464         struct dcerpc_binding *res_binding = NULL;
2465         struct epm_twr_t *map_tower = NULL;
2466         struct epm_twr_t *res_towers = NULL;
2467         struct policy_handle *entry_handle = NULL;
2468         uint32_t num_towers = 0;
2469         uint32_t max_towers = 1;
2470         struct epm_twr_p_t towers;
2471         TALLOC_CTX *tmp_ctx = talloc_stackframe();
2472
2473         if (pport == NULL) {
2474                 status = NT_STATUS_INVALID_PARAMETER;
2475                 goto done;
2476         }
2477
2478         /* open the connection to the endpoint mapper */
2479         status = rpc_pipe_open_tcp_port(tmp_ctx, host, 135,
2480                                         &ndr_table_epmapper.syntax_id,
2481                                         &epm_pipe);
2482
2483         if (!NT_STATUS_IS_OK(status)) {
2484                 goto done;
2485         }
2486
2487         status = rpccli_anon_bind_data(tmp_ctx, &auth);
2488         if (!NT_STATUS_IS_OK(status)) {
2489                 goto done;
2490         }
2491
2492         status = rpc_pipe_bind(epm_pipe, auth);
2493         if (!NT_STATUS_IS_OK(status)) {
2494                 goto done;
2495         }
2496
2497         /* create tower for asking the epmapper */
2498
2499         map_binding = TALLOC_ZERO_P(tmp_ctx, struct dcerpc_binding);
2500         if (map_binding == NULL) {
2501                 status = NT_STATUS_NO_MEMORY;
2502                 goto done;
2503         }
2504
2505         map_binding->transport = NCACN_IP_TCP;
2506         map_binding->object = *abstract_syntax;
2507         map_binding->host = host; /* needed? */
2508         map_binding->endpoint = "0"; /* correct? needed? */
2509
2510         map_tower = TALLOC_ZERO_P(tmp_ctx, struct epm_twr_t);
2511         if (map_tower == NULL) {
2512                 status = NT_STATUS_NO_MEMORY;
2513                 goto done;
2514         }
2515
2516         status = dcerpc_binding_build_tower(tmp_ctx, map_binding,
2517                                             &(map_tower->tower));
2518         if (!NT_STATUS_IS_OK(status)) {
2519                 goto done;
2520         }
2521
2522         /* allocate further parameters for the epm_Map call */
2523
2524         res_towers = TALLOC_ARRAY(tmp_ctx, struct epm_twr_t, max_towers);
2525         if (res_towers == NULL) {
2526                 status = NT_STATUS_NO_MEMORY;
2527                 goto done;
2528         }
2529         towers.twr = res_towers;
2530
2531         entry_handle = TALLOC_ZERO_P(tmp_ctx, struct policy_handle);
2532         if (entry_handle == NULL) {
2533                 status = NT_STATUS_NO_MEMORY;
2534                 goto done;
2535         }
2536
2537         /* ask the endpoint mapper for the port */
2538
2539         status = rpccli_epm_Map(epm_pipe,
2540                                 tmp_ctx,
2541                                 CONST_DISCARD(struct GUID *,
2542                                               &(abstract_syntax->uuid)),
2543                                 map_tower,
2544                                 entry_handle,
2545                                 max_towers,
2546                                 &num_towers,
2547                                 &towers);
2548
2549         if (!NT_STATUS_IS_OK(status)) {
2550                 goto done;
2551         }
2552
2553         if (num_towers != 1) {
2554                 status = NT_STATUS_UNSUCCESSFUL;
2555                 goto done;
2556         }
2557
2558         /* extract the port from the answer */
2559
2560         status = dcerpc_binding_from_tower(tmp_ctx,
2561                                            &(towers.twr->tower),
2562                                            &res_binding);
2563         if (!NT_STATUS_IS_OK(status)) {
2564                 goto done;
2565         }
2566
2567         /* are further checks here necessary? */
2568         if (res_binding->transport != NCACN_IP_TCP) {
2569                 status = NT_STATUS_UNSUCCESSFUL;
2570                 goto done;
2571         }
2572
2573         *pport = (uint16_t)atoi(res_binding->endpoint);
2574
2575 done:
2576         TALLOC_FREE(tmp_ctx);
2577         return status;
2578 }
2579
2580 /**
2581  * Create a rpc pipe client struct, connecting to a host via tcp.
2582  * The port is determined by asking the endpoint mapper on the given
2583  * host.
2584  */
2585 NTSTATUS rpc_pipe_open_tcp(TALLOC_CTX *mem_ctx, const char *host,
2586                            const struct ndr_syntax_id *abstract_syntax,
2587                            struct rpc_pipe_client **presult)
2588 {
2589         NTSTATUS status;
2590         uint16_t port = 0;
2591
2592         status = rpc_pipe_get_tcp_port(host, abstract_syntax, &port);
2593         if (!NT_STATUS_IS_OK(status)) {
2594                 return status;
2595         }
2596
2597         return rpc_pipe_open_tcp_port(mem_ctx, host, port,
2598                                         abstract_syntax, presult);
2599 }
2600
2601 /********************************************************************
2602  Create a rpc pipe client struct, connecting to a unix domain socket
2603  ********************************************************************/
2604 NTSTATUS rpc_pipe_open_ncalrpc(TALLOC_CTX *mem_ctx, const char *socket_path,
2605                                const struct ndr_syntax_id *abstract_syntax,
2606                                struct rpc_pipe_client **presult)
2607 {
2608         struct rpc_pipe_client *result;
2609         struct sockaddr_un addr;
2610         NTSTATUS status;
2611         int fd;
2612
2613         result = talloc_zero(mem_ctx, struct rpc_pipe_client);
2614         if (result == NULL) {
2615                 return NT_STATUS_NO_MEMORY;
2616         }
2617
2618         result->abstract_syntax = *abstract_syntax;
2619         result->transfer_syntax = ndr_transfer_syntax;
2620         result->dispatch = cli_do_rpc_ndr;
2621         result->dispatch_send = cli_do_rpc_ndr_send;
2622         result->dispatch_recv = cli_do_rpc_ndr_recv;
2623
2624         result->desthost = get_myname(result);
2625         result->srv_name_slash = talloc_asprintf_strupper_m(
2626                 result, "\\\\%s", result->desthost);
2627         if ((result->desthost == NULL) || (result->srv_name_slash == NULL)) {
2628                 status = NT_STATUS_NO_MEMORY;
2629                 goto fail;
2630         }
2631
2632         result->max_xmit_frag = RPC_MAX_PDU_FRAG_LEN;
2633         result->max_recv_frag = RPC_MAX_PDU_FRAG_LEN;
2634
2635         fd = socket(AF_UNIX, SOCK_STREAM, 0);
2636         if (fd == -1) {
2637                 status = map_nt_error_from_unix(errno);
2638                 goto fail;
2639         }
2640
2641         ZERO_STRUCT(addr);
2642         addr.sun_family = AF_UNIX;
2643         strncpy(addr.sun_path, socket_path, sizeof(addr.sun_path));
2644
2645         if (sys_connect(fd, (struct sockaddr *)(void *)&addr) == -1) {
2646                 DEBUG(0, ("connect(%s) failed: %s\n", socket_path,
2647                           strerror(errno)));
2648                 close(fd);
2649                 return map_nt_error_from_unix(errno);
2650         }
2651
2652         status = rpc_transport_sock_init(result, fd, &result->transport);
2653         if (!NT_STATUS_IS_OK(status)) {
2654                 close(fd);
2655                 goto fail;
2656         }
2657
2658         result->transport->transport = NCALRPC;
2659
2660         *presult = result;
2661         return NT_STATUS_OK;
2662
2663  fail:
2664         TALLOC_FREE(result);
2665         return status;
2666 }
2667
2668 struct rpc_pipe_client_np_ref {
2669         struct cli_state *cli;
2670         struct rpc_pipe_client *pipe;
2671 };
2672
2673 static int rpc_pipe_client_np_ref_destructor(struct rpc_pipe_client_np_ref *np_ref)
2674 {
2675         DLIST_REMOVE(np_ref->cli->pipe_list, np_ref->pipe);
2676         return 0;
2677 }
2678
2679 /****************************************************************************
2680  Open a named pipe over SMB to a remote server.
2681  *
2682  * CAVEAT CALLER OF THIS FUNCTION:
2683  *    The returned rpc_pipe_client saves a copy of the cli_state cli pointer,
2684  *    so be sure that this function is called AFTER any structure (vs pointer)
2685  *    assignment of the cli.  In particular, libsmbclient does structure
2686  *    assignments of cli, which invalidates the data in the returned
2687  *    rpc_pipe_client if this function is called before the structure assignment
2688  *    of cli.
2689  * 
2690  ****************************************************************************/
2691
2692 static NTSTATUS rpc_pipe_open_np(struct cli_state *cli,
2693                                  const struct ndr_syntax_id *abstract_syntax,
2694                                  struct rpc_pipe_client **presult)
2695 {
2696         struct rpc_pipe_client *result;
2697         NTSTATUS status;
2698         struct rpc_pipe_client_np_ref *np_ref;
2699
2700         /* sanity check to protect against crashes */
2701
2702         if ( !cli ) {
2703                 return NT_STATUS_INVALID_HANDLE;
2704         }
2705
2706         result = TALLOC_ZERO_P(NULL, struct rpc_pipe_client);
2707         if (result == NULL) {
2708                 return NT_STATUS_NO_MEMORY;
2709         }
2710
2711         result->abstract_syntax = *abstract_syntax;
2712         result->transfer_syntax = ndr_transfer_syntax;
2713         result->dispatch = cli_do_rpc_ndr;
2714         result->dispatch_send = cli_do_rpc_ndr_send;
2715         result->dispatch_recv = cli_do_rpc_ndr_recv;
2716         result->desthost = talloc_strdup(result, cli->desthost);
2717         result->srv_name_slash = talloc_asprintf_strupper_m(
2718                 result, "\\\\%s", result->desthost);
2719
2720         result->max_xmit_frag = RPC_MAX_PDU_FRAG_LEN;
2721         result->max_recv_frag = RPC_MAX_PDU_FRAG_LEN;
2722
2723         if ((result->desthost == NULL) || (result->srv_name_slash == NULL)) {
2724                 TALLOC_FREE(result);
2725                 return NT_STATUS_NO_MEMORY;
2726         }
2727
2728         status = rpc_transport_np_init(result, cli, abstract_syntax,
2729                                        &result->transport);
2730         if (!NT_STATUS_IS_OK(status)) {
2731                 TALLOC_FREE(result);
2732                 return status;
2733         }
2734
2735         result->transport->transport = NCACN_NP;
2736
2737         np_ref = talloc(result->transport, struct rpc_pipe_client_np_ref);
2738         if (np_ref == NULL) {
2739                 TALLOC_FREE(result);
2740                 return NT_STATUS_NO_MEMORY;
2741         }
2742         np_ref->cli = cli;
2743         np_ref->pipe = result;
2744
2745         DLIST_ADD(np_ref->cli->pipe_list, np_ref->pipe);
2746         talloc_set_destructor(np_ref, rpc_pipe_client_np_ref_destructor);
2747
2748         *presult = result;
2749         return NT_STATUS_OK;
2750 }
2751
2752 NTSTATUS rpc_pipe_open_local(TALLOC_CTX *mem_ctx,
2753                              struct rpc_cli_smbd_conn *conn,
2754                              const struct ndr_syntax_id *syntax,
2755                              struct rpc_pipe_client **presult)
2756 {
2757         struct rpc_pipe_client *result;
2758         struct pipe_auth_data *auth;
2759         NTSTATUS status;
2760
2761         result = talloc(mem_ctx, struct rpc_pipe_client);
2762         if (result == NULL) {
2763                 return NT_STATUS_NO_MEMORY;
2764         }
2765         result->abstract_syntax = *syntax;
2766         result->transfer_syntax = ndr_transfer_syntax;
2767         result->dispatch = cli_do_rpc_ndr;
2768         result->dispatch_send = cli_do_rpc_ndr_send;
2769         result->dispatch_recv = cli_do_rpc_ndr_recv;
2770         result->max_xmit_frag = RPC_MAX_PDU_FRAG_LEN;
2771         result->max_recv_frag = RPC_MAX_PDU_FRAG_LEN;
2772
2773         result->desthost = talloc_strdup(result, global_myname());
2774         result->srv_name_slash = talloc_asprintf_strupper_m(
2775                 result, "\\\\%s", global_myname());
2776         if ((result->desthost == NULL) || (result->srv_name_slash == NULL)) {
2777                 TALLOC_FREE(result);
2778                 return NT_STATUS_NO_MEMORY;
2779         }
2780
2781         status = rpc_transport_smbd_init(result, conn, syntax,
2782                                          &result->transport);
2783         if (!NT_STATUS_IS_OK(status)) {
2784                 DEBUG(1, ("rpc_transport_smbd_init failed: %s\n",
2785                           nt_errstr(status)));
2786                 TALLOC_FREE(result);
2787                 return status;
2788         }
2789
2790         status = rpccli_anon_bind_data(result, &auth);
2791         if (!NT_STATUS_IS_OK(status)) {
2792                 DEBUG(1, ("rpccli_anon_bind_data failed: %s\n",
2793                           nt_errstr(status)));
2794                 TALLOC_FREE(result);
2795                 return status;
2796         }
2797
2798         status = rpc_pipe_bind(result, auth);
2799         if (!NT_STATUS_IS_OK(status)) {
2800                 DEBUG(1, ("rpc_pipe_bind failed: %s\n", nt_errstr(status)));
2801                 TALLOC_FREE(result);
2802                 return status;
2803         }
2804
2805         result->transport->transport = NCACN_INTERNAL;
2806
2807         *presult = result;
2808         return NT_STATUS_OK;
2809 }
2810
2811 /****************************************************************************
2812  Open a pipe to a remote server.
2813  ****************************************************************************/
2814
2815 static NTSTATUS cli_rpc_pipe_open(struct cli_state *cli,
2816                                   enum dcerpc_transport_t transport,
2817                                   const struct ndr_syntax_id *interface,
2818                                   struct rpc_pipe_client **presult)
2819 {
2820         switch (transport) {
2821         case NCACN_IP_TCP:
2822                 return rpc_pipe_open_tcp(NULL, cli->desthost, interface,
2823                                          presult);
2824         case NCACN_NP:
2825                 return rpc_pipe_open_np(cli, interface, presult);
2826         default:
2827                 return NT_STATUS_NOT_IMPLEMENTED;
2828         }
2829 }
2830
2831 /****************************************************************************
2832  Open a named pipe to an SMB server and bind anonymously.
2833  ****************************************************************************/
2834
2835 NTSTATUS cli_rpc_pipe_open_noauth_transport(struct cli_state *cli,
2836                                             enum dcerpc_transport_t transport,
2837                                             const struct ndr_syntax_id *interface,
2838                                             struct rpc_pipe_client **presult)
2839 {
2840         struct rpc_pipe_client *result;
2841         struct pipe_auth_data *auth;
2842         NTSTATUS status;
2843
2844         status = cli_rpc_pipe_open(cli, transport, interface, &result);
2845         if (!NT_STATUS_IS_OK(status)) {
2846                 return status;
2847         }
2848
2849         status = rpccli_anon_bind_data(result, &auth);
2850         if (!NT_STATUS_IS_OK(status)) {
2851                 DEBUG(0, ("rpccli_anon_bind_data returned %s\n",
2852                           nt_errstr(status)));
2853                 TALLOC_FREE(result);
2854                 return status;
2855         }
2856
2857         /*
2858          * This is a bit of an abstraction violation due to the fact that an
2859          * anonymous bind on an authenticated SMB inherits the user/domain
2860          * from the enclosing SMB creds
2861          */
2862
2863         TALLOC_FREE(auth->user_name);
2864         TALLOC_FREE(auth->domain);
2865
2866         auth->user_name = talloc_strdup(auth, cli->user_name);
2867         auth->domain = talloc_strdup(auth, cli->domain);
2868         auth->user_session_key = data_blob_talloc(auth,
2869                 cli->user_session_key.data,
2870                 cli->user_session_key.length);
2871
2872         if ((auth->user_name == NULL) || (auth->domain == NULL)) {
2873                 TALLOC_FREE(result);
2874                 return NT_STATUS_NO_MEMORY;
2875         }
2876
2877         status = rpc_pipe_bind(result, auth);
2878         if (!NT_STATUS_IS_OK(status)) {
2879                 int lvl = 0;
2880                 if (ndr_syntax_id_equal(interface,
2881                                         &ndr_table_dssetup.syntax_id)) {
2882                         /* non AD domains just don't have this pipe, avoid
2883                          * level 0 statement in that case - gd */
2884                         lvl = 3;
2885                 }
2886                 DEBUG(lvl, ("cli_rpc_pipe_open_noauth: rpc_pipe_bind for pipe "
2887                             "%s failed with error %s\n",
2888                             get_pipe_name_from_syntax(talloc_tos(), interface),
2889                             nt_errstr(status) ));
2890                 TALLOC_FREE(result);
2891                 return status;
2892         }
2893
2894         DEBUG(10,("cli_rpc_pipe_open_noauth: opened pipe %s to machine "
2895                   "%s and bound anonymously.\n",
2896                   get_pipe_name_from_syntax(talloc_tos(), interface),
2897                   cli->desthost));
2898
2899         *presult = result;
2900         return NT_STATUS_OK;
2901 }
2902
2903 /****************************************************************************
2904  ****************************************************************************/
2905
2906 NTSTATUS cli_rpc_pipe_open_noauth(struct cli_state *cli,
2907                                   const struct ndr_syntax_id *interface,
2908                                   struct rpc_pipe_client **presult)
2909 {
2910         return cli_rpc_pipe_open_noauth_transport(cli, NCACN_NP,
2911                                                   interface, presult);
2912 }
2913
2914 /****************************************************************************
2915  Open a named pipe to an SMB server and bind using NTLMSSP or SPNEGO NTLMSSP
2916  ****************************************************************************/
2917
2918 static NTSTATUS cli_rpc_pipe_open_ntlmssp_internal(struct cli_state *cli,
2919                                                    const struct ndr_syntax_id *interface,
2920                                                    enum dcerpc_transport_t transport,
2921                                                    enum pipe_auth_type auth_type,
2922                                                    enum dcerpc_AuthLevel auth_level,
2923                                                    const char *domain,
2924                                                    const char *username,
2925                                                    const char *password,
2926                                                    struct rpc_pipe_client **presult)
2927 {
2928         struct rpc_pipe_client *result;
2929         struct pipe_auth_data *auth;
2930         NTSTATUS status;
2931
2932         status = cli_rpc_pipe_open(cli, transport, interface, &result);
2933         if (!NT_STATUS_IS_OK(status)) {
2934                 return status;
2935         }
2936
2937         status = rpccli_ntlmssp_bind_data(
2938                 result, auth_type, auth_level, domain, username,
2939                 password, &auth);
2940         if (!NT_STATUS_IS_OK(status)) {
2941                 DEBUG(0, ("rpccli_ntlmssp_bind_data returned %s\n",
2942                           nt_errstr(status)));
2943                 goto err;
2944         }
2945
2946         status = rpc_pipe_bind(result, auth);
2947         if (!NT_STATUS_IS_OK(status)) {
2948                 DEBUG(0, ("cli_rpc_pipe_open_ntlmssp_internal: cli_rpc_pipe_bind failed with error %s\n",
2949                         nt_errstr(status) ));
2950                 goto err;
2951         }
2952
2953         DEBUG(10,("cli_rpc_pipe_open_ntlmssp_internal: opened pipe %s to "
2954                 "machine %s and bound NTLMSSP as user %s\\%s.\n",
2955                   get_pipe_name_from_syntax(talloc_tos(), interface),
2956                   cli->desthost, domain, username ));
2957
2958         *presult = result;
2959         return NT_STATUS_OK;
2960
2961   err:
2962
2963         TALLOC_FREE(result);
2964         return status;
2965 }
2966
2967 /****************************************************************************
2968  External interface.
2969  Open a named pipe to an SMB server and bind using NTLMSSP (bind type 10)
2970  ****************************************************************************/
2971
2972 NTSTATUS cli_rpc_pipe_open_ntlmssp(struct cli_state *cli,
2973                                    const struct ndr_syntax_id *interface,
2974                                    enum dcerpc_transport_t transport,
2975                                    enum dcerpc_AuthLevel auth_level,
2976                                    const char *domain,
2977                                    const char *username,
2978                                    const char *password,
2979                                    struct rpc_pipe_client **presult)
2980 {
2981         return cli_rpc_pipe_open_ntlmssp_internal(cli,
2982                                                 interface,
2983                                                 transport,
2984                                                 PIPE_AUTH_TYPE_NTLMSSP,
2985                                                 auth_level,
2986                                                 domain,
2987                                                 username,
2988                                                 password,
2989                                                 presult);
2990 }
2991
2992 /****************************************************************************
2993  External interface.
2994  Open a named pipe to an SMB server and bind using spnego NTLMSSP (bind type 9)
2995  ****************************************************************************/
2996
2997 NTSTATUS cli_rpc_pipe_open_spnego_ntlmssp(struct cli_state *cli,
2998                                           const struct ndr_syntax_id *interface,
2999                                           enum dcerpc_transport_t transport,
3000                                           enum dcerpc_AuthLevel auth_level,
3001                                           const char *domain,
3002                                           const char *username,
3003                                           const char *password,
3004                                           struct rpc_pipe_client **presult)
3005 {
3006         return cli_rpc_pipe_open_ntlmssp_internal(cli,
3007                                                 interface,
3008                                                 transport,
3009                                                 PIPE_AUTH_TYPE_SPNEGO_NTLMSSP,
3010                                                 auth_level,
3011                                                 domain,
3012                                                 username,
3013                                                 password,
3014                                                 presult);
3015 }
3016
3017 /****************************************************************************
3018   Get a the schannel session key out of an already opened netlogon pipe.
3019  ****************************************************************************/
3020 static NTSTATUS get_schannel_session_key_common(struct rpc_pipe_client *netlogon_pipe,
3021                                                 struct cli_state *cli,
3022                                                 const char *domain,
3023                                                 uint32 *pneg_flags)
3024 {
3025         enum netr_SchannelType sec_chan_type = 0;
3026         unsigned char machine_pwd[16];
3027         const char *machine_account;
3028         NTSTATUS status;
3029
3030         /* Get the machine account credentials from secrets.tdb. */
3031         if (!get_trust_pw_hash(domain, machine_pwd, &machine_account,
3032                                &sec_chan_type))
3033         {
3034                 DEBUG(0, ("get_schannel_session_key: could not fetch "
3035                         "trust account password for domain '%s'\n",
3036                         domain));
3037                 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
3038         }
3039
3040         status = rpccli_netlogon_setup_creds(netlogon_pipe,
3041                                         cli->desthost, /* server name */
3042                                         domain,        /* domain */
3043                                         global_myname(), /* client name */
3044                                         machine_account, /* machine account name */
3045                                         machine_pwd,
3046                                         sec_chan_type,
3047                                         pneg_flags);
3048
3049         if (!NT_STATUS_IS_OK(status)) {
3050                 DEBUG(3, ("get_schannel_session_key_common: "
3051                           "rpccli_netlogon_setup_creds failed with result %s "
3052                           "to server %s, domain %s, machine account %s.\n",
3053                           nt_errstr(status), cli->desthost, domain,
3054                           machine_account ));
3055                 return status;
3056         }
3057
3058         if (((*pneg_flags) & NETLOGON_NEG_SCHANNEL) == 0) {
3059                 DEBUG(3, ("get_schannel_session_key: Server %s did not offer schannel\n",
3060                         cli->desthost));
3061                 return NT_STATUS_INVALID_NETWORK_RESPONSE;
3062         }
3063
3064         return NT_STATUS_OK;;
3065 }
3066
3067 /****************************************************************************
3068  Open a netlogon pipe and get the schannel session key.
3069  Now exposed to external callers.
3070  ****************************************************************************/
3071
3072
3073 NTSTATUS get_schannel_session_key(struct cli_state *cli,
3074                                   const char *domain,
3075                                   uint32 *pneg_flags,
3076                                   struct rpc_pipe_client **presult)
3077 {
3078         struct rpc_pipe_client *netlogon_pipe = NULL;
3079         NTSTATUS status;
3080
3081         status = cli_rpc_pipe_open_noauth(cli, &ndr_table_netlogon.syntax_id,
3082                                           &netlogon_pipe);
3083         if (!NT_STATUS_IS_OK(status)) {
3084                 return status;
3085         }
3086
3087         status = get_schannel_session_key_common(netlogon_pipe, cli, domain,
3088                                                  pneg_flags);
3089         if (!NT_STATUS_IS_OK(status)) {
3090                 TALLOC_FREE(netlogon_pipe);
3091                 return status;
3092         }
3093
3094         *presult = netlogon_pipe;
3095         return NT_STATUS_OK;
3096 }
3097
3098 /****************************************************************************
3099  External interface.
3100  Open a named pipe to an SMB server and bind using schannel (bind type 68)
3101  using session_key. sign and seal.
3102
3103  The *pdc will be stolen onto this new pipe
3104  ****************************************************************************/
3105
3106 NTSTATUS cli_rpc_pipe_open_schannel_with_key(struct cli_state *cli,
3107                                              const struct ndr_syntax_id *interface,
3108                                              enum dcerpc_transport_t transport,
3109                                              enum dcerpc_AuthLevel auth_level,
3110                                              const char *domain,
3111                                              struct netlogon_creds_CredentialState **pdc,
3112                                              struct rpc_pipe_client **presult)
3113 {
3114         struct rpc_pipe_client *result;
3115         struct pipe_auth_data *auth;
3116         NTSTATUS status;
3117
3118         status = cli_rpc_pipe_open(cli, transport, interface, &result);
3119         if (!NT_STATUS_IS_OK(status)) {
3120                 return status;
3121         }
3122
3123         status = rpccli_schannel_bind_data(result, domain, auth_level,
3124                                            *pdc, &auth);
3125         if (!NT_STATUS_IS_OK(status)) {
3126                 DEBUG(0, ("rpccli_schannel_bind_data returned %s\n",
3127                           nt_errstr(status)));
3128                 TALLOC_FREE(result);
3129                 return status;
3130         }
3131
3132         status = rpc_pipe_bind(result, auth);
3133         if (!NT_STATUS_IS_OK(status)) {
3134                 DEBUG(0, ("cli_rpc_pipe_open_schannel_with_key: "
3135                           "cli_rpc_pipe_bind failed with error %s\n",
3136                           nt_errstr(status) ));
3137                 TALLOC_FREE(result);
3138                 return status;
3139         }
3140
3141         /*
3142          * The credentials on a new netlogon pipe are the ones we are passed
3143          * in - reference them in
3144          */
3145         result->dc = talloc_move(result, pdc);
3146
3147         DEBUG(10,("cli_rpc_pipe_open_schannel_with_key: opened pipe %s to machine %s "
3148                   "for domain %s and bound using schannel.\n",
3149                   get_pipe_name_from_syntax(talloc_tos(), interface),
3150                   cli->desthost, domain ));
3151
3152         *presult = result;
3153         return NT_STATUS_OK;
3154 }
3155
3156 /****************************************************************************
3157  Open a named pipe to an SMB server and bind using schannel (bind type 68).
3158  Fetch the session key ourselves using a temporary netlogon pipe. This
3159  version uses an ntlmssp auth bound netlogon pipe to get the key.
3160  ****************************************************************************/
3161
3162 static NTSTATUS get_schannel_session_key_auth_ntlmssp(struct cli_state *cli,
3163                                                       const char *domain,
3164                                                       const char *username,
3165                                                       const char *password,
3166                                                       uint32 *pneg_flags,
3167                                                       struct rpc_pipe_client **presult)
3168 {
3169         struct rpc_pipe_client *netlogon_pipe = NULL;
3170         NTSTATUS status;
3171
3172         status = cli_rpc_pipe_open_spnego_ntlmssp(
3173                 cli, &ndr_table_netlogon.syntax_id, NCACN_NP,
3174                 DCERPC_AUTH_LEVEL_PRIVACY,
3175                 domain, username, password, &netlogon_pipe);
3176         if (!NT_STATUS_IS_OK(status)) {
3177                 return status;
3178         }
3179
3180         status = get_schannel_session_key_common(netlogon_pipe, cli, domain,
3181                                                  pneg_flags);
3182         if (!NT_STATUS_IS_OK(status)) {
3183                 TALLOC_FREE(netlogon_pipe);
3184                 return status;
3185         }
3186
3187         *presult = netlogon_pipe;
3188         return NT_STATUS_OK;
3189 }
3190
3191 /****************************************************************************
3192  Open a named pipe to an SMB server and bind using schannel (bind type 68).
3193  Fetch the session key ourselves using a temporary netlogon pipe. This version
3194  uses an ntlmssp bind to get the session key.
3195  ****************************************************************************/
3196
3197 NTSTATUS cli_rpc_pipe_open_ntlmssp_auth_schannel(struct cli_state *cli,
3198                                                  const struct ndr_syntax_id *interface,
3199                                                  enum dcerpc_transport_t transport,
3200                                                  enum dcerpc_AuthLevel auth_level,
3201                                                  const char *domain,
3202                                                  const char *username,
3203                                                  const char *password,
3204                                                  struct rpc_pipe_client **presult)
3205 {
3206         uint32_t neg_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS;
3207         struct rpc_pipe_client *netlogon_pipe = NULL;
3208         struct rpc_pipe_client *result = NULL;
3209         NTSTATUS status;
3210
3211         status = get_schannel_session_key_auth_ntlmssp(
3212                 cli, domain, username, password, &neg_flags, &netlogon_pipe);
3213         if (!NT_STATUS_IS_OK(status)) {
3214                 DEBUG(0,("cli_rpc_pipe_open_ntlmssp_auth_schannel: failed to get schannel session "
3215                         "key from server %s for domain %s.\n",
3216                         cli->desthost, domain ));
3217                 return status;
3218         }
3219
3220         status = cli_rpc_pipe_open_schannel_with_key(
3221                 cli, interface, transport, auth_level, domain, &netlogon_pipe->dc,
3222                 &result);
3223
3224         /* Now we've bound using the session key we can close the netlog pipe. */
3225         TALLOC_FREE(netlogon_pipe);
3226
3227         if (NT_STATUS_IS_OK(status)) {
3228                 *presult = result;
3229         }
3230         return status;
3231 }
3232
3233 /****************************************************************************
3234  Open a named pipe to an SMB server and bind using schannel (bind type 68).
3235  Fetch the session key ourselves using a temporary netlogon pipe.
3236  ****************************************************************************/
3237
3238 NTSTATUS cli_rpc_pipe_open_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                                     struct rpc_pipe_client **presult)
3244 {
3245         uint32_t neg_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS;
3246         struct rpc_pipe_client *netlogon_pipe = NULL;
3247         struct rpc_pipe_client *result = NULL;
3248         NTSTATUS status;
3249
3250         status = get_schannel_session_key(cli, domain, &neg_flags,
3251                                           &netlogon_pipe);
3252         if (!NT_STATUS_IS_OK(status)) {
3253                 DEBUG(0,("cli_rpc_pipe_open_schannel: failed to get schannel session "
3254                         "key from server %s for domain %s.\n",
3255                         cli->desthost, domain ));
3256                 return status;
3257         }
3258
3259         status = cli_rpc_pipe_open_schannel_with_key(
3260                 cli, interface, transport, auth_level, domain, &netlogon_pipe->dc,
3261                 &result);
3262
3263         /* Now we've bound using the session key we can close the netlog pipe. */
3264         TALLOC_FREE(netlogon_pipe);
3265
3266         if (NT_STATUS_IS_OK(status)) {
3267                 *presult = result;
3268         }
3269
3270         return status;
3271 }
3272
3273 /****************************************************************************
3274  Open a named pipe to an SMB server and bind using krb5 (bind type 16).
3275  The idea is this can be called with service_princ, username and password all
3276  NULL so long as the caller has a TGT.
3277  ****************************************************************************/
3278
3279 NTSTATUS cli_rpc_pipe_open_krb5(struct cli_state *cli,
3280                                 const struct ndr_syntax_id *interface,
3281                                 enum dcerpc_AuthLevel auth_level,
3282                                 const char *service_princ,
3283                                 const char *username,
3284                                 const char *password,
3285                                 struct rpc_pipe_client **presult)
3286 {
3287 #ifdef HAVE_KRB5
3288         struct rpc_pipe_client *result;
3289         struct pipe_auth_data *auth;
3290         NTSTATUS status;
3291
3292         status = cli_rpc_pipe_open(cli, NCACN_NP, interface, &result);
3293         if (!NT_STATUS_IS_OK(status)) {
3294                 return status;
3295         }
3296
3297         status = rpccli_kerberos_bind_data(result, auth_level, service_princ,
3298                                            username, password, &auth);
3299         if (!NT_STATUS_IS_OK(status)) {
3300                 DEBUG(0, ("rpccli_kerberos_bind_data returned %s\n",
3301                           nt_errstr(status)));
3302                 TALLOC_FREE(result);
3303                 return status;
3304         }
3305
3306         status = rpc_pipe_bind(result, auth);
3307         if (!NT_STATUS_IS_OK(status)) {
3308                 DEBUG(0, ("cli_rpc_pipe_open_krb5: cli_rpc_pipe_bind failed "
3309                           "with error %s\n", nt_errstr(status)));
3310                 TALLOC_FREE(result);
3311                 return status;
3312         }
3313
3314         *presult = result;
3315         return NT_STATUS_OK;
3316 #else
3317         DEBUG(0,("cli_rpc_pipe_open_krb5: kerberos not found at compile time.\n"));
3318         return NT_STATUS_NOT_IMPLEMENTED;
3319 #endif
3320 }
3321
3322 NTSTATUS cli_get_session_key(TALLOC_CTX *mem_ctx,
3323                              struct rpc_pipe_client *cli,
3324                              DATA_BLOB *session_key)
3325 {
3326         struct pipe_auth_data *a = cli->auth;
3327         DATA_BLOB sk;
3328
3329         if (!session_key || !cli) {
3330                 return NT_STATUS_INVALID_PARAMETER;
3331         }
3332
3333         if (!cli->auth) {
3334                 return NT_STATUS_INVALID_PARAMETER;
3335         }
3336
3337         switch (cli->auth->auth_type) {
3338         case PIPE_AUTH_TYPE_SCHANNEL:
3339                 sk = data_blob_const(a->a_u.schannel_auth->creds->session_key,
3340                                      16);
3341                 break;
3342         case PIPE_AUTH_TYPE_NTLMSSP:
3343         case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP:
3344                 sk = auth_ntlmssp_get_session_key(a->a_u.auth_ntlmssp_state);
3345                 break;
3346         case PIPE_AUTH_TYPE_KRB5:
3347         case PIPE_AUTH_TYPE_SPNEGO_KRB5:
3348                 sk = data_blob_const(a->a_u.kerberos_auth->session_key.data,
3349                                      a->a_u.kerberos_auth->session_key.length);
3350                 break;
3351         case PIPE_AUTH_TYPE_NONE:
3352                 sk = data_blob_const(a->user_session_key.data,
3353                                      a->user_session_key.length);
3354                 break;
3355         default:
3356                 return NT_STATUS_NO_USER_SESSION_KEY;
3357         }
3358
3359         *session_key = data_blob_dup_talloc(mem_ctx, &sk);
3360         return NT_STATUS_OK;
3361 }