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