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