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