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