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