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