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