s3-dcerpc: Avoid unnecessary memory allocation for dcerpc_ctx_list
[kamenim/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 prs_struct 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                                             prs_struct *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 (prs_offset(data) > 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                                    (uint8_t *)prs_data_p(data),
1294                                    prs_offset(data), max_recv_frag);
1295         if (subreq == NULL) {
1296                 goto fail;
1297         }
1298         tevent_req_set_callback(subreq, rpc_api_pipe_trans_done, req);
1299         return req;
1300
1301  post_status:
1302         tevent_req_nterror(req, status);
1303         return tevent_req_post(req, ev);
1304  fail:
1305         TALLOC_FREE(req);
1306         return NULL;
1307 }
1308
1309 static void rpc_api_pipe_trans_done(struct tevent_req *subreq)
1310 {
1311         struct tevent_req *req = tevent_req_callback_data(
1312                 subreq, struct tevent_req);
1313         struct rpc_api_pipe_state *state = tevent_req_data(
1314                 req, struct rpc_api_pipe_state);
1315         NTSTATUS status;
1316         uint8_t *rdata = NULL;
1317         uint32_t rdata_len = 0;
1318
1319         status = cli_api_pipe_recv(subreq, state, &rdata, &rdata_len);
1320         TALLOC_FREE(subreq);
1321         if (!NT_STATUS_IS_OK(status)) {
1322                 DEBUG(5, ("cli_api_pipe failed: %s\n", nt_errstr(status)));
1323                 tevent_req_nterror(req, status);
1324                 return;
1325         }
1326
1327         if (rdata == NULL) {
1328                 DEBUG(3,("rpc_api_pipe: %s failed to return data.\n",
1329                          rpccli_pipe_txt(talloc_tos(), state->cli)));
1330                 tevent_req_done(req);
1331                 return;
1332         }
1333
1334         /*
1335          * Move data on state->incoming_frag.
1336          */
1337         state->incoming_frag.data = talloc_move(state, &rdata);
1338         state->incoming_frag.length = rdata_len;
1339         if (!state->incoming_frag.data) {
1340                 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
1341                 return;
1342         }
1343
1344         /* Ensure we have enough data for a pdu. */
1345         subreq = get_complete_frag_send(state, state->ev, state->cli,
1346                                         &state->incoming_frag);
1347         if (tevent_req_nomem(subreq, req)) {
1348                 return;
1349         }
1350         tevent_req_set_callback(subreq, rpc_api_pipe_got_pdu, req);
1351 }
1352
1353 static void rpc_api_pipe_got_pdu(struct tevent_req *subreq)
1354 {
1355         struct tevent_req *req = tevent_req_callback_data(
1356                 subreq, struct tevent_req);
1357         struct rpc_api_pipe_state *state = tevent_req_data(
1358                 req, struct rpc_api_pipe_state);
1359         NTSTATUS status;
1360         DATA_BLOB rdata = data_blob_null;
1361
1362         status = get_complete_frag_recv(subreq);
1363         TALLOC_FREE(subreq);
1364         if (!NT_STATUS_IS_OK(status)) {
1365                 DEBUG(5, ("get_complete_frag failed: %s\n",
1366                           nt_errstr(status)));
1367                 tevent_req_nterror(req, status);
1368                 return;
1369         }
1370
1371         state->pkt = talloc(state, struct ncacn_packet);
1372         if (!state->pkt) {
1373                 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
1374                 return;
1375         }
1376
1377         status = cli_pipe_validate_current_pdu(state,
1378                                                 state->cli, state->pkt,
1379                                                 &state->incoming_frag,
1380                                                 state->expected_pkt_type,
1381                                                 &rdata,
1382                                                 &state->reply_pdu);
1383
1384         DEBUG(10,("rpc_api_pipe: got frag len of %u at offset %u: %s\n",
1385                   (unsigned)state->incoming_frag.length,
1386                   (unsigned)state->reply_pdu_offset,
1387                   nt_errstr(status)));
1388
1389         if (!NT_STATUS_IS_OK(status)) {
1390                 tevent_req_nterror(req, status);
1391                 return;
1392         }
1393
1394         if ((state->pkt->pfc_flags & DCERPC_PFC_FLAG_FIRST)
1395             && (state->pkt->drep[0] != DCERPC_DREP_LE)) {
1396                 /*
1397                  * Set the data type correctly for big-endian data on the
1398                  * first packet.
1399                  */
1400                 DEBUG(10,("rpc_api_pipe: On %s PDU data format is "
1401                           "big-endian.\n",
1402                           rpccli_pipe_txt(talloc_tos(), state->cli)));
1403                 state->endianess = 0x00; /* BIG ENDIAN */
1404         }
1405         /*
1406          * Check endianness on subsequent packets.
1407          */
1408         if (state->endianess != state->pkt->drep[0]) {
1409                 DEBUG(0,("rpc_api_pipe: Error : Endianness changed from %s to "
1410                          "%s\n",
1411                          state->endianess?"little":"big",
1412                          state->pkt->drep[0]?"little":"big"));
1413                 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
1414                 return;
1415         }
1416
1417         /* Now copy the data portion out of the pdu into rbuf. */
1418         if (state->reply_pdu.length < state->reply_pdu_offset + rdata.length) {
1419                 if (!data_blob_realloc(NULL, &state->reply_pdu,
1420                                 state->reply_pdu_offset + rdata.length)) {
1421                         tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
1422                         return;
1423                 }
1424         }
1425
1426         memcpy(state->reply_pdu.data + state->reply_pdu_offset,
1427                 rdata.data, rdata.length);
1428         state->reply_pdu_offset += rdata.length;
1429
1430         /* reset state->incoming_frag, there is no need to free it,
1431          * it will be reallocated to the right size the next time
1432          * it is used */
1433         state->incoming_frag.length = 0;
1434
1435         if (state->pkt->pfc_flags & DCERPC_PFC_FLAG_LAST) {
1436                 /* make sure the pdu length is right now that we
1437                  * have all the data available (alloc hint may
1438                  * have allocated more than was actually used) */
1439                 state->reply_pdu.length = state->reply_pdu_offset;
1440                 DEBUG(10,("rpc_api_pipe: %s returned %u bytes.\n",
1441                           rpccli_pipe_txt(talloc_tos(), state->cli),
1442                           (unsigned)state->reply_pdu.length));
1443                 tevent_req_done(req);
1444                 return;
1445         }
1446
1447         subreq = get_complete_frag_send(state, state->ev, state->cli,
1448                                         &state->incoming_frag);
1449         if (tevent_req_nomem(subreq, req)) {
1450                 return;
1451         }
1452         tevent_req_set_callback(subreq, rpc_api_pipe_got_pdu, req);
1453 }
1454
1455 static NTSTATUS rpc_api_pipe_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
1456                                   struct ncacn_packet **pkt,
1457                                   DATA_BLOB *reply_pdu)
1458 {
1459         struct rpc_api_pipe_state *state = tevent_req_data(
1460                 req, struct rpc_api_pipe_state);
1461         NTSTATUS status;
1462
1463         if (tevent_req_is_nterror(req, &status)) {
1464                 return status;
1465         }
1466
1467         /* return data to caller and assign it ownership of memory */
1468         if (reply_pdu) {
1469                 reply_pdu->data = talloc_move(mem_ctx, &state->reply_pdu.data);
1470                 reply_pdu->length = state->reply_pdu.length;
1471                 state->reply_pdu.length = 0;
1472         } else {
1473                 data_blob_free(&state->reply_pdu);
1474         }
1475
1476         if (pkt) {
1477                 *pkt = talloc_steal(mem_ctx, state->pkt);
1478         }
1479
1480         return NT_STATUS_OK;
1481 }
1482
1483 /*******************************************************************
1484  Creates krb5 auth bind.
1485  ********************************************************************/
1486
1487 static NTSTATUS create_krb5_auth_bind_req(struct rpc_pipe_client *cli,
1488                                           enum dcerpc_AuthLevel auth_level,
1489                                           DATA_BLOB *auth_info)
1490 {
1491 #ifdef HAVE_KRB5
1492         int ret;
1493         NTSTATUS status;
1494         struct kerberos_auth_struct *a = cli->auth->a_u.kerberos_auth;
1495         DATA_BLOB tkt = data_blob_null;
1496         DATA_BLOB tkt_wrapped = data_blob_null;
1497
1498         DEBUG(5, ("create_krb5_auth_bind_req: creating a service ticket for principal %s\n",
1499                 a->service_principal ));
1500
1501         /* Create the ticket for the service principal and return it in a gss-api wrapped blob. */
1502
1503         ret = cli_krb5_get_ticket(a->service_principal, 0, &tkt,
1504                         &a->session_key, (uint32)AP_OPTS_MUTUAL_REQUIRED, NULL, NULL, NULL);
1505
1506         if (ret) {
1507                 DEBUG(1,("create_krb5_auth_bind_req: cli_krb5_get_ticket for principal %s "
1508                         "failed with %s\n",
1509                         a->service_principal,
1510                         error_message(ret) ));
1511
1512                 data_blob_free(&tkt);
1513                 return NT_STATUS_INVALID_PARAMETER;
1514         }
1515
1516         /* wrap that up in a nice GSS-API wrapping */
1517         tkt_wrapped = spnego_gen_krb5_wrap(tkt, TOK_ID_KRB_AP_REQ);
1518
1519         data_blob_free(&tkt);
1520
1521         status = dcerpc_push_dcerpc_auth(cli,
1522                                          DCERPC_AUTH_TYPE_KRB5,
1523                                          auth_level,
1524                                          0, /* auth_pad_length */
1525                                          1, /* auth_context_id */
1526                                          &tkt_wrapped,
1527                                          auth_info);
1528         if (!NT_STATUS_IS_OK(status)) {
1529                 data_blob_free(&tkt_wrapped);
1530                 return status;
1531         }
1532
1533         DEBUG(5, ("create_krb5_auth_bind_req: Created krb5 GSS blob :\n"));
1534         dump_data(5, tkt_wrapped.data, tkt_wrapped.length);
1535
1536         return NT_STATUS_OK;
1537 #else
1538         return NT_STATUS_INVALID_PARAMETER;
1539 #endif
1540 }
1541
1542 /*******************************************************************
1543  Creates SPNEGO NTLMSSP auth bind.
1544  ********************************************************************/
1545
1546 static NTSTATUS create_spnego_ntlmssp_auth_rpc_bind_req(struct rpc_pipe_client *cli,
1547                                                         enum dcerpc_AuthLevel auth_level,
1548                                                         DATA_BLOB *auth_info)
1549 {
1550         NTSTATUS status;
1551         DATA_BLOB null_blob = data_blob_null;
1552         DATA_BLOB request = data_blob_null;
1553         DATA_BLOB spnego_msg = data_blob_null;
1554
1555         DEBUG(5, ("create_spnego_ntlmssp_auth_rpc_bind_req: Processing NTLMSSP Negotiate\n"));
1556         status = ntlmssp_update(cli->auth->a_u.ntlmssp_state,
1557                                         null_blob,
1558                                         &request);
1559
1560         if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1561                 data_blob_free(&request);
1562                 return status;
1563         }
1564
1565         /* Wrap this in SPNEGO. */
1566         spnego_msg = gen_negTokenInit(OID_NTLMSSP, request);
1567
1568         data_blob_free(&request);
1569
1570         status = dcerpc_push_dcerpc_auth(cli,
1571                                          DCERPC_AUTH_TYPE_SPNEGO,
1572                                          auth_level,
1573                                          0, /* auth_pad_length */
1574                                          1, /* auth_context_id */
1575                                          &spnego_msg,
1576                                          auth_info);
1577         if (!NT_STATUS_IS_OK(status)) {
1578                 data_blob_free(&spnego_msg);
1579                 return status;
1580         }
1581
1582         DEBUG(5, ("create_spnego_ntlmssp_auth_rpc_bind_req: NTLMSSP Negotiate:\n"));
1583         dump_data(5, spnego_msg.data, spnego_msg.length);
1584
1585         return NT_STATUS_OK;
1586 }
1587
1588 /*******************************************************************
1589  Creates NTLMSSP auth bind.
1590  ********************************************************************/
1591
1592 static NTSTATUS create_ntlmssp_auth_rpc_bind_req(struct rpc_pipe_client *cli,
1593                                                  enum dcerpc_AuthLevel auth_level,
1594                                                  DATA_BLOB *auth_info)
1595 {
1596         NTSTATUS status;
1597         DATA_BLOB null_blob = data_blob_null;
1598         DATA_BLOB request = data_blob_null;
1599
1600         DEBUG(5, ("create_ntlmssp_auth_rpc_bind_req: Processing NTLMSSP Negotiate\n"));
1601         status = ntlmssp_update(cli->auth->a_u.ntlmssp_state,
1602                                         null_blob,
1603                                         &request);
1604
1605         if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1606                 data_blob_free(&request);
1607                 return status;
1608         }
1609
1610         status = dcerpc_push_dcerpc_auth(cli,
1611                                          DCERPC_AUTH_TYPE_NTLMSSP,
1612                                          auth_level,
1613                                          0, /* auth_pad_length */
1614                                          1, /* auth_context_id */
1615                                          &request,
1616                                          auth_info);
1617         if (!NT_STATUS_IS_OK(status)) {
1618                 data_blob_free(&request);
1619                 return status;
1620         }
1621
1622         DEBUG(5, ("create_ntlmssp_auth_rpc_bind_req: NTLMSSP Negotiate:\n"));
1623         dump_data(5, request.data, request.length);
1624
1625         return NT_STATUS_OK;
1626 }
1627
1628 /*******************************************************************
1629  Creates schannel auth bind.
1630  ********************************************************************/
1631
1632 static NTSTATUS create_schannel_auth_rpc_bind_req(struct rpc_pipe_client *cli,
1633                                                   enum dcerpc_AuthLevel auth_level,
1634                                                   DATA_BLOB *auth_info)
1635 {
1636         NTSTATUS status;
1637         struct NL_AUTH_MESSAGE r;
1638         DATA_BLOB schannel_blob;
1639
1640         /* Use lp_workgroup() if domain not specified */
1641
1642         if (!cli->auth->domain || !cli->auth->domain[0]) {
1643                 cli->auth->domain = talloc_strdup(cli, lp_workgroup());
1644                 if (cli->auth->domain == NULL) {
1645                         return NT_STATUS_NO_MEMORY;
1646                 }
1647         }
1648
1649         /*
1650          * Now marshall the data into the auth parse_struct.
1651          */
1652
1653         r.MessageType                   = NL_NEGOTIATE_REQUEST;
1654         r.Flags                         = NL_FLAG_OEM_NETBIOS_DOMAIN_NAME |
1655                                           NL_FLAG_OEM_NETBIOS_COMPUTER_NAME;
1656         r.oem_netbios_domain.a          = cli->auth->domain;
1657         r.oem_netbios_computer.a        = global_myname();
1658
1659         status = dcerpc_push_schannel_bind(cli, &r, &schannel_blob);
1660         if (!NT_STATUS_IS_OK(status)) {
1661                 return status;
1662         }
1663
1664         status = dcerpc_push_dcerpc_auth(cli,
1665                                          DCERPC_AUTH_TYPE_SCHANNEL,
1666                                          auth_level,
1667                                          0, /* auth_pad_length */
1668                                          1, /* auth_context_id */
1669                                          &schannel_blob,
1670                                          auth_info);
1671         if (!NT_STATUS_IS_OK(status)) {
1672                 return status;
1673         }
1674
1675         return NT_STATUS_OK;
1676 }
1677
1678 /*******************************************************************
1679  Creates the internals of a DCE/RPC bind request or alter context PDU.
1680  ********************************************************************/
1681
1682 static NTSTATUS create_bind_or_alt_ctx_internal(enum dcerpc_pkt_type ptype,
1683                                                 prs_struct *rpc_out, 
1684                                                 uint32 rpc_call_id,
1685                                                 const struct ndr_syntax_id *abstract,
1686                                                 const struct ndr_syntax_id *transfer,
1687                                                 const DATA_BLOB *auth_info)
1688 {
1689         uint16 auth_len = auth_info->length;
1690         NTSTATUS status;
1691         union dcerpc_payload u;
1692         DATA_BLOB blob;
1693         struct dcerpc_ctx_list ctx_list;
1694
1695         if (auth_len) {
1696                 auth_len -= DCERPC_AUTH_TRAILER_LENGTH;
1697         }
1698
1699         ctx_list.context_id = 0;
1700         ctx_list.num_transfer_syntaxes = 1;
1701         ctx_list.abstract_syntax = *abstract;
1702         ctx_list.transfer_syntaxes = discard_const(transfer);
1703
1704         u.bind.max_xmit_frag    = RPC_MAX_PDU_FRAG_LEN;
1705         u.bind.max_recv_frag    = RPC_MAX_PDU_FRAG_LEN;
1706         u.bind.assoc_group_id   = 0x0;
1707         u.bind.num_contexts     = 1;
1708         u.bind.ctx_list         = &ctx_list;
1709         u.bind.auth_info        = *auth_info;
1710
1711         status = dcerpc_push_ncacn_packet(rpc_out->mem_ctx,
1712                                           ptype,
1713                                           DCERPC_PFC_FLAG_FIRST |
1714                                           DCERPC_PFC_FLAG_LAST,
1715                                           auth_len,
1716                                           rpc_call_id,
1717                                           &u,
1718                                           &blob);
1719         if (!NT_STATUS_IS_OK(status)) {
1720                 DEBUG(0,("create_bind_or_alt_ctx_internal: failed to marshall RPC_HDR_RB.\n"));
1721                 return status;
1722         }
1723
1724         if (!prs_copy_data_in(rpc_out, (char *)blob.data, blob.length)) {
1725                 return NT_STATUS_NO_MEMORY;
1726         }
1727
1728         return NT_STATUS_OK;
1729 }
1730
1731 /*******************************************************************
1732  Creates a DCE/RPC bind request.
1733  ********************************************************************/
1734
1735 static NTSTATUS create_rpc_bind_req(struct rpc_pipe_client *cli,
1736                                     prs_struct *rpc_out,
1737                                     uint32 rpc_call_id,
1738                                     const struct ndr_syntax_id *abstract,
1739                                     const struct ndr_syntax_id *transfer,
1740                                     enum pipe_auth_type auth_type,
1741                                     enum dcerpc_AuthLevel auth_level)
1742 {
1743         DATA_BLOB auth_info = data_blob_null;
1744         NTSTATUS ret = NT_STATUS_OK;
1745
1746         switch (auth_type) {
1747                 case PIPE_AUTH_TYPE_SCHANNEL:
1748                         ret = create_schannel_auth_rpc_bind_req(cli, auth_level, &auth_info);
1749                         if (!NT_STATUS_IS_OK(ret)) {
1750                                 return ret;
1751                         }
1752                         break;
1753
1754                 case PIPE_AUTH_TYPE_NTLMSSP:
1755                         ret = create_ntlmssp_auth_rpc_bind_req(cli, auth_level, &auth_info);
1756                         if (!NT_STATUS_IS_OK(ret)) {
1757                                 return ret;
1758                         }
1759                         break;
1760
1761                 case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP:
1762                         ret = create_spnego_ntlmssp_auth_rpc_bind_req(cli, auth_level, &auth_info);
1763                         if (!NT_STATUS_IS_OK(ret)) {
1764                                 return ret;
1765                         }
1766                         break;
1767
1768                 case PIPE_AUTH_TYPE_KRB5:
1769                         ret = create_krb5_auth_bind_req(cli, auth_level, &auth_info);
1770                         if (!NT_STATUS_IS_OK(ret)) {
1771                                 return ret;
1772                         }
1773                         break;
1774
1775                 case PIPE_AUTH_TYPE_NONE:
1776                         break;
1777
1778                 default:
1779                         /* "Can't" happen. */
1780                         return NT_STATUS_INVALID_INFO_CLASS;
1781         }
1782
1783         ret = create_bind_or_alt_ctx_internal(DCERPC_PKT_BIND,
1784                                               rpc_out,
1785                                               rpc_call_id,
1786                                               abstract,
1787                                               transfer,
1788                                               &auth_info);
1789         return ret;
1790 }
1791
1792 /*******************************************************************
1793  Create and add the NTLMSSP sign/seal auth header and data.
1794  ********************************************************************/
1795
1796 static NTSTATUS add_ntlmssp_auth_footer(struct rpc_pipe_client *cli,
1797                                         uint32 ss_padding_len,
1798                                         prs_struct *rpc_out)
1799 {
1800         DATA_BLOB auth_info;
1801         NTSTATUS status;
1802         DATA_BLOB auth_blob = data_blob_null;
1803         uint16_t data_and_pad_len = prs_offset(rpc_out)
1804                                                 - DCERPC_RESPONSE_LENGTH;
1805
1806         if (!cli->auth->a_u.ntlmssp_state) {
1807                 return NT_STATUS_INVALID_PARAMETER;
1808         }
1809
1810         /* marshall the dcerpc_auth with an actually empty auth_blob.
1811          * this is needed because the ntmlssp signature includes the
1812          * auth header */
1813         status = dcerpc_push_dcerpc_auth(prs_get_mem_context(rpc_out),
1814                                         map_pipe_auth_type_to_rpc_auth_type(cli->auth->auth_type),
1815                                         cli->auth->auth_level,
1816                                         ss_padding_len,
1817                                         1 /* context id. */,
1818                                         &auth_blob,
1819                                         &auth_info);
1820         if (!NT_STATUS_IS_OK(status)) {
1821                 return status;
1822         }
1823
1824         /* append the header */
1825         if (!prs_copy_data_in(rpc_out,
1826                                 (char *)auth_info.data,
1827                                 auth_info.length)) {
1828                 DEBUG(0, ("Failed to add %u bytes auth blob.\n",
1829                           (unsigned int)auth_info.length));
1830                 return NT_STATUS_NO_MEMORY;
1831         }
1832
1833         switch (cli->auth->auth_level) {
1834         case DCERPC_AUTH_LEVEL_PRIVACY:
1835                 /* Data portion is encrypted. */
1836                 status = ntlmssp_seal_packet(cli->auth->a_u.ntlmssp_state,
1837                                         prs_get_mem_context(rpc_out),
1838                                         (unsigned char *)prs_data_p(rpc_out)
1839                                                 + DCERPC_RESPONSE_LENGTH,
1840                                         data_and_pad_len,
1841                                         (unsigned char *)prs_data_p(rpc_out),
1842                                         (size_t)prs_offset(rpc_out),
1843                                         &auth_blob);
1844                 if (!NT_STATUS_IS_OK(status)) {
1845                         return status;
1846                 }
1847                 break;
1848
1849         case DCERPC_AUTH_LEVEL_INTEGRITY:
1850                 /* Data is signed. */
1851                 status = ntlmssp_sign_packet(cli->auth->a_u.ntlmssp_state,
1852                                         prs_get_mem_context(rpc_out),
1853                                         (unsigned char *)prs_data_p(rpc_out)
1854                                                 + DCERPC_RESPONSE_LENGTH,
1855                                         data_and_pad_len,
1856                                         (unsigned char *)prs_data_p(rpc_out),
1857                                         (size_t)prs_offset(rpc_out),
1858                                         &auth_blob);
1859                 if (!NT_STATUS_IS_OK(status)) {
1860                         return status;
1861                 }
1862                 break;
1863
1864         default:
1865                 /* Can't happen. */
1866                 smb_panic("bad auth level");
1867                 /* Notreached. */
1868                 return NT_STATUS_INVALID_PARAMETER;
1869         }
1870
1871         /* Finally attach the blob. */
1872         if (!prs_copy_data_in(rpc_out,
1873                                 (char *)auth_blob.data,
1874                                 auth_blob.length)) {
1875                 DEBUG(0, ("Failed to add %u bytes auth blob.\n",
1876                           (unsigned int)auth_info.length));
1877                 return NT_STATUS_NO_MEMORY;
1878         }
1879
1880         return NT_STATUS_OK;
1881 }
1882
1883 /*******************************************************************
1884  Create and add the schannel sign/seal auth header and data.
1885  ********************************************************************/
1886
1887 static NTSTATUS add_schannel_auth_footer(struct rpc_pipe_client *cli,
1888                                         uint32 ss_padding_len,
1889                                         prs_struct *rpc_out)
1890 {
1891         DATA_BLOB auth_info;
1892         struct schannel_state *sas = cli->auth->a_u.schannel_auth;
1893         char *data_p = prs_data_p(rpc_out) + DCERPC_RESPONSE_LENGTH;
1894         size_t data_and_pad_len = prs_offset(rpc_out)
1895                                         - DCERPC_RESPONSE_LENGTH;
1896         DATA_BLOB blob;
1897         NTSTATUS status;
1898
1899         if (!sas) {
1900                 return NT_STATUS_INVALID_PARAMETER;
1901         }
1902
1903         DEBUG(10,("add_schannel_auth_footer: SCHANNEL seq_num=%d\n",
1904                         sas->seq_num));
1905
1906         switch (cli->auth->auth_level) {
1907         case DCERPC_AUTH_LEVEL_PRIVACY:
1908                 status = netsec_outgoing_packet(sas,
1909                                                 talloc_tos(),
1910                                                 true,
1911                                                 (uint8_t *)data_p,
1912                                                 data_and_pad_len,
1913                                                 &blob);
1914                 break;
1915         case DCERPC_AUTH_LEVEL_INTEGRITY:
1916                 status = netsec_outgoing_packet(sas,
1917                                                 talloc_tos(),
1918                                                 false,
1919                                                 (uint8_t *)data_p,
1920                                                 data_and_pad_len,
1921                                                 &blob);
1922                 break;
1923         default:
1924                 status = NT_STATUS_INTERNAL_ERROR;
1925                 break;
1926         }
1927
1928         if (!NT_STATUS_IS_OK(status)) {
1929                 DEBUG(1,("add_schannel_auth_footer: failed to process packet: %s\n",
1930                         nt_errstr(status)));
1931                 return status;
1932         }
1933
1934         if (DEBUGLEVEL >= 10) {
1935                 dump_NL_AUTH_SIGNATURE(talloc_tos(), &blob);
1936         }
1937
1938         /* Finally marshall the blob. */
1939         status = dcerpc_push_dcerpc_auth(prs_get_mem_context(rpc_out),
1940                                         map_pipe_auth_type_to_rpc_auth_type(cli->auth->auth_type),
1941                                         cli->auth->auth_level,
1942                                         ss_padding_len,
1943                                         1 /* context id. */,
1944                                         &blob,
1945                                         &auth_info);
1946         if (!NT_STATUS_IS_OK(status)) {
1947                 return status;
1948         }
1949
1950         if (!prs_copy_data_in(rpc_out, (const char *)auth_info.data, auth_info.length)) {
1951                 return NT_STATUS_NO_MEMORY;
1952         }
1953
1954         return NT_STATUS_OK;
1955 }
1956
1957 /*******************************************************************
1958  Calculate how much data we're going to send in this packet, also
1959  work out any sign/seal padding length.
1960  ********************************************************************/
1961
1962 static uint32 calculate_data_len_tosend(struct rpc_pipe_client *cli,
1963                                         uint32 data_left,
1964                                         uint16 *p_frag_len,
1965                                         uint16 *p_auth_len,
1966                                         uint32 *p_ss_padding)
1967 {
1968         uint32 data_space, data_len;
1969
1970 #if 0
1971         if ((data_left > 0) && (sys_random() % 2)) {
1972                 data_left = MAX(data_left/2, 1);
1973         }
1974 #endif
1975
1976         switch (cli->auth->auth_level) {
1977                 case DCERPC_AUTH_LEVEL_NONE:
1978                 case DCERPC_AUTH_LEVEL_CONNECT:
1979                         data_space = cli->max_xmit_frag - DCERPC_REQUEST_LENGTH;
1980                         data_len = MIN(data_space, data_left);
1981                         *p_ss_padding = 0;
1982                         *p_auth_len = 0;
1983                         *p_frag_len = DCERPC_REQUEST_LENGTH + data_len;
1984                         return data_len;
1985
1986                 case DCERPC_AUTH_LEVEL_INTEGRITY:
1987                 case DCERPC_AUTH_LEVEL_PRIVACY:
1988                         /* Treat the same for all authenticated rpc requests. */
1989                         switch(cli->auth->auth_type) {
1990                                 case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP:
1991                                 case PIPE_AUTH_TYPE_NTLMSSP:
1992                                         *p_auth_len = NTLMSSP_SIG_SIZE;
1993                                         break;
1994                                 case PIPE_AUTH_TYPE_SCHANNEL:
1995                                         *p_auth_len = SCHANNEL_SIG_SIZE;
1996                                         break;
1997                                 default:
1998                                         smb_panic("bad auth type");
1999                                         break;
2000                         }
2001
2002                         data_space = cli->max_xmit_frag
2003                                         - DCERPC_REQUEST_LENGTH
2004                                         - DCERPC_AUTH_TRAILER_LENGTH
2005                                         - *p_auth_len;
2006
2007                         data_len = MIN(data_space, data_left);
2008                         *p_ss_padding = 0;
2009                         if (data_len % CLIENT_NDR_PADDING_SIZE) {
2010                                 *p_ss_padding = CLIENT_NDR_PADDING_SIZE - (data_len % CLIENT_NDR_PADDING_SIZE);
2011                         }
2012                         *p_frag_len = DCERPC_REQUEST_LENGTH
2013                                         + data_len + *p_ss_padding
2014                                         + DCERPC_AUTH_TRAILER_LENGTH
2015                                         + *p_auth_len;
2016                         return data_len;
2017
2018                 default:
2019                         smb_panic("bad auth level");
2020                         /* Notreached. */
2021                         return 0;
2022         }
2023 }
2024
2025 /*******************************************************************
2026  External interface.
2027  Does an rpc request on a pipe. Incoming data is NDR encoded in in_data.
2028  Reply is NDR encoded in out_data. Splits the data stream into RPC PDU's
2029  and deals with signing/sealing details.
2030  ********************************************************************/
2031
2032 struct rpc_api_pipe_req_state {
2033         struct event_context *ev;
2034         struct rpc_pipe_client *cli;
2035         uint8_t op_num;
2036         uint32_t call_id;
2037         prs_struct *req_data;
2038         uint32_t req_data_sent;
2039         prs_struct outgoing_frag;
2040         DATA_BLOB reply_pdu;
2041 };
2042
2043 static void rpc_api_pipe_req_write_done(struct tevent_req *subreq);
2044 static void rpc_api_pipe_req_done(struct tevent_req *subreq);
2045 static NTSTATUS prepare_next_frag(struct rpc_api_pipe_req_state *state,
2046                                   bool *is_last_frag);
2047
2048 struct tevent_req *rpc_api_pipe_req_send(TALLOC_CTX *mem_ctx,
2049                                          struct event_context *ev,
2050                                          struct rpc_pipe_client *cli,
2051                                          uint8_t op_num,
2052                                          prs_struct *req_data)
2053 {
2054         struct tevent_req *req, *subreq;
2055         struct rpc_api_pipe_req_state *state;
2056         NTSTATUS status;
2057         bool is_last_frag;
2058
2059         req = tevent_req_create(mem_ctx, &state,
2060                                 struct rpc_api_pipe_req_state);
2061         if (req == NULL) {
2062                 return NULL;
2063         }
2064         state->ev = ev;
2065         state->cli = cli;
2066         state->op_num = op_num;
2067         state->req_data = req_data;
2068         state->req_data_sent = 0;
2069         state->call_id = get_rpc_call_id();
2070         state->reply_pdu = 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         if (!prs_init(&state->outgoing_frag, cli->max_xmit_frag,
2080                       state, MARSHALL)) {
2081                 goto fail;
2082         }
2083
2084         status = prepare_next_frag(state, &is_last_frag);
2085         if (!NT_STATUS_IS_OK(status)) {
2086                 goto post_status;
2087         }
2088
2089         if (is_last_frag) {
2090                 subreq = rpc_api_pipe_send(state, ev, state->cli,
2091                                            &state->outgoing_frag,
2092                                            DCERPC_PKT_RESPONSE);
2093                 if (subreq == NULL) {
2094                         goto fail;
2095                 }
2096                 tevent_req_set_callback(subreq, rpc_api_pipe_req_done, req);
2097         } else {
2098                 subreq = rpc_write_send(
2099                         state, ev, cli->transport,
2100                         (uint8_t *)prs_data_p(&state->outgoing_frag),
2101                         prs_offset(&state->outgoing_frag));
2102                 if (subreq == NULL) {
2103                         goto fail;
2104                 }
2105                 tevent_req_set_callback(subreq, rpc_api_pipe_req_write_done,
2106                                         req);
2107         }
2108         return req;
2109
2110  post_status:
2111         tevent_req_nterror(req, status);
2112         return tevent_req_post(req, ev);
2113  fail:
2114         TALLOC_FREE(req);
2115         return NULL;
2116 }
2117
2118 static NTSTATUS prepare_next_frag(struct rpc_api_pipe_req_state *state,
2119                                   bool *is_last_frag)
2120 {
2121         uint32_t data_sent_thistime;
2122         uint16_t auth_len;
2123         uint16_t frag_len;
2124         uint8_t flags = 0;
2125         uint32_t ss_padding;
2126         uint32_t data_left;
2127         char pad[8] = { 0, };
2128         NTSTATUS status;
2129         union dcerpc_payload u;
2130         DATA_BLOB blob;
2131
2132         data_left = prs_offset(state->req_data) - state->req_data_sent;
2133
2134         data_sent_thistime = calculate_data_len_tosend(
2135                 state->cli, data_left, &frag_len, &auth_len, &ss_padding);
2136
2137         if (state->req_data_sent == 0) {
2138                 flags = DCERPC_PFC_FLAG_FIRST;
2139         }
2140
2141         if (data_sent_thistime == data_left) {
2142                 flags |= DCERPC_PFC_FLAG_LAST;
2143         }
2144
2145         if (!prs_set_offset(&state->outgoing_frag, 0)) {
2146                 return NT_STATUS_NO_MEMORY;
2147         }
2148
2149         ZERO_STRUCT(u.request);
2150
2151         u.request.alloc_hint    = prs_offset(state->req_data);
2152         u.request.context_id    = 0;
2153         u.request.opnum         = state->op_num;
2154
2155         status = dcerpc_push_ncacn_packet(prs_get_mem_context(&state->outgoing_frag),
2156                                           DCERPC_PKT_REQUEST,
2157                                           flags,
2158                                           auth_len,
2159                                           state->call_id,
2160                                           &u,
2161                                           &blob);
2162         if (!NT_STATUS_IS_OK(status)) {
2163                 return status;
2164         }
2165
2166         /* explicitly set frag_len here as dcerpc_push_ncacn_packet() can't
2167          * compute it right for requests */
2168         dcerpc_set_frag_length(&blob, frag_len);
2169
2170         if (!prs_copy_data_in(&state->outgoing_frag, (const char *)blob.data, blob.length)) {
2171                 return NT_STATUS_NO_MEMORY;
2172         }
2173
2174         /* Copy in the data, plus any ss padding. */
2175         if (!prs_append_some_prs_data(&state->outgoing_frag,
2176                                       state->req_data, state->req_data_sent,
2177                                       data_sent_thistime)) {
2178                 return NT_STATUS_NO_MEMORY;
2179         }
2180
2181         /* Copy the sign/seal padding data. */
2182         if (!prs_copy_data_in(&state->outgoing_frag, pad, ss_padding)) {
2183                 return NT_STATUS_NO_MEMORY;
2184         }
2185
2186         /* Generate any auth sign/seal and add the auth footer. */
2187         switch (state->cli->auth->auth_type) {
2188         case PIPE_AUTH_TYPE_NONE:
2189                 status = NT_STATUS_OK;
2190                 break;
2191         case PIPE_AUTH_TYPE_NTLMSSP:
2192         case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP:
2193                 status = add_ntlmssp_auth_footer(state->cli, ss_padding,
2194                                                  &state->outgoing_frag);
2195                 break;
2196         case PIPE_AUTH_TYPE_SCHANNEL:
2197                 status = add_schannel_auth_footer(state->cli, ss_padding,
2198                                                   &state->outgoing_frag);
2199                 break;
2200         default:
2201                 status = NT_STATUS_INVALID_PARAMETER;
2202                 break;
2203         }
2204
2205         state->req_data_sent += data_sent_thistime;
2206         *is_last_frag = ((flags & DCERPC_PFC_FLAG_LAST) != 0);
2207
2208         return status;
2209 }
2210
2211 static void rpc_api_pipe_req_write_done(struct tevent_req *subreq)
2212 {
2213         struct tevent_req *req = tevent_req_callback_data(
2214                 subreq, struct tevent_req);
2215         struct rpc_api_pipe_req_state *state = tevent_req_data(
2216                 req, struct rpc_api_pipe_req_state);
2217         NTSTATUS status;
2218         bool is_last_frag;
2219
2220         status = rpc_write_recv(subreq);
2221         TALLOC_FREE(subreq);
2222         if (!NT_STATUS_IS_OK(status)) {
2223                 tevent_req_nterror(req, status);
2224                 return;
2225         }
2226
2227         status = prepare_next_frag(state, &is_last_frag);
2228         if (!NT_STATUS_IS_OK(status)) {
2229                 tevent_req_nterror(req, status);
2230                 return;
2231         }
2232
2233         if (is_last_frag) {
2234                 subreq = rpc_api_pipe_send(state, state->ev, state->cli,
2235                                            &state->outgoing_frag,
2236                                            DCERPC_PKT_RESPONSE);
2237                 if (tevent_req_nomem(subreq, req)) {
2238                         return;
2239                 }
2240                 tevent_req_set_callback(subreq, rpc_api_pipe_req_done, req);
2241         } else {
2242                 subreq = rpc_write_send(
2243                         state, state->ev,
2244                         state->cli->transport,
2245                         (uint8_t *)prs_data_p(&state->outgoing_frag),
2246                         prs_offset(&state->outgoing_frag));
2247                 if (tevent_req_nomem(subreq, req)) {
2248                         return;
2249                 }
2250                 tevent_req_set_callback(subreq, rpc_api_pipe_req_write_done,
2251                                         req);
2252         }
2253 }
2254
2255 static void rpc_api_pipe_req_done(struct tevent_req *subreq)
2256 {
2257         struct tevent_req *req = tevent_req_callback_data(
2258                 subreq, struct tevent_req);
2259         struct rpc_api_pipe_req_state *state = tevent_req_data(
2260                 req, struct rpc_api_pipe_req_state);
2261         NTSTATUS status;
2262
2263         status = rpc_api_pipe_recv(subreq, state, NULL, &state->reply_pdu);
2264         TALLOC_FREE(subreq);
2265         if (!NT_STATUS_IS_OK(status)) {
2266                 tevent_req_nterror(req, status);
2267                 return;
2268         }
2269         tevent_req_done(req);
2270 }
2271
2272 NTSTATUS rpc_api_pipe_req_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
2273                                DATA_BLOB *reply_pdu)
2274 {
2275         struct rpc_api_pipe_req_state *state = tevent_req_data(
2276                 req, struct rpc_api_pipe_req_state);
2277         NTSTATUS status;
2278
2279         if (tevent_req_is_nterror(req, &status)) {
2280                 /*
2281                  * We always have to initialize to reply pdu, even if there is
2282                  * none. The rpccli_* caller routines expect this.
2283                  */
2284                 *reply_pdu = data_blob_null;
2285                 return status;
2286         }
2287
2288         /* return data to caller and assign it ownership of memory */
2289         reply_pdu->data = talloc_move(mem_ctx, &state->reply_pdu.data);
2290         reply_pdu->length = state->reply_pdu.length;
2291         state->reply_pdu.length = 0;
2292
2293         return NT_STATUS_OK;
2294 }
2295
2296 #if 0
2297 /****************************************************************************
2298  Set the handle state.
2299 ****************************************************************************/
2300
2301 static bool rpc_pipe_set_hnd_state(struct rpc_pipe_client *cli,
2302                                    const char *pipe_name, uint16 device_state)
2303 {
2304         bool state_set = False;
2305         char param[2];
2306         uint16 setup[2]; /* only need 2 uint16 setup parameters */
2307         char *rparam = NULL;
2308         char *rdata = NULL;
2309         uint32 rparam_len, rdata_len;
2310
2311         if (pipe_name == NULL)
2312                 return False;
2313
2314         DEBUG(5,("Set Handle state Pipe[%x]: %s - device state:%x\n",
2315                  cli->fnum, pipe_name, device_state));
2316
2317         /* create parameters: device state */
2318         SSVAL(param, 0, device_state);
2319
2320         /* create setup parameters. */
2321         setup[0] = 0x0001; 
2322         setup[1] = cli->fnum; /* pipe file handle.  got this from an SMBOpenX. */
2323
2324         /* send the data on \PIPE\ */
2325         if (cli_api_pipe(cli->cli, "\\PIPE\\",
2326                     setup, 2, 0,                /* setup, length, max */
2327                     param, 2, 0,                /* param, length, max */
2328                     NULL, 0, 1024,              /* data, length, max */
2329                     &rparam, &rparam_len,        /* return param, length */
2330                     &rdata, &rdata_len))         /* return data, length */
2331         {
2332                 DEBUG(5, ("Set Handle state: return OK\n"));
2333                 state_set = True;
2334         }
2335
2336         SAFE_FREE(rparam);
2337         SAFE_FREE(rdata);
2338
2339         return state_set;
2340 }
2341 #endif
2342
2343 /****************************************************************************
2344  Check the rpc bind acknowledge response.
2345 ****************************************************************************/
2346
2347 static bool check_bind_response(const struct dcerpc_bind_ack *r,
2348                                 const struct ndr_syntax_id *transfer)
2349 {
2350         struct dcerpc_ack_ctx ctx;
2351
2352         if (r->secondary_address_size == 0) {
2353                 DEBUG(4,("Ignoring length check -- ASU bug (server didn't fill in the pipe name correctly)"));
2354         }
2355
2356         if (r->num_results < 1 || !r->ctx_list) {
2357                 return false;
2358         }
2359
2360         ctx = r->ctx_list[0];
2361
2362         /* check the transfer syntax */
2363         if ((ctx.syntax.if_version != transfer->if_version) ||
2364              (memcmp(&ctx.syntax.uuid, &transfer->uuid, sizeof(transfer->uuid)) !=0)) {
2365                 DEBUG(2,("bind_rpc_pipe: transfer syntax differs\n"));
2366                 return False;
2367         }
2368
2369         if (r->num_results != 0x1 || ctx.result != 0) {
2370                 DEBUG(2,("bind_rpc_pipe: bind denied results: %d reason: %x\n",
2371                           r->num_results, ctx.reason));
2372         }
2373
2374         DEBUG(5,("check_bind_response: accepted!\n"));
2375         return True;
2376 }
2377
2378 /*******************************************************************
2379  Creates a DCE/RPC bind authentication response.
2380  This is the packet that is sent back to the server once we
2381  have received a BIND-ACK, to finish the third leg of
2382  the authentication handshake.
2383  ********************************************************************/
2384
2385 static NTSTATUS create_rpc_bind_auth3(struct rpc_pipe_client *cli,
2386                                 uint32 rpc_call_id,
2387                                 enum pipe_auth_type auth_type,
2388                                 enum dcerpc_AuthLevel auth_level,
2389                                 DATA_BLOB *pauth_blob,
2390                                 prs_struct *rpc_out)
2391 {
2392         NTSTATUS status;
2393         union dcerpc_payload u;
2394         DATA_BLOB blob;
2395
2396         u.auth3._pad = 0;
2397
2398         status = dcerpc_push_dcerpc_auth(prs_get_mem_context(rpc_out),
2399                         map_pipe_auth_type_to_rpc_auth_type(auth_type),
2400                                          auth_level,
2401                                          0, /* auth_pad_length */
2402                                          1, /* auth_context_id */
2403                                          pauth_blob,
2404                                          &u.auth3.auth_info);
2405         if (!NT_STATUS_IS_OK(status)) {
2406                 return status;
2407         }
2408
2409         status = dcerpc_push_ncacn_packet(prs_get_mem_context(rpc_out),
2410                                           DCERPC_PKT_AUTH3,
2411                                           DCERPC_PFC_FLAG_FIRST |
2412                                           DCERPC_PFC_FLAG_LAST,
2413                                           pauth_blob->length,
2414                                           rpc_call_id,
2415                                           &u,
2416                                           &blob);
2417         if (!NT_STATUS_IS_OK(status)) {
2418                 DEBUG(0,("create_bind_or_alt_ctx_internal: failed to marshall RPC_HDR_RB.\n"));
2419                 return status;
2420         }
2421
2422         if (!prs_copy_data_in(rpc_out, (char *)blob.data, blob.length)) {
2423                 return NT_STATUS_NO_MEMORY;
2424         }
2425
2426         return NT_STATUS_OK;
2427 }
2428
2429 /*******************************************************************
2430  Creates a DCE/RPC bind alter context authentication request which
2431  may contain a spnego auth blobl
2432  ********************************************************************/
2433
2434 static NTSTATUS create_rpc_alter_context(uint32 rpc_call_id,
2435                                         const struct ndr_syntax_id *abstract,
2436                                         const struct ndr_syntax_id *transfer,
2437                                         enum dcerpc_AuthLevel auth_level,
2438                                         const DATA_BLOB *pauth_blob, /* spnego auth blob already created. */
2439                                         prs_struct *rpc_out)
2440 {
2441         DATA_BLOB auth_info;
2442         NTSTATUS status;
2443
2444         status = dcerpc_push_dcerpc_auth(prs_get_mem_context(rpc_out),
2445                                          DCERPC_AUTH_TYPE_SPNEGO,
2446                                          auth_level,
2447                                          0, /* auth_pad_length */
2448                                          1, /* auth_context_id */
2449                                          pauth_blob,
2450                                          &auth_info);
2451         if (!NT_STATUS_IS_OK(status)) {
2452                 return status;
2453         }
2454
2455
2456         status = create_bind_or_alt_ctx_internal(DCERPC_PKT_ALTER,
2457                                                  rpc_out,
2458                                                  rpc_call_id,
2459                                                  abstract,
2460                                                  transfer,
2461                                                  &auth_info);
2462         if (!NT_STATUS_IS_OK(status)) {
2463                 return status;
2464         }
2465
2466         return status;
2467 }
2468
2469 /****************************************************************************
2470  Do an rpc bind.
2471 ****************************************************************************/
2472
2473 struct rpc_pipe_bind_state {
2474         struct event_context *ev;
2475         struct rpc_pipe_client *cli;
2476         prs_struct rpc_out;
2477         uint32_t rpc_call_id;
2478 };
2479
2480 static void rpc_pipe_bind_step_one_done(struct tevent_req *subreq);
2481 static NTSTATUS rpc_finish_auth3_bind_send(struct tevent_req *req,
2482                                            struct rpc_pipe_bind_state *state,
2483                                            struct ncacn_packet *r);
2484 static void rpc_bind_auth3_write_done(struct tevent_req *subreq);
2485 static NTSTATUS rpc_finish_spnego_ntlmssp_bind_send(struct tevent_req *req,
2486                                                     struct rpc_pipe_bind_state *state,
2487                                                     struct ncacn_packet *r,
2488                                                     DATA_BLOB *reply_pdu);
2489 static void rpc_bind_ntlmssp_api_done(struct tevent_req *subreq);
2490
2491 struct tevent_req *rpc_pipe_bind_send(TALLOC_CTX *mem_ctx,
2492                                       struct event_context *ev,
2493                                       struct rpc_pipe_client *cli,
2494                                       struct cli_pipe_auth_data *auth)
2495 {
2496         struct tevent_req *req, *subreq;
2497         struct rpc_pipe_bind_state *state;
2498         NTSTATUS status;
2499
2500         req = tevent_req_create(mem_ctx, &state, struct rpc_pipe_bind_state);
2501         if (req == NULL) {
2502                 return NULL;
2503         }
2504
2505         DEBUG(5,("Bind RPC Pipe: %s auth_type %u, auth_level %u\n",
2506                 rpccli_pipe_txt(talloc_tos(), cli),
2507                 (unsigned int)auth->auth_type,
2508                 (unsigned int)auth->auth_level ));
2509
2510         state->ev = ev;
2511         state->cli = cli;
2512         state->rpc_call_id = get_rpc_call_id();
2513
2514         prs_init_empty(&state->rpc_out, state, MARSHALL);
2515
2516         cli->auth = talloc_move(cli, &auth);
2517
2518         /* Marshall the outgoing data. */
2519         status = create_rpc_bind_req(cli, &state->rpc_out,
2520                                      state->rpc_call_id,
2521                                      &cli->abstract_syntax,
2522                                      &cli->transfer_syntax,
2523                                      cli->auth->auth_type,
2524                                      cli->auth->auth_level);
2525
2526         if (!NT_STATUS_IS_OK(status)) {
2527                 goto post_status;
2528         }
2529
2530         subreq = rpc_api_pipe_send(state, ev, cli, &state->rpc_out,
2531                                    DCERPC_PKT_BIND_ACK);
2532         if (subreq == NULL) {
2533                 goto fail;
2534         }
2535         tevent_req_set_callback(subreq, rpc_pipe_bind_step_one_done, req);
2536         return req;
2537
2538  post_status:
2539         tevent_req_nterror(req, status);
2540         return tevent_req_post(req, ev);
2541  fail:
2542         TALLOC_FREE(req);
2543         return NULL;
2544 }
2545
2546 static void rpc_pipe_bind_step_one_done(struct tevent_req *subreq)
2547 {
2548         struct tevent_req *req = tevent_req_callback_data(
2549                 subreq, struct tevent_req);
2550         struct rpc_pipe_bind_state *state = tevent_req_data(
2551                 req, struct rpc_pipe_bind_state);
2552         DATA_BLOB reply_pdu;
2553         struct ncacn_packet *pkt;
2554         NTSTATUS status;
2555
2556         status = rpc_api_pipe_recv(subreq, talloc_tos(), &pkt, &reply_pdu);
2557         TALLOC_FREE(subreq);
2558         if (!NT_STATUS_IS_OK(status)) {
2559                 DEBUG(3, ("rpc_pipe_bind: %s bind request returned %s\n",
2560                           rpccli_pipe_txt(talloc_tos(), state->cli),
2561                           nt_errstr(status)));
2562                 tevent_req_nterror(req, status);
2563                 return;
2564         }
2565
2566         if (!check_bind_response(&pkt->u.bind_ack, &state->cli->transfer_syntax)) {
2567                 DEBUG(2, ("rpc_pipe_bind: check_bind_response failed.\n"));
2568                 tevent_req_nterror(req, NT_STATUS_BUFFER_TOO_SMALL);
2569                 return;
2570         }
2571
2572         state->cli->max_xmit_frag = pkt->u.bind_ack.max_xmit_frag;
2573         state->cli->max_recv_frag = pkt->u.bind_ack.max_recv_frag;
2574
2575         /*
2576          * For authenticated binds we may need to do 3 or 4 leg binds.
2577          */
2578
2579         switch(state->cli->auth->auth_type) {
2580
2581         case PIPE_AUTH_TYPE_NONE:
2582         case PIPE_AUTH_TYPE_SCHANNEL:
2583                 /* Bind complete. */
2584                 tevent_req_done(req);
2585                 break;
2586
2587         case PIPE_AUTH_TYPE_NTLMSSP:
2588                 /* Need to send AUTH3 packet - no reply. */
2589                 status = rpc_finish_auth3_bind_send(req, state, pkt);
2590                 if (!NT_STATUS_IS_OK(status)) {
2591                         tevent_req_nterror(req, status);
2592                 }
2593                 break;
2594
2595         case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP:
2596                 /* Need to send alter context request and reply. */
2597                 status = rpc_finish_spnego_ntlmssp_bind_send(req, state, pkt,
2598                                                              &reply_pdu);
2599                 if (!NT_STATUS_IS_OK(status)) {
2600                         tevent_req_nterror(req, status);
2601                 }
2602                 break;
2603
2604         case PIPE_AUTH_TYPE_KRB5:
2605                 /* */
2606
2607         default:
2608                 DEBUG(0,("cli_finish_bind_auth: unknown auth type %u\n",
2609                          (unsigned int)state->cli->auth->auth_type));
2610                 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
2611         }
2612 }
2613
2614 static NTSTATUS rpc_finish_auth3_bind_send(struct tevent_req *req,
2615                                            struct rpc_pipe_bind_state *state,
2616                                            struct ncacn_packet *r)
2617 {
2618         DATA_BLOB client_reply = data_blob_null;
2619         struct dcerpc_auth auth;
2620         struct tevent_req *subreq;
2621         NTSTATUS status;
2622
2623         if ((r->auth_length == 0)
2624             || (r->frag_length < DCERPC_AUTH_TRAILER_LENGTH
2625                                         + r->auth_length)) {
2626                 return NT_STATUS_INVALID_PARAMETER;
2627         }
2628
2629         status = dcerpc_pull_dcerpc_auth(talloc_tos(),
2630                                          &r->u.bind_ack.auth_info,
2631                                          &auth);
2632         if (!NT_STATUS_IS_OK(status)) {
2633                 DEBUG(0, ("Failed to pull dcerpc auth: %s.\n",
2634                           nt_errstr(status)));
2635                 return status;
2636         }
2637
2638         /* TODO - check auth_type/auth_level match. */
2639
2640         status = ntlmssp_update(state->cli->auth->a_u.ntlmssp_state,
2641                                 auth.credentials, &client_reply);
2642
2643         if (!NT_STATUS_IS_OK(status)) {
2644                 DEBUG(0, ("rpc_finish_auth3_bind: NTLMSSP update using server "
2645                           "blob failed: %s.\n", nt_errstr(status)));
2646                 return status;
2647         }
2648
2649         prs_init_empty(&state->rpc_out, talloc_tos(), MARSHALL);
2650
2651         status = create_rpc_bind_auth3(state->cli, state->rpc_call_id,
2652                                        state->cli->auth->auth_type,
2653                                        state->cli->auth->auth_level,
2654                                        &client_reply, &state->rpc_out);
2655         data_blob_free(&client_reply);
2656
2657         if (!NT_STATUS_IS_OK(status)) {
2658                 return status;
2659         }
2660
2661         subreq = rpc_write_send(state, state->ev, state->cli->transport,
2662                                 (uint8_t *)prs_data_p(&state->rpc_out),
2663                                 prs_offset(&state->rpc_out));
2664         if (subreq == NULL) {
2665                 return NT_STATUS_NO_MEMORY;
2666         }
2667         tevent_req_set_callback(subreq, rpc_bind_auth3_write_done, req);
2668         return NT_STATUS_OK;
2669 }
2670
2671 static void rpc_bind_auth3_write_done(struct tevent_req *subreq)
2672 {
2673         struct tevent_req *req = tevent_req_callback_data(
2674                 subreq, struct tevent_req);
2675         NTSTATUS status;
2676
2677         status = rpc_write_recv(subreq);
2678         TALLOC_FREE(subreq);
2679         if (!NT_STATUS_IS_OK(status)) {
2680                 tevent_req_nterror(req, status);
2681                 return;
2682         }
2683         tevent_req_done(req);
2684 }
2685
2686 static NTSTATUS rpc_finish_spnego_ntlmssp_bind_send(struct tevent_req *req,
2687                                                     struct rpc_pipe_bind_state *state,
2688                                                     struct ncacn_packet *r,
2689                                                     DATA_BLOB *reply_pdu)
2690 {
2691         DATA_BLOB server_ntlm_response = data_blob_null;
2692         DATA_BLOB client_reply = data_blob_null;
2693         DATA_BLOB tmp_blob = data_blob_null;
2694         struct dcerpc_auth auth_info;
2695         DATA_BLOB auth_blob;
2696         struct tevent_req *subreq;
2697         NTSTATUS status;
2698
2699         if ((r->auth_length == 0)
2700             || (r->frag_length < DCERPC_AUTH_TRAILER_LENGTH
2701                                         + r->auth_length)) {
2702                 return NT_STATUS_INVALID_PARAMETER;
2703         }
2704
2705         /* Process the returned NTLMSSP blob first. */
2706         auth_blob = data_blob_const(reply_pdu->data
2707                                         + r->frag_length
2708                                         - DCERPC_AUTH_TRAILER_LENGTH
2709                                         - r->auth_length,
2710                                     DCERPC_AUTH_TRAILER_LENGTH
2711                                         + r->auth_length);
2712
2713         status = dcerpc_pull_dcerpc_auth(state, &auth_blob, &auth_info);
2714         if (!NT_STATUS_IS_OK(status)) {
2715                 DEBUG(0, ("Failed to unmarshall dcerpc_auth.\n"));
2716                 return status;
2717         }
2718
2719         /*
2720          * The server might give us back two challenges - tmp_blob is for the
2721          * second.
2722          */
2723         if (!spnego_parse_challenge(auth_info.credentials,
2724                                     &server_ntlm_response, &tmp_blob)) {
2725                 data_blob_free(&server_ntlm_response);
2726                 data_blob_free(&tmp_blob);
2727                 return NT_STATUS_INVALID_PARAMETER;
2728         }
2729
2730         /* We're finished with the server spnego response and the tmp_blob. */
2731         data_blob_free(&tmp_blob);
2732
2733         status = ntlmssp_update(state->cli->auth->a_u.ntlmssp_state,
2734                                 server_ntlm_response, &client_reply);
2735
2736         /* Finished with the server_ntlm response */
2737         data_blob_free(&server_ntlm_response);
2738
2739         if (!NT_STATUS_IS_OK(status)) {
2740                 DEBUG(0, ("rpc_finish_spnego_ntlmssp_bind: NTLMSSP update "
2741                           "using server blob failed.\n"));
2742                 data_blob_free(&client_reply);
2743                 return status;
2744         }
2745
2746         /* SPNEGO wrap the client reply. */
2747         tmp_blob = spnego_gen_auth(client_reply);
2748         data_blob_free(&client_reply);
2749         client_reply = tmp_blob;
2750         tmp_blob = data_blob_null;
2751
2752         /* Now prepare the alter context pdu. */
2753         prs_init_empty(&state->rpc_out, state, MARSHALL);
2754
2755         status = create_rpc_alter_context(state->rpc_call_id,
2756                                           &state->cli->abstract_syntax,
2757                                           &state->cli->transfer_syntax,
2758                                           state->cli->auth->auth_level,
2759                                           &client_reply,
2760                                           &state->rpc_out);
2761         data_blob_free(&client_reply);
2762
2763         if (!NT_STATUS_IS_OK(status)) {
2764                 return status;
2765         }
2766
2767         subreq = rpc_api_pipe_send(state, state->ev, state->cli,
2768                                    &state->rpc_out, DCERPC_PKT_ALTER_RESP);
2769         if (subreq == NULL) {
2770                 return NT_STATUS_NO_MEMORY;
2771         }
2772         tevent_req_set_callback(subreq, rpc_bind_ntlmssp_api_done, req);
2773         return NT_STATUS_OK;
2774 }
2775
2776 static void rpc_bind_ntlmssp_api_done(struct tevent_req *subreq)
2777 {
2778         struct tevent_req *req = tevent_req_callback_data(
2779                 subreq, struct tevent_req);
2780         struct rpc_pipe_bind_state *state = tevent_req_data(
2781                 req, struct rpc_pipe_bind_state);
2782         DATA_BLOB tmp_blob = data_blob_null;
2783         struct ncacn_packet *pkt;
2784         struct dcerpc_auth auth;
2785         NTSTATUS status;
2786
2787         status = rpc_api_pipe_recv(subreq, talloc_tos(), &pkt, NULL);
2788         TALLOC_FREE(subreq);
2789         if (!NT_STATUS_IS_OK(status)) {
2790                 tevent_req_nterror(req, status);
2791                 return;
2792         }
2793
2794         status = dcerpc_pull_dcerpc_auth(pkt,
2795                                          &pkt->u.alter_resp.auth_info,
2796                                          &auth);
2797         if (!NT_STATUS_IS_OK(status)) {
2798                 tevent_req_nterror(req, status);
2799                 return;
2800         }
2801
2802         /* Check we got a valid auth response. */
2803         if (!spnego_parse_auth_response(auth.credentials,
2804                                         NT_STATUS_OK,
2805                                         OID_NTLMSSP, &tmp_blob)) {
2806                 data_blob_free(&tmp_blob);
2807                 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
2808                 return;
2809         }
2810
2811         data_blob_free(&tmp_blob);
2812
2813         DEBUG(5,("rpc_finish_spnego_ntlmssp_bind: alter context request to "
2814                  "%s.\n", rpccli_pipe_txt(talloc_tos(), state->cli)));
2815         tevent_req_done(req);
2816 }
2817
2818 NTSTATUS rpc_pipe_bind_recv(struct tevent_req *req)
2819 {
2820         return tevent_req_simple_recv_ntstatus(req);
2821 }
2822
2823 NTSTATUS rpc_pipe_bind(struct rpc_pipe_client *cli,
2824                        struct cli_pipe_auth_data *auth)
2825 {
2826         TALLOC_CTX *frame = talloc_stackframe();
2827         struct event_context *ev;
2828         struct tevent_req *req;
2829         NTSTATUS status = NT_STATUS_OK;
2830
2831         ev = event_context_init(frame);
2832         if (ev == NULL) {
2833                 status = NT_STATUS_NO_MEMORY;
2834                 goto fail;
2835         }
2836
2837         req = rpc_pipe_bind_send(frame, ev, cli, auth);
2838         if (req == NULL) {
2839                 status = NT_STATUS_NO_MEMORY;
2840                 goto fail;
2841         }
2842
2843         if (!tevent_req_poll(req, ev)) {
2844                 status = map_nt_error_from_unix(errno);
2845                 goto fail;
2846         }
2847
2848         status = rpc_pipe_bind_recv(req);
2849  fail:
2850         TALLOC_FREE(frame);
2851         return status;
2852 }
2853
2854 #define RPCCLI_DEFAULT_TIMEOUT 10000 /* 10 seconds. */
2855
2856 unsigned int rpccli_set_timeout(struct rpc_pipe_client *rpc_cli,
2857                                 unsigned int timeout)
2858 {
2859         unsigned int old;
2860
2861         if (rpc_cli->transport == NULL) {
2862                 return RPCCLI_DEFAULT_TIMEOUT;
2863         }
2864
2865         if (rpc_cli->transport->set_timeout == NULL) {
2866                 return RPCCLI_DEFAULT_TIMEOUT;
2867         }
2868
2869         old = rpc_cli->transport->set_timeout(rpc_cli->transport->priv, timeout);
2870         if (old == 0) {
2871                 return RPCCLI_DEFAULT_TIMEOUT;
2872         }
2873
2874         return old;
2875 }
2876
2877 bool rpccli_is_connected(struct rpc_pipe_client *rpc_cli)
2878 {
2879         if (rpc_cli == NULL) {
2880                 return false;
2881         }
2882
2883         if (rpc_cli->transport == NULL) {
2884                 return false;
2885         }
2886
2887         return rpc_cli->transport->is_connected(rpc_cli->transport->priv);
2888 }
2889
2890 bool rpccli_get_pwd_hash(struct rpc_pipe_client *rpc_cli, uint8_t nt_hash[16])
2891 {
2892         struct cli_state *cli;
2893
2894         if ((rpc_cli->auth->auth_type == PIPE_AUTH_TYPE_NTLMSSP)
2895             || (rpc_cli->auth->auth_type == PIPE_AUTH_TYPE_SPNEGO_NTLMSSP)) {
2896                 memcpy(nt_hash, rpc_cli->auth->a_u.ntlmssp_state->nt_hash, 16);
2897                 return true;
2898         }
2899
2900         cli = rpc_pipe_np_smb_conn(rpc_cli);
2901         if (cli == NULL) {
2902                 return false;
2903         }
2904         E_md4hash(cli->password ? cli->password : "", nt_hash);
2905         return true;
2906 }
2907
2908 NTSTATUS rpccli_anon_bind_data(TALLOC_CTX *mem_ctx,
2909                                struct cli_pipe_auth_data **presult)
2910 {
2911         struct cli_pipe_auth_data *result;
2912
2913         result = talloc(mem_ctx, struct cli_pipe_auth_data);
2914         if (result == NULL) {
2915                 return NT_STATUS_NO_MEMORY;
2916         }
2917
2918         result->auth_type = PIPE_AUTH_TYPE_NONE;
2919         result->auth_level = DCERPC_AUTH_LEVEL_NONE;
2920
2921         result->user_name = talloc_strdup(result, "");
2922         result->domain = talloc_strdup(result, "");
2923         if ((result->user_name == NULL) || (result->domain == NULL)) {
2924                 TALLOC_FREE(result);
2925                 return NT_STATUS_NO_MEMORY;
2926         }
2927
2928         *presult = result;
2929         return NT_STATUS_OK;
2930 }
2931
2932 static int cli_auth_ntlmssp_data_destructor(struct cli_pipe_auth_data *auth)
2933 {
2934         ntlmssp_end(&auth->a_u.ntlmssp_state);
2935         return 0;
2936 }
2937
2938 static NTSTATUS rpccli_ntlmssp_bind_data(TALLOC_CTX *mem_ctx,
2939                                   enum pipe_auth_type auth_type,
2940                                   enum dcerpc_AuthLevel auth_level,
2941                                   const char *domain,
2942                                   const char *username,
2943                                   const char *password,
2944                                   struct cli_pipe_auth_data **presult)
2945 {
2946         struct cli_pipe_auth_data *result;
2947         NTSTATUS status;
2948
2949         result = talloc(mem_ctx, struct cli_pipe_auth_data);
2950         if (result == NULL) {
2951                 return NT_STATUS_NO_MEMORY;
2952         }
2953
2954         result->auth_type = auth_type;
2955         result->auth_level = auth_level;
2956
2957         result->user_name = talloc_strdup(result, username);
2958         result->domain = talloc_strdup(result, domain);
2959         if ((result->user_name == NULL) || (result->domain == NULL)) {
2960                 status = NT_STATUS_NO_MEMORY;
2961                 goto fail;
2962         }
2963
2964         status = ntlmssp_client_start(NULL,
2965                                       global_myname(),
2966                                       lp_workgroup(),
2967                                       lp_client_ntlmv2_auth(),
2968                                       &result->a_u.ntlmssp_state);
2969         if (!NT_STATUS_IS_OK(status)) {
2970                 goto fail;
2971         }
2972
2973         talloc_set_destructor(result, cli_auth_ntlmssp_data_destructor);
2974
2975         status = ntlmssp_set_username(result->a_u.ntlmssp_state, username);
2976         if (!NT_STATUS_IS_OK(status)) {
2977                 goto fail;
2978         }
2979
2980         status = ntlmssp_set_domain(result->a_u.ntlmssp_state, domain);
2981         if (!NT_STATUS_IS_OK(status)) {
2982                 goto fail;
2983         }
2984
2985         status = ntlmssp_set_password(result->a_u.ntlmssp_state, password);
2986         if (!NT_STATUS_IS_OK(status)) {
2987                 goto fail;
2988         }
2989
2990         /*
2991          * Turn off sign+seal to allow selected auth level to turn it back on.
2992          */
2993         result->a_u.ntlmssp_state->neg_flags &=
2994                 ~(NTLMSSP_NEGOTIATE_SIGN | NTLMSSP_NEGOTIATE_SEAL);
2995
2996         if (auth_level == DCERPC_AUTH_LEVEL_INTEGRITY) {
2997                 result->a_u.ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SIGN;
2998         } else if (auth_level == DCERPC_AUTH_LEVEL_PRIVACY) {
2999                 result->a_u.ntlmssp_state->neg_flags
3000                         |= NTLMSSP_NEGOTIATE_SEAL | NTLMSSP_NEGOTIATE_SIGN;
3001         }
3002
3003         *presult = result;
3004         return NT_STATUS_OK;
3005
3006  fail:
3007         TALLOC_FREE(result);
3008         return status;
3009 }
3010
3011 NTSTATUS rpccli_schannel_bind_data(TALLOC_CTX *mem_ctx, const char *domain,
3012                                    enum dcerpc_AuthLevel auth_level,
3013                                    struct netlogon_creds_CredentialState *creds,
3014                                    struct cli_pipe_auth_data **presult)
3015 {
3016         struct cli_pipe_auth_data *result;
3017
3018         result = talloc(mem_ctx, struct cli_pipe_auth_data);
3019         if (result == NULL) {
3020                 return NT_STATUS_NO_MEMORY;
3021         }
3022
3023         result->auth_type = PIPE_AUTH_TYPE_SCHANNEL;
3024         result->auth_level = auth_level;
3025
3026         result->user_name = talloc_strdup(result, "");
3027         result->domain = talloc_strdup(result, domain);
3028         if ((result->user_name == NULL) || (result->domain == NULL)) {
3029                 goto fail;
3030         }
3031
3032         result->a_u.schannel_auth = talloc(result, struct schannel_state);
3033         if (result->a_u.schannel_auth == NULL) {
3034                 goto fail;
3035         }
3036
3037         result->a_u.schannel_auth->state = SCHANNEL_STATE_START;
3038         result->a_u.schannel_auth->seq_num = 0;
3039         result->a_u.schannel_auth->initiator = true;
3040         result->a_u.schannel_auth->creds = creds;
3041
3042         *presult = result;
3043         return NT_STATUS_OK;
3044
3045  fail:
3046         TALLOC_FREE(result);
3047         return NT_STATUS_NO_MEMORY;
3048 }
3049
3050 #ifdef HAVE_KRB5
3051 static int cli_auth_kerberos_data_destructor(struct kerberos_auth_struct *auth)
3052 {
3053         data_blob_free(&auth->session_key);
3054         return 0;
3055 }
3056 #endif
3057
3058 static NTSTATUS rpccli_kerberos_bind_data(TALLOC_CTX *mem_ctx,
3059                                    enum dcerpc_AuthLevel auth_level,
3060                                    const char *service_princ,
3061                                    const char *username,
3062                                    const char *password,
3063                                    struct cli_pipe_auth_data **presult)
3064 {
3065 #ifdef HAVE_KRB5
3066         struct cli_pipe_auth_data *result;
3067
3068         if ((username != NULL) && (password != NULL)) {
3069                 int ret = kerberos_kinit_password(username, password, 0, NULL);
3070                 if (ret != 0) {
3071                         return NT_STATUS_ACCESS_DENIED;
3072                 }
3073         }
3074
3075         result = talloc(mem_ctx, struct cli_pipe_auth_data);
3076         if (result == NULL) {
3077                 return NT_STATUS_NO_MEMORY;
3078         }
3079
3080         result->auth_type = PIPE_AUTH_TYPE_KRB5;
3081         result->auth_level = auth_level;
3082
3083         /*
3084          * Username / domain need fixing!
3085          */
3086         result->user_name = talloc_strdup(result, "");
3087         result->domain = talloc_strdup(result, "");
3088         if ((result->user_name == NULL) || (result->domain == NULL)) {
3089                 goto fail;
3090         }
3091
3092         result->a_u.kerberos_auth = TALLOC_ZERO_P(
3093                 result, struct kerberos_auth_struct);
3094         if (result->a_u.kerberos_auth == NULL) {
3095                 goto fail;
3096         }
3097         talloc_set_destructor(result->a_u.kerberos_auth,
3098                               cli_auth_kerberos_data_destructor);
3099
3100         result->a_u.kerberos_auth->service_principal = talloc_strdup(
3101                 result, service_princ);
3102         if (result->a_u.kerberos_auth->service_principal == NULL) {
3103                 goto fail;
3104         }
3105
3106         *presult = result;
3107         return NT_STATUS_OK;
3108
3109  fail:
3110         TALLOC_FREE(result);
3111         return NT_STATUS_NO_MEMORY;
3112 #else
3113         return NT_STATUS_NOT_SUPPORTED;
3114 #endif
3115 }
3116
3117 /**
3118  * Create an rpc pipe client struct, connecting to a tcp port.
3119  */
3120 static NTSTATUS rpc_pipe_open_tcp_port(TALLOC_CTX *mem_ctx, const char *host,
3121                                        uint16_t port,
3122                                        const struct ndr_syntax_id *abstract_syntax,
3123                                        struct rpc_pipe_client **presult)
3124 {
3125         struct rpc_pipe_client *result;
3126         struct sockaddr_storage addr;
3127         NTSTATUS status;
3128         int fd;
3129
3130         result = TALLOC_ZERO_P(mem_ctx, struct rpc_pipe_client);
3131         if (result == NULL) {
3132                 return NT_STATUS_NO_MEMORY;
3133         }
3134
3135         result->abstract_syntax = *abstract_syntax;
3136         result->transfer_syntax = ndr_transfer_syntax;
3137         result->dispatch = cli_do_rpc_ndr;
3138         result->dispatch_send = cli_do_rpc_ndr_send;
3139         result->dispatch_recv = cli_do_rpc_ndr_recv;
3140
3141         result->desthost = talloc_strdup(result, host);
3142         result->srv_name_slash = talloc_asprintf_strupper_m(
3143                 result, "\\\\%s", result->desthost);
3144         if ((result->desthost == NULL) || (result->srv_name_slash == NULL)) {
3145                 status = NT_STATUS_NO_MEMORY;
3146                 goto fail;
3147         }
3148
3149         result->max_xmit_frag = RPC_MAX_PDU_FRAG_LEN;
3150         result->max_recv_frag = RPC_MAX_PDU_FRAG_LEN;
3151
3152         if (!resolve_name(host, &addr, 0, false)) {
3153                 status = NT_STATUS_NOT_FOUND;
3154                 goto fail;
3155         }
3156
3157         status = open_socket_out(&addr, port, 60, &fd);
3158         if (!NT_STATUS_IS_OK(status)) {
3159                 goto fail;
3160         }
3161         set_socket_options(fd, lp_socket_options());
3162
3163         status = rpc_transport_sock_init(result, fd, &result->transport);
3164         if (!NT_STATUS_IS_OK(status)) {
3165                 close(fd);
3166                 goto fail;
3167         }
3168
3169         result->transport->transport = NCACN_IP_TCP;
3170
3171         *presult = result;
3172         return NT_STATUS_OK;
3173
3174  fail:
3175         TALLOC_FREE(result);
3176         return status;
3177 }
3178
3179 /**
3180  * Determine the tcp port on which a dcerpc interface is listening
3181  * for the ncacn_ip_tcp transport via the endpoint mapper of the
3182  * target host.
3183  */
3184 static NTSTATUS rpc_pipe_get_tcp_port(const char *host,
3185                                       const struct ndr_syntax_id *abstract_syntax,
3186                                       uint16_t *pport)
3187 {
3188         NTSTATUS status;
3189         struct rpc_pipe_client *epm_pipe = NULL;
3190         struct cli_pipe_auth_data *auth = NULL;
3191         struct dcerpc_binding *map_binding = NULL;
3192         struct dcerpc_binding *res_binding = NULL;
3193         struct epm_twr_t *map_tower = NULL;
3194         struct epm_twr_t *res_towers = NULL;
3195         struct policy_handle *entry_handle = NULL;
3196         uint32_t num_towers = 0;
3197         uint32_t max_towers = 1;
3198         struct epm_twr_p_t towers;
3199         TALLOC_CTX *tmp_ctx = talloc_stackframe();
3200
3201         if (pport == NULL) {
3202                 status = NT_STATUS_INVALID_PARAMETER;
3203                 goto done;
3204         }
3205
3206         /* open the connection to the endpoint mapper */
3207         status = rpc_pipe_open_tcp_port(tmp_ctx, host, 135,
3208                                         &ndr_table_epmapper.syntax_id,
3209                                         &epm_pipe);
3210
3211         if (!NT_STATUS_IS_OK(status)) {
3212                 goto done;
3213         }
3214
3215         status = rpccli_anon_bind_data(tmp_ctx, &auth);
3216         if (!NT_STATUS_IS_OK(status)) {
3217                 goto done;
3218         }
3219
3220         status = rpc_pipe_bind(epm_pipe, auth);
3221         if (!NT_STATUS_IS_OK(status)) {
3222                 goto done;
3223         }
3224
3225         /* create tower for asking the epmapper */
3226
3227         map_binding = TALLOC_ZERO_P(tmp_ctx, struct dcerpc_binding);
3228         if (map_binding == NULL) {
3229                 status = NT_STATUS_NO_MEMORY;
3230                 goto done;
3231         }
3232
3233         map_binding->transport = NCACN_IP_TCP;
3234         map_binding->object = *abstract_syntax;
3235         map_binding->host = host; /* needed? */
3236         map_binding->endpoint = "0"; /* correct? needed? */
3237
3238         map_tower = TALLOC_ZERO_P(tmp_ctx, struct epm_twr_t);
3239         if (map_tower == NULL) {
3240                 status = NT_STATUS_NO_MEMORY;
3241                 goto done;
3242         }
3243
3244         status = dcerpc_binding_build_tower(tmp_ctx, map_binding,
3245                                             &(map_tower->tower));
3246         if (!NT_STATUS_IS_OK(status)) {
3247                 goto done;
3248         }
3249
3250         /* allocate further parameters for the epm_Map call */
3251
3252         res_towers = TALLOC_ARRAY(tmp_ctx, struct epm_twr_t, max_towers);
3253         if (res_towers == NULL) {
3254                 status = NT_STATUS_NO_MEMORY;
3255                 goto done;
3256         }
3257         towers.twr = res_towers;
3258
3259         entry_handle = TALLOC_ZERO_P(tmp_ctx, struct policy_handle);
3260         if (entry_handle == NULL) {
3261                 status = NT_STATUS_NO_MEMORY;
3262                 goto done;
3263         }
3264
3265         /* ask the endpoint mapper for the port */
3266
3267         status = rpccli_epm_Map(epm_pipe,
3268                                 tmp_ctx,
3269                                 CONST_DISCARD(struct GUID *,
3270                                               &(abstract_syntax->uuid)),
3271                                 map_tower,
3272                                 entry_handle,
3273                                 max_towers,
3274                                 &num_towers,
3275                                 &towers);
3276
3277         if (!NT_STATUS_IS_OK(status)) {
3278                 goto done;
3279         }
3280
3281         if (num_towers != 1) {
3282                 status = NT_STATUS_UNSUCCESSFUL;
3283                 goto done;
3284         }
3285
3286         /* extract the port from the answer */
3287
3288         status = dcerpc_binding_from_tower(tmp_ctx,
3289                                            &(towers.twr->tower),
3290                                            &res_binding);
3291         if (!NT_STATUS_IS_OK(status)) {
3292                 goto done;
3293         }
3294
3295         /* are further checks here necessary? */
3296         if (res_binding->transport != NCACN_IP_TCP) {
3297                 status = NT_STATUS_UNSUCCESSFUL;
3298                 goto done;
3299         }
3300
3301         *pport = (uint16_t)atoi(res_binding->endpoint);
3302
3303 done:
3304         TALLOC_FREE(tmp_ctx);
3305         return status;
3306 }
3307
3308 /**
3309  * Create a rpc pipe client struct, connecting to a host via tcp.
3310  * The port is determined by asking the endpoint mapper on the given
3311  * host.
3312  */
3313 NTSTATUS rpc_pipe_open_tcp(TALLOC_CTX *mem_ctx, const char *host,
3314                            const struct ndr_syntax_id *abstract_syntax,
3315                            struct rpc_pipe_client **presult)
3316 {
3317         NTSTATUS status;
3318         uint16_t port = 0;
3319
3320         status = rpc_pipe_get_tcp_port(host, abstract_syntax, &port);
3321         if (!NT_STATUS_IS_OK(status)) {
3322                 return status;
3323         }
3324
3325         return rpc_pipe_open_tcp_port(mem_ctx, host, port,
3326                                         abstract_syntax, presult);
3327 }
3328
3329 /********************************************************************
3330  Create a rpc pipe client struct, connecting to a unix domain socket
3331  ********************************************************************/
3332 NTSTATUS rpc_pipe_open_ncalrpc(TALLOC_CTX *mem_ctx, const char *socket_path,
3333                                const struct ndr_syntax_id *abstract_syntax,
3334                                struct rpc_pipe_client **presult)
3335 {
3336         struct rpc_pipe_client *result;
3337         struct sockaddr_un addr;
3338         NTSTATUS status;
3339         int fd;
3340
3341         result = talloc_zero(mem_ctx, struct rpc_pipe_client);
3342         if (result == NULL) {
3343                 return NT_STATUS_NO_MEMORY;
3344         }
3345
3346         result->abstract_syntax = *abstract_syntax;
3347         result->transfer_syntax = ndr_transfer_syntax;
3348         result->dispatch = cli_do_rpc_ndr;
3349         result->dispatch_send = cli_do_rpc_ndr_send;
3350         result->dispatch_recv = cli_do_rpc_ndr_recv;
3351
3352         result->desthost = get_myname(result);
3353         result->srv_name_slash = talloc_asprintf_strupper_m(
3354                 result, "\\\\%s", result->desthost);
3355         if ((result->desthost == NULL) || (result->srv_name_slash == NULL)) {
3356                 status = NT_STATUS_NO_MEMORY;
3357                 goto fail;
3358         }
3359
3360         result->max_xmit_frag = RPC_MAX_PDU_FRAG_LEN;
3361         result->max_recv_frag = RPC_MAX_PDU_FRAG_LEN;
3362
3363         fd = socket(AF_UNIX, SOCK_STREAM, 0);
3364         if (fd == -1) {
3365                 status = map_nt_error_from_unix(errno);
3366                 goto fail;
3367         }
3368
3369         ZERO_STRUCT(addr);
3370         addr.sun_family = AF_UNIX;
3371         strncpy(addr.sun_path, socket_path, sizeof(addr.sun_path));
3372
3373         if (sys_connect(fd, (struct sockaddr *)(void *)&addr) == -1) {
3374                 DEBUG(0, ("connect(%s) failed: %s\n", socket_path,
3375                           strerror(errno)));
3376                 close(fd);
3377                 return map_nt_error_from_unix(errno);
3378         }
3379
3380         status = rpc_transport_sock_init(result, fd, &result->transport);
3381         if (!NT_STATUS_IS_OK(status)) {
3382                 close(fd);
3383                 goto fail;
3384         }
3385
3386         result->transport->transport = NCALRPC;
3387
3388         *presult = result;
3389         return NT_STATUS_OK;
3390
3391  fail:
3392         TALLOC_FREE(result);
3393         return status;
3394 }
3395
3396 struct rpc_pipe_client_np_ref {
3397         struct cli_state *cli;
3398         struct rpc_pipe_client *pipe;
3399 };
3400
3401 static int rpc_pipe_client_np_ref_destructor(struct rpc_pipe_client_np_ref *np_ref)
3402 {
3403         DLIST_REMOVE(np_ref->cli->pipe_list, np_ref->pipe);
3404         return 0;
3405 }
3406
3407 /****************************************************************************
3408  Open a named pipe over SMB to a remote server.
3409  *
3410  * CAVEAT CALLER OF THIS FUNCTION:
3411  *    The returned rpc_pipe_client saves a copy of the cli_state cli pointer,
3412  *    so be sure that this function is called AFTER any structure (vs pointer)
3413  *    assignment of the cli.  In particular, libsmbclient does structure
3414  *    assignments of cli, which invalidates the data in the returned
3415  *    rpc_pipe_client if this function is called before the structure assignment
3416  *    of cli.
3417  * 
3418  ****************************************************************************/
3419
3420 static NTSTATUS rpc_pipe_open_np(struct cli_state *cli,
3421                                  const struct ndr_syntax_id *abstract_syntax,
3422                                  struct rpc_pipe_client **presult)
3423 {
3424         struct rpc_pipe_client *result;
3425         NTSTATUS status;
3426         struct rpc_pipe_client_np_ref *np_ref;
3427
3428         /* sanity check to protect against crashes */
3429
3430         if ( !cli ) {
3431                 return NT_STATUS_INVALID_HANDLE;
3432         }
3433
3434         result = TALLOC_ZERO_P(NULL, struct rpc_pipe_client);
3435         if (result == NULL) {
3436                 return NT_STATUS_NO_MEMORY;
3437         }
3438
3439         result->abstract_syntax = *abstract_syntax;
3440         result->transfer_syntax = ndr_transfer_syntax;
3441         result->dispatch = cli_do_rpc_ndr;
3442         result->dispatch_send = cli_do_rpc_ndr_send;
3443         result->dispatch_recv = cli_do_rpc_ndr_recv;
3444         result->desthost = talloc_strdup(result, cli->desthost);
3445         result->srv_name_slash = talloc_asprintf_strupper_m(
3446                 result, "\\\\%s", result->desthost);
3447
3448         result->max_xmit_frag = RPC_MAX_PDU_FRAG_LEN;
3449         result->max_recv_frag = RPC_MAX_PDU_FRAG_LEN;
3450
3451         if ((result->desthost == NULL) || (result->srv_name_slash == NULL)) {
3452                 TALLOC_FREE(result);
3453                 return NT_STATUS_NO_MEMORY;
3454         }
3455
3456         status = rpc_transport_np_init(result, cli, abstract_syntax,
3457                                        &result->transport);
3458         if (!NT_STATUS_IS_OK(status)) {
3459                 TALLOC_FREE(result);
3460                 return status;
3461         }
3462
3463         result->transport->transport = NCACN_NP;
3464
3465         np_ref = talloc(result->transport, struct rpc_pipe_client_np_ref);
3466         if (np_ref == NULL) {
3467                 TALLOC_FREE(result);
3468                 return NT_STATUS_NO_MEMORY;
3469         }
3470         np_ref->cli = cli;
3471         np_ref->pipe = result;
3472
3473         DLIST_ADD(np_ref->cli->pipe_list, np_ref->pipe);
3474         talloc_set_destructor(np_ref, rpc_pipe_client_np_ref_destructor);
3475
3476         *presult = result;
3477         return NT_STATUS_OK;
3478 }
3479
3480 NTSTATUS rpc_pipe_open_local(TALLOC_CTX *mem_ctx,
3481                              struct rpc_cli_smbd_conn *conn,
3482                              const struct ndr_syntax_id *syntax,
3483                              struct rpc_pipe_client **presult)
3484 {
3485         struct rpc_pipe_client *result;
3486         struct cli_pipe_auth_data *auth;
3487         NTSTATUS status;
3488
3489         result = talloc(mem_ctx, struct rpc_pipe_client);
3490         if (result == NULL) {
3491                 return NT_STATUS_NO_MEMORY;
3492         }
3493         result->abstract_syntax = *syntax;
3494         result->transfer_syntax = ndr_transfer_syntax;
3495         result->dispatch = cli_do_rpc_ndr;
3496         result->dispatch_send = cli_do_rpc_ndr_send;
3497         result->dispatch_recv = cli_do_rpc_ndr_recv;
3498         result->max_xmit_frag = RPC_MAX_PDU_FRAG_LEN;
3499         result->max_recv_frag = RPC_MAX_PDU_FRAG_LEN;
3500
3501         result->desthost = talloc_strdup(result, global_myname());
3502         result->srv_name_slash = talloc_asprintf_strupper_m(
3503                 result, "\\\\%s", global_myname());
3504         if ((result->desthost == NULL) || (result->srv_name_slash == NULL)) {
3505                 TALLOC_FREE(result);
3506                 return NT_STATUS_NO_MEMORY;
3507         }
3508
3509         status = rpc_transport_smbd_init(result, conn, syntax,
3510                                          &result->transport);
3511         if (!NT_STATUS_IS_OK(status)) {
3512                 DEBUG(1, ("rpc_transport_smbd_init failed: %s\n",
3513                           nt_errstr(status)));
3514                 TALLOC_FREE(result);
3515                 return status;
3516         }
3517
3518         status = rpccli_anon_bind_data(result, &auth);
3519         if (!NT_STATUS_IS_OK(status)) {
3520                 DEBUG(1, ("rpccli_anon_bind_data failed: %s\n",
3521                           nt_errstr(status)));
3522                 TALLOC_FREE(result);
3523                 return status;
3524         }
3525
3526         status = rpc_pipe_bind(result, auth);
3527         if (!NT_STATUS_IS_OK(status)) {
3528                 DEBUG(1, ("rpc_pipe_bind failed: %s\n", nt_errstr(status)));
3529                 TALLOC_FREE(result);
3530                 return status;
3531         }
3532
3533         result->transport->transport = NCACN_INTERNAL;
3534
3535         *presult = result;
3536         return NT_STATUS_OK;
3537 }
3538
3539 /****************************************************************************
3540  Open a pipe to a remote server.
3541  ****************************************************************************/
3542
3543 static NTSTATUS cli_rpc_pipe_open(struct cli_state *cli,
3544                                   enum dcerpc_transport_t transport,
3545                                   const struct ndr_syntax_id *interface,
3546                                   struct rpc_pipe_client **presult)
3547 {
3548         switch (transport) {
3549         case NCACN_IP_TCP:
3550                 return rpc_pipe_open_tcp(NULL, cli->desthost, interface,
3551                                          presult);
3552         case NCACN_NP:
3553                 return rpc_pipe_open_np(cli, interface, presult);
3554         default:
3555                 return NT_STATUS_NOT_IMPLEMENTED;
3556         }
3557 }
3558
3559 /****************************************************************************
3560  Open a named pipe to an SMB server and bind anonymously.
3561  ****************************************************************************/
3562
3563 NTSTATUS cli_rpc_pipe_open_noauth_transport(struct cli_state *cli,
3564                                             enum dcerpc_transport_t transport,
3565                                             const struct ndr_syntax_id *interface,
3566                                             struct rpc_pipe_client **presult)
3567 {
3568         struct rpc_pipe_client *result;
3569         struct cli_pipe_auth_data *auth;
3570         NTSTATUS status;
3571
3572         status = cli_rpc_pipe_open(cli, transport, interface, &result);
3573         if (!NT_STATUS_IS_OK(status)) {
3574                 return status;
3575         }
3576
3577         status = rpccli_anon_bind_data(result, &auth);
3578         if (!NT_STATUS_IS_OK(status)) {
3579                 DEBUG(0, ("rpccli_anon_bind_data returned %s\n",
3580                           nt_errstr(status)));
3581                 TALLOC_FREE(result);
3582                 return status;
3583         }
3584
3585         /*
3586          * This is a bit of an abstraction violation due to the fact that an
3587          * anonymous bind on an authenticated SMB inherits the user/domain
3588          * from the enclosing SMB creds
3589          */
3590
3591         TALLOC_FREE(auth->user_name);
3592         TALLOC_FREE(auth->domain);
3593
3594         auth->user_name = talloc_strdup(auth, cli->user_name);
3595         auth->domain = talloc_strdup(auth, cli->domain);
3596         auth->user_session_key = data_blob_talloc(auth,
3597                 cli->user_session_key.data,
3598                 cli->user_session_key.length);
3599
3600         if ((auth->user_name == NULL) || (auth->domain == NULL)) {
3601                 TALLOC_FREE(result);
3602                 return NT_STATUS_NO_MEMORY;
3603         }
3604
3605         status = rpc_pipe_bind(result, auth);
3606         if (!NT_STATUS_IS_OK(status)) {
3607                 int lvl = 0;
3608                 if (ndr_syntax_id_equal(interface,
3609                                         &ndr_table_dssetup.syntax_id)) {
3610                         /* non AD domains just don't have this pipe, avoid
3611                          * level 0 statement in that case - gd */
3612                         lvl = 3;
3613                 }
3614                 DEBUG(lvl, ("cli_rpc_pipe_open_noauth: rpc_pipe_bind for pipe "
3615                             "%s failed with error %s\n",
3616                             get_pipe_name_from_syntax(talloc_tos(), interface),
3617                             nt_errstr(status) ));
3618                 TALLOC_FREE(result);
3619                 return status;
3620         }
3621
3622         DEBUG(10,("cli_rpc_pipe_open_noauth: opened pipe %s to machine "
3623                   "%s and bound anonymously.\n",
3624                   get_pipe_name_from_syntax(talloc_tos(), interface),
3625                   cli->desthost));
3626
3627         *presult = result;
3628         return NT_STATUS_OK;
3629 }
3630
3631 /****************************************************************************
3632  ****************************************************************************/
3633
3634 NTSTATUS cli_rpc_pipe_open_noauth(struct cli_state *cli,
3635                                   const struct ndr_syntax_id *interface,
3636                                   struct rpc_pipe_client **presult)
3637 {
3638         return cli_rpc_pipe_open_noauth_transport(cli, NCACN_NP,
3639                                                   interface, presult);
3640 }
3641
3642 /****************************************************************************
3643  Open a named pipe to an SMB server and bind using NTLMSSP or SPNEGO NTLMSSP
3644  ****************************************************************************/
3645
3646 static NTSTATUS cli_rpc_pipe_open_ntlmssp_internal(struct cli_state *cli,
3647                                                    const struct ndr_syntax_id *interface,
3648                                                    enum dcerpc_transport_t transport,
3649                                                    enum pipe_auth_type auth_type,
3650                                                    enum dcerpc_AuthLevel auth_level,
3651                                                    const char *domain,
3652                                                    const char *username,
3653                                                    const char *password,
3654                                                    struct rpc_pipe_client **presult)
3655 {
3656         struct rpc_pipe_client *result;
3657         struct cli_pipe_auth_data *auth;
3658         NTSTATUS status;
3659
3660         status = cli_rpc_pipe_open(cli, transport, interface, &result);
3661         if (!NT_STATUS_IS_OK(status)) {
3662                 return status;
3663         }
3664
3665         status = rpccli_ntlmssp_bind_data(
3666                 result, auth_type, auth_level, domain, username,
3667                 password, &auth);
3668         if (!NT_STATUS_IS_OK(status)) {
3669                 DEBUG(0, ("rpccli_ntlmssp_bind_data returned %s\n",
3670                           nt_errstr(status)));
3671                 goto err;
3672         }
3673
3674         status = rpc_pipe_bind(result, auth);
3675         if (!NT_STATUS_IS_OK(status)) {
3676                 DEBUG(0, ("cli_rpc_pipe_open_ntlmssp_internal: cli_rpc_pipe_bind failed with error %s\n",
3677                         nt_errstr(status) ));
3678                 goto err;
3679         }
3680
3681         DEBUG(10,("cli_rpc_pipe_open_ntlmssp_internal: opened pipe %s to "
3682                 "machine %s and bound NTLMSSP as user %s\\%s.\n",
3683                   get_pipe_name_from_syntax(talloc_tos(), interface),
3684                   cli->desthost, domain, username ));
3685
3686         *presult = result;
3687         return NT_STATUS_OK;
3688
3689   err:
3690
3691         TALLOC_FREE(result);
3692         return status;
3693 }
3694
3695 /****************************************************************************
3696  External interface.
3697  Open a named pipe to an SMB server and bind using NTLMSSP (bind type 10)
3698  ****************************************************************************/
3699
3700 NTSTATUS cli_rpc_pipe_open_ntlmssp(struct cli_state *cli,
3701                                    const struct ndr_syntax_id *interface,
3702                                    enum dcerpc_transport_t transport,
3703                                    enum dcerpc_AuthLevel auth_level,
3704                                    const char *domain,
3705                                    const char *username,
3706                                    const char *password,
3707                                    struct rpc_pipe_client **presult)
3708 {
3709         return cli_rpc_pipe_open_ntlmssp_internal(cli,
3710                                                 interface,
3711                                                 transport,
3712                                                 PIPE_AUTH_TYPE_NTLMSSP,
3713                                                 auth_level,
3714                                                 domain,
3715                                                 username,
3716                                                 password,
3717                                                 presult);
3718 }
3719
3720 /****************************************************************************
3721  External interface.
3722  Open a named pipe to an SMB server and bind using spnego NTLMSSP (bind type 9)
3723  ****************************************************************************/
3724
3725 NTSTATUS cli_rpc_pipe_open_spnego_ntlmssp(struct cli_state *cli,
3726                                           const struct ndr_syntax_id *interface,
3727                                           enum dcerpc_transport_t transport,
3728                                           enum dcerpc_AuthLevel auth_level,
3729                                           const char *domain,
3730                                           const char *username,
3731                                           const char *password,
3732                                           struct rpc_pipe_client **presult)
3733 {
3734         return cli_rpc_pipe_open_ntlmssp_internal(cli,
3735                                                 interface,
3736                                                 transport,
3737                                                 PIPE_AUTH_TYPE_SPNEGO_NTLMSSP,
3738                                                 auth_level,
3739                                                 domain,
3740                                                 username,
3741                                                 password,
3742                                                 presult);
3743 }
3744
3745 /****************************************************************************
3746   Get a the schannel session key out of an already opened netlogon pipe.
3747  ****************************************************************************/
3748 static NTSTATUS get_schannel_session_key_common(struct rpc_pipe_client *netlogon_pipe,
3749                                                 struct cli_state *cli,
3750                                                 const char *domain,
3751                                                 uint32 *pneg_flags)
3752 {
3753         enum netr_SchannelType sec_chan_type = 0;
3754         unsigned char machine_pwd[16];
3755         const char *machine_account;
3756         NTSTATUS status;
3757
3758         /* Get the machine account credentials from secrets.tdb. */
3759         if (!get_trust_pw_hash(domain, machine_pwd, &machine_account,
3760                                &sec_chan_type))
3761         {
3762                 DEBUG(0, ("get_schannel_session_key: could not fetch "
3763                         "trust account password for domain '%s'\n",
3764                         domain));
3765                 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
3766         }
3767
3768         status = rpccli_netlogon_setup_creds(netlogon_pipe,
3769                                         cli->desthost, /* server name */
3770                                         domain,        /* domain */
3771                                         global_myname(), /* client name */
3772                                         machine_account, /* machine account name */
3773                                         machine_pwd,
3774                                         sec_chan_type,
3775                                         pneg_flags);
3776
3777         if (!NT_STATUS_IS_OK(status)) {
3778                 DEBUG(3, ("get_schannel_session_key_common: "
3779                           "rpccli_netlogon_setup_creds failed with result %s "
3780                           "to server %s, domain %s, machine account %s.\n",
3781                           nt_errstr(status), cli->desthost, domain,
3782                           machine_account ));
3783                 return status;
3784         }
3785
3786         if (((*pneg_flags) & NETLOGON_NEG_SCHANNEL) == 0) {
3787                 DEBUG(3, ("get_schannel_session_key: Server %s did not offer schannel\n",
3788                         cli->desthost));
3789                 return NT_STATUS_INVALID_NETWORK_RESPONSE;
3790         }
3791
3792         return NT_STATUS_OK;;
3793 }
3794
3795 /****************************************************************************
3796  Open a netlogon pipe and get the schannel session key.
3797  Now exposed to external callers.
3798  ****************************************************************************/
3799
3800
3801 NTSTATUS get_schannel_session_key(struct cli_state *cli,
3802                                   const char *domain,
3803                                   uint32 *pneg_flags,
3804                                   struct rpc_pipe_client **presult)
3805 {
3806         struct rpc_pipe_client *netlogon_pipe = NULL;
3807         NTSTATUS status;
3808
3809         status = cli_rpc_pipe_open_noauth(cli, &ndr_table_netlogon.syntax_id,
3810                                           &netlogon_pipe);
3811         if (!NT_STATUS_IS_OK(status)) {
3812                 return status;
3813         }
3814
3815         status = get_schannel_session_key_common(netlogon_pipe, cli, domain,
3816                                                  pneg_flags);
3817         if (!NT_STATUS_IS_OK(status)) {
3818                 TALLOC_FREE(netlogon_pipe);
3819                 return status;
3820         }
3821
3822         *presult = netlogon_pipe;
3823         return NT_STATUS_OK;
3824 }
3825
3826 /****************************************************************************
3827  External interface.
3828  Open a named pipe to an SMB server and bind using schannel (bind type 68)
3829  using session_key. sign and seal.
3830
3831  The *pdc will be stolen onto this new pipe
3832  ****************************************************************************/
3833
3834 NTSTATUS cli_rpc_pipe_open_schannel_with_key(struct cli_state *cli,
3835                                              const struct ndr_syntax_id *interface,
3836                                              enum dcerpc_transport_t transport,
3837                                              enum dcerpc_AuthLevel auth_level,
3838                                              const char *domain,
3839                                              struct netlogon_creds_CredentialState **pdc,
3840                                              struct rpc_pipe_client **presult)
3841 {
3842         struct rpc_pipe_client *result;
3843         struct cli_pipe_auth_data *auth;
3844         NTSTATUS status;
3845
3846         status = cli_rpc_pipe_open(cli, transport, interface, &result);
3847         if (!NT_STATUS_IS_OK(status)) {
3848                 return status;
3849         }
3850
3851         status = rpccli_schannel_bind_data(result, domain, auth_level,
3852                                            *pdc, &auth);
3853         if (!NT_STATUS_IS_OK(status)) {
3854                 DEBUG(0, ("rpccli_schannel_bind_data returned %s\n",
3855                           nt_errstr(status)));
3856                 TALLOC_FREE(result);
3857                 return status;
3858         }
3859
3860         status = rpc_pipe_bind(result, auth);
3861         if (!NT_STATUS_IS_OK(status)) {
3862                 DEBUG(0, ("cli_rpc_pipe_open_schannel_with_key: "
3863                           "cli_rpc_pipe_bind failed with error %s\n",
3864                           nt_errstr(status) ));
3865                 TALLOC_FREE(result);
3866                 return status;
3867         }
3868
3869         /*
3870          * The credentials on a new netlogon pipe are the ones we are passed
3871          * in - reference them in
3872          */
3873         result->dc = talloc_move(result, pdc);
3874
3875         DEBUG(10,("cli_rpc_pipe_open_schannel_with_key: opened pipe %s to machine %s "
3876                   "for domain %s and bound using schannel.\n",
3877                   get_pipe_name_from_syntax(talloc_tos(), interface),
3878                   cli->desthost, domain ));
3879
3880         *presult = result;
3881         return NT_STATUS_OK;
3882 }
3883
3884 /****************************************************************************
3885  Open a named pipe to an SMB server and bind using schannel (bind type 68).
3886  Fetch the session key ourselves using a temporary netlogon pipe. This
3887  version uses an ntlmssp auth bound netlogon pipe to get the key.
3888  ****************************************************************************/
3889
3890 static NTSTATUS get_schannel_session_key_auth_ntlmssp(struct cli_state *cli,
3891                                                       const char *domain,
3892                                                       const char *username,
3893                                                       const char *password,
3894                                                       uint32 *pneg_flags,
3895                                                       struct rpc_pipe_client **presult)
3896 {
3897         struct rpc_pipe_client *netlogon_pipe = NULL;
3898         NTSTATUS status;
3899
3900         status = cli_rpc_pipe_open_spnego_ntlmssp(
3901                 cli, &ndr_table_netlogon.syntax_id, NCACN_NP,
3902                 DCERPC_AUTH_LEVEL_PRIVACY,
3903                 domain, username, password, &netlogon_pipe);
3904         if (!NT_STATUS_IS_OK(status)) {
3905                 return status;
3906         }
3907
3908         status = get_schannel_session_key_common(netlogon_pipe, cli, domain,
3909                                                  pneg_flags);
3910         if (!NT_STATUS_IS_OK(status)) {
3911                 TALLOC_FREE(netlogon_pipe);
3912                 return status;
3913         }
3914
3915         *presult = netlogon_pipe;
3916         return NT_STATUS_OK;
3917 }
3918
3919 /****************************************************************************
3920  Open a named pipe to an SMB server and bind using schannel (bind type 68).
3921  Fetch the session key ourselves using a temporary netlogon pipe. This version
3922  uses an ntlmssp bind to get the session key.
3923  ****************************************************************************/
3924
3925 NTSTATUS cli_rpc_pipe_open_ntlmssp_auth_schannel(struct cli_state *cli,
3926                                                  const struct ndr_syntax_id *interface,
3927                                                  enum dcerpc_transport_t transport,
3928                                                  enum dcerpc_AuthLevel auth_level,
3929                                                  const char *domain,
3930                                                  const char *username,
3931                                                  const char *password,
3932                                                  struct rpc_pipe_client **presult)
3933 {
3934         uint32_t neg_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS;
3935         struct rpc_pipe_client *netlogon_pipe = NULL;
3936         struct rpc_pipe_client *result = NULL;
3937         NTSTATUS status;
3938
3939         status = get_schannel_session_key_auth_ntlmssp(
3940                 cli, domain, username, password, &neg_flags, &netlogon_pipe);
3941         if (!NT_STATUS_IS_OK(status)) {
3942                 DEBUG(0,("cli_rpc_pipe_open_ntlmssp_auth_schannel: failed to get schannel session "
3943                         "key from server %s for domain %s.\n",
3944                         cli->desthost, domain ));
3945                 return status;
3946         }
3947
3948         status = cli_rpc_pipe_open_schannel_with_key(
3949                 cli, interface, transport, auth_level, domain, &netlogon_pipe->dc,
3950                 &result);
3951
3952         /* Now we've bound using the session key we can close the netlog pipe. */
3953         TALLOC_FREE(netlogon_pipe);
3954
3955         if (NT_STATUS_IS_OK(status)) {
3956                 *presult = result;
3957         }
3958         return status;
3959 }
3960
3961 /****************************************************************************
3962  Open a named pipe to an SMB server and bind using schannel (bind type 68).
3963  Fetch the session key ourselves using a temporary netlogon pipe.
3964  ****************************************************************************/
3965
3966 NTSTATUS cli_rpc_pipe_open_schannel(struct cli_state *cli,
3967                                     const struct ndr_syntax_id *interface,
3968                                     enum dcerpc_transport_t transport,
3969                                     enum dcerpc_AuthLevel auth_level,
3970                                     const char *domain,
3971                                     struct rpc_pipe_client **presult)
3972 {
3973         uint32_t neg_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS;
3974         struct rpc_pipe_client *netlogon_pipe = NULL;
3975         struct rpc_pipe_client *result = NULL;
3976         NTSTATUS status;
3977
3978         status = get_schannel_session_key(cli, domain, &neg_flags,
3979                                           &netlogon_pipe);
3980         if (!NT_STATUS_IS_OK(status)) {
3981                 DEBUG(0,("cli_rpc_pipe_open_schannel: failed to get schannel session "
3982                         "key from server %s for domain %s.\n",
3983                         cli->desthost, domain ));
3984                 return status;
3985         }
3986
3987         status = cli_rpc_pipe_open_schannel_with_key(
3988                 cli, interface, transport, auth_level, domain, &netlogon_pipe->dc,
3989                 &result);
3990
3991         /* Now we've bound using the session key we can close the netlog pipe. */
3992         TALLOC_FREE(netlogon_pipe);
3993
3994         if (NT_STATUS_IS_OK(status)) {
3995                 *presult = result;
3996         }
3997
3998         return status;
3999 }
4000
4001 /****************************************************************************
4002  Open a named pipe to an SMB server and bind using krb5 (bind type 16).
4003  The idea is this can be called with service_princ, username and password all
4004  NULL so long as the caller has a TGT.
4005  ****************************************************************************/
4006
4007 NTSTATUS cli_rpc_pipe_open_krb5(struct cli_state *cli,
4008                                 const struct ndr_syntax_id *interface,
4009                                 enum dcerpc_AuthLevel auth_level,
4010                                 const char *service_princ,
4011                                 const char *username,
4012                                 const char *password,
4013                                 struct rpc_pipe_client **presult)
4014 {
4015 #ifdef HAVE_KRB5
4016         struct rpc_pipe_client *result;
4017         struct cli_pipe_auth_data *auth;
4018         NTSTATUS status;
4019
4020         status = cli_rpc_pipe_open(cli, NCACN_NP, interface, &result);
4021         if (!NT_STATUS_IS_OK(status)) {
4022                 return status;
4023         }
4024
4025         status = rpccli_kerberos_bind_data(result, auth_level, service_princ,
4026                                            username, password, &auth);
4027         if (!NT_STATUS_IS_OK(status)) {
4028                 DEBUG(0, ("rpccli_kerberos_bind_data returned %s\n",
4029                           nt_errstr(status)));
4030                 TALLOC_FREE(result);
4031                 return status;
4032         }
4033
4034         status = rpc_pipe_bind(result, auth);
4035         if (!NT_STATUS_IS_OK(status)) {
4036                 DEBUG(0, ("cli_rpc_pipe_open_krb5: cli_rpc_pipe_bind failed "
4037                           "with error %s\n", nt_errstr(status)));
4038                 TALLOC_FREE(result);
4039                 return status;
4040         }
4041
4042         *presult = result;
4043         return NT_STATUS_OK;
4044 #else
4045         DEBUG(0,("cli_rpc_pipe_open_krb5: kerberos not found at compile time.\n"));
4046         return NT_STATUS_NOT_IMPLEMENTED;
4047 #endif
4048 }
4049
4050 NTSTATUS cli_get_session_key(TALLOC_CTX *mem_ctx,
4051                              struct rpc_pipe_client *cli,
4052                              DATA_BLOB *session_key)
4053 {
4054         if (!session_key || !cli) {
4055                 return NT_STATUS_INVALID_PARAMETER;
4056         }
4057
4058         if (!cli->auth) {
4059                 return NT_STATUS_INVALID_PARAMETER;
4060         }
4061
4062         switch (cli->auth->auth_type) {
4063                 case PIPE_AUTH_TYPE_SCHANNEL:
4064                         *session_key = data_blob_talloc(mem_ctx,
4065                                 cli->auth->a_u.schannel_auth->creds->session_key, 16);
4066                         break;
4067                 case PIPE_AUTH_TYPE_NTLMSSP:
4068                 case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP:
4069                         *session_key = data_blob_talloc(mem_ctx,
4070                                 cli->auth->a_u.ntlmssp_state->session_key.data,
4071                                 cli->auth->a_u.ntlmssp_state->session_key.length);
4072                         break;
4073                 case PIPE_AUTH_TYPE_KRB5:
4074                 case PIPE_AUTH_TYPE_SPNEGO_KRB5:
4075                         *session_key = data_blob_talloc(mem_ctx,
4076                                 cli->auth->a_u.kerberos_auth->session_key.data,
4077                                 cli->auth->a_u.kerberos_auth->session_key.length);
4078                         break;
4079                 case PIPE_AUTH_TYPE_NONE:
4080                         *session_key = data_blob_talloc(mem_ctx,
4081                                 cli->auth->user_session_key.data,
4082                                 cli->auth->user_session_key.length);
4083                         break;
4084                 default:
4085                         return NT_STATUS_NO_USER_SESSION_KEY;
4086         }
4087
4088         return NT_STATUS_OK;
4089 }