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