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