s3-dcerpc: Remove unused functions
[amitay/samba.git] / source3 / rpc_client / cli_pipe.c
1 /* 
2  *  Unix SMB/CIFS implementation.
3  *  RPC Pipe client / server routines
4  *  Largely rewritten by Jeremy Allison             2005.
5  *  
6  *  This program is free software; you can redistribute it and/or modify
7  *  it under the terms of the GNU General Public License as published by
8  *  the Free Software Foundation; either version 3 of the License, or
9  *  (at your option) any later version.
10  *  
11  *  This program is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *  GNU General Public License for more details.
15  *  
16  *  You should have received a copy of the GNU General Public License
17  *  along with this program; if not, see <http://www.gnu.org/licenses/>.
18  */
19
20 #include "includes.h"
21 #include "librpc/gen_ndr/cli_epmapper.h"
22 #include "../librpc/gen_ndr/ndr_schannel.h"
23 #include "../librpc/gen_ndr/ndr_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_info)
955 {
956         DATA_BLOB in_token = data_blob_null;
957         DATA_BLOB auth_token = data_blob_null;
958         NTSTATUS status;
959
960         /* Negotiate the initial auth token */
961         status = spnego_get_client_auth_token(mem_ctx,
962                                               auth->a_u.spnego_state,
963                                               &in_token, &auth_token);
964         if (!NT_STATUS_IS_OK(status)) {
965                 return status;
966         }
967
968         status = dcerpc_push_dcerpc_auth(mem_ctx,
969                                          auth->auth_type,
970                                          auth->auth_level,
971                                          0, /* auth_pad_length */
972                                          1, /* auth_context_id */
973                                          &auth_token,
974                                          auth_info);
975         if (!NT_STATUS_IS_OK(status)) {
976                 data_blob_free(&auth_token);
977                 return status;
978         }
979
980         DEBUG(5, ("Created GSS Authentication Token:\n"));
981         dump_data(5, auth_token.data, auth_token.length);
982
983         data_blob_free(&auth_token);
984         return NT_STATUS_OK;
985 }
986
987 /*******************************************************************
988  Creates krb5 auth bind.
989  ********************************************************************/
990
991 static NTSTATUS create_gssapi_auth_bind_req(TALLOC_CTX *mem_ctx,
992                                             struct pipe_auth_data *auth,
993                                             DATA_BLOB *auth_info)
994 {
995         DATA_BLOB in_token = data_blob_null;
996         DATA_BLOB auth_token = data_blob_null;
997         NTSTATUS status;
998
999         /* Negotiate the initial auth token */
1000         status = gse_get_client_auth_token(mem_ctx,
1001                                            auth->a_u.gssapi_state,
1002                                            &in_token,
1003                                            &auth_token);
1004         if (!NT_STATUS_IS_OK(status)) {
1005                 return status;
1006         }
1007
1008         status = dcerpc_push_dcerpc_auth(mem_ctx,
1009                                          auth->auth_type,
1010                                          auth->auth_level,
1011                                          0, /* auth_pad_length */
1012                                          1, /* auth_context_id */
1013                                          &auth_token,
1014                                          auth_info);
1015         if (!NT_STATUS_IS_OK(status)) {
1016                 data_blob_free(&auth_token);
1017                 return status;
1018         }
1019
1020         DEBUG(5, ("Created GSS Authentication Token:\n"));
1021         dump_data(5, auth_token.data, auth_token.length);
1022
1023         data_blob_free(&auth_token);
1024         return NT_STATUS_OK;
1025 }
1026
1027 /*******************************************************************
1028  Creates NTLMSSP auth bind.
1029  ********************************************************************/
1030
1031 static NTSTATUS create_ntlmssp_auth_rpc_bind_req(struct rpc_pipe_client *cli,
1032                                                  enum dcerpc_AuthLevel auth_level,
1033                                                  DATA_BLOB *auth_info)
1034 {
1035         NTSTATUS status;
1036         DATA_BLOB null_blob = data_blob_null;
1037         DATA_BLOB request = data_blob_null;
1038
1039         DEBUG(5, ("create_ntlmssp_auth_rpc_bind_req: Processing NTLMSSP Negotiate\n"));
1040         status = auth_ntlmssp_update(cli->auth->a_u.auth_ntlmssp_state,
1041                                         null_blob,
1042                                         &request);
1043
1044         if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1045                 data_blob_free(&request);
1046                 return status;
1047         }
1048
1049         status = dcerpc_push_dcerpc_auth(cli,
1050                                          DCERPC_AUTH_TYPE_NTLMSSP,
1051                                          auth_level,
1052                                          0, /* auth_pad_length */
1053                                          1, /* auth_context_id */
1054                                          &request,
1055                                          auth_info);
1056         if (!NT_STATUS_IS_OK(status)) {
1057                 data_blob_free(&request);
1058                 return status;
1059         }
1060
1061         DEBUG(5, ("create_ntlmssp_auth_rpc_bind_req: NTLMSSP Negotiate:\n"));
1062         dump_data(5, request.data, request.length);
1063
1064         return NT_STATUS_OK;
1065 }
1066
1067 /*******************************************************************
1068  Creates schannel auth bind.
1069  ********************************************************************/
1070
1071 static NTSTATUS create_schannel_auth_rpc_bind_req(struct rpc_pipe_client *cli,
1072                                                   enum dcerpc_AuthLevel auth_level,
1073                                                   DATA_BLOB *auth_info)
1074 {
1075         NTSTATUS status;
1076         struct NL_AUTH_MESSAGE r;
1077         DATA_BLOB schannel_blob;
1078
1079         /* Use lp_workgroup() if domain not specified */
1080
1081         if (!cli->auth->domain || !cli->auth->domain[0]) {
1082                 cli->auth->domain = talloc_strdup(cli, lp_workgroup());
1083                 if (cli->auth->domain == NULL) {
1084                         return NT_STATUS_NO_MEMORY;
1085                 }
1086         }
1087
1088         /*
1089          * Now marshall the data into the auth parse_struct.
1090          */
1091
1092         r.MessageType                   = NL_NEGOTIATE_REQUEST;
1093         r.Flags                         = NL_FLAG_OEM_NETBIOS_DOMAIN_NAME |
1094                                           NL_FLAG_OEM_NETBIOS_COMPUTER_NAME;
1095         r.oem_netbios_domain.a          = cli->auth->domain;
1096         r.oem_netbios_computer.a        = global_myname();
1097
1098         status = dcerpc_push_schannel_bind(cli, &r, &schannel_blob);
1099         if (!NT_STATUS_IS_OK(status)) {
1100                 return status;
1101         }
1102
1103         status = dcerpc_push_dcerpc_auth(cli,
1104                                          DCERPC_AUTH_TYPE_SCHANNEL,
1105                                          auth_level,
1106                                          0, /* auth_pad_length */
1107                                          1, /* auth_context_id */
1108                                          &schannel_blob,
1109                                          auth_info);
1110         if (!NT_STATUS_IS_OK(status)) {
1111                 return status;
1112         }
1113
1114         return NT_STATUS_OK;
1115 }
1116
1117 /*******************************************************************
1118  Creates the internals of a DCE/RPC bind request or alter context PDU.
1119  ********************************************************************/
1120
1121 static NTSTATUS create_bind_or_alt_ctx_internal(TALLOC_CTX *mem_ctx,
1122                                                 enum dcerpc_pkt_type ptype,
1123                                                 uint32 rpc_call_id,
1124                                                 const struct ndr_syntax_id *abstract,
1125                                                 const struct ndr_syntax_id *transfer,
1126                                                 const DATA_BLOB *auth_info,
1127                                                 DATA_BLOB *blob)
1128 {
1129         uint16 auth_len = auth_info->length;
1130         NTSTATUS status;
1131         union dcerpc_payload u;
1132         struct dcerpc_ctx_list ctx_list;
1133
1134         if (auth_len) {
1135                 auth_len -= DCERPC_AUTH_TRAILER_LENGTH;
1136         }
1137
1138         ctx_list.context_id = 0;
1139         ctx_list.num_transfer_syntaxes = 1;
1140         ctx_list.abstract_syntax = *abstract;
1141         ctx_list.transfer_syntaxes = (struct ndr_syntax_id *)discard_const(transfer);
1142
1143         u.bind.max_xmit_frag    = RPC_MAX_PDU_FRAG_LEN;
1144         u.bind.max_recv_frag    = RPC_MAX_PDU_FRAG_LEN;
1145         u.bind.assoc_group_id   = 0x0;
1146         u.bind.num_contexts     = 1;
1147         u.bind.ctx_list         = &ctx_list;
1148         u.bind.auth_info        = *auth_info;
1149
1150         status = dcerpc_push_ncacn_packet(mem_ctx,
1151                                           ptype,
1152                                           DCERPC_PFC_FLAG_FIRST |
1153                                           DCERPC_PFC_FLAG_LAST,
1154                                           auth_len,
1155                                           rpc_call_id,
1156                                           &u,
1157                                           blob);
1158         if (!NT_STATUS_IS_OK(status)) {
1159                 DEBUG(0, ("Failed to marshall bind/alter ncacn_packet.\n"));
1160                 return status;
1161         }
1162
1163         return NT_STATUS_OK;
1164 }
1165
1166 /*******************************************************************
1167  Creates a DCE/RPC bind request.
1168  ********************************************************************/
1169
1170 static NTSTATUS create_rpc_bind_req(TALLOC_CTX *mem_ctx,
1171                                     struct rpc_pipe_client *cli,
1172                                     struct pipe_auth_data *auth,
1173                                     uint32 rpc_call_id,
1174                                     const struct ndr_syntax_id *abstract,
1175                                     const struct ndr_syntax_id *transfer,
1176                                     DATA_BLOB *rpc_out)
1177 {
1178         DATA_BLOB auth_info = data_blob_null;
1179         NTSTATUS ret = NT_STATUS_OK;
1180
1181         switch (auth->auth_type) {
1182         case DCERPC_AUTH_TYPE_SCHANNEL:
1183                 ret = create_schannel_auth_rpc_bind_req(cli,
1184                                                         auth->auth_level,
1185                                                         &auth_info);
1186                 if (!NT_STATUS_IS_OK(ret)) {
1187                         return ret;
1188                 }
1189                 break;
1190
1191         case DCERPC_AUTH_TYPE_NTLMSSP:
1192                 ret = create_ntlmssp_auth_rpc_bind_req(cli,
1193                                                         auth->auth_level,
1194                                                         &auth_info);
1195                 if (!NT_STATUS_IS_OK(ret)) {
1196                         return ret;
1197                 }
1198                 break;
1199
1200         case DCERPC_AUTH_TYPE_SPNEGO:
1201                 ret = create_spnego_auth_bind_req(cli, auth, &auth_info);
1202                 if (!NT_STATUS_IS_OK(ret)) {
1203                         return ret;
1204                 }
1205                 break;
1206
1207         case DCERPC_AUTH_TYPE_KRB5:
1208                 ret = create_gssapi_auth_bind_req(mem_ctx, auth, &auth_info);
1209                 if (!NT_STATUS_IS_OK(ret)) {
1210                         return ret;
1211                 }
1212                 break;
1213
1214         case DCERPC_AUTH_TYPE_NONE:
1215                 break;
1216
1217         default:
1218                 /* "Can't" happen. */
1219                 return NT_STATUS_INVALID_INFO_CLASS;
1220         }
1221
1222         ret = create_bind_or_alt_ctx_internal(mem_ctx,
1223                                               DCERPC_PKT_BIND,
1224                                               rpc_call_id,
1225                                               abstract,
1226                                               transfer,
1227                                               &auth_info,
1228                                               rpc_out);
1229         return ret;
1230 }
1231
1232 /*******************************************************************
1233  Calculate how much data we're going to send in this packet, also
1234  work out any sign/seal padding length.
1235  ********************************************************************/
1236
1237 static NTSTATUS calculate_data_len_tosend(struct rpc_pipe_client *cli,
1238                                           uint32_t data_left,
1239                                           uint32_t *data_to_send,
1240                                           uint16_t *p_frag_len,
1241                                           uint16_t *p_auth_len,
1242                                           uint32_t *p_ss_padding)
1243 {
1244         uint32_t data_space, data_len;
1245         size_t max_len;
1246         struct gse_context *gse_ctx;
1247         enum dcerpc_AuthType auth_type;
1248         void *auth_ctx;
1249         NTSTATUS status;
1250
1251         switch (cli->auth->auth_level) {
1252         case DCERPC_AUTH_LEVEL_NONE:
1253         case DCERPC_AUTH_LEVEL_CONNECT:
1254         case DCERPC_AUTH_LEVEL_PACKET:
1255                 data_space = cli->max_xmit_frag - DCERPC_REQUEST_LENGTH;
1256                 data_len = MIN(data_space, data_left);
1257                 *p_ss_padding = 0;
1258                 *p_auth_len = 0;
1259                 *p_frag_len = DCERPC_REQUEST_LENGTH + data_len;
1260                 *data_to_send = data_len;
1261                 return NT_STATUS_OK;
1262
1263         case DCERPC_AUTH_LEVEL_INTEGRITY:
1264         case DCERPC_AUTH_LEVEL_PRIVACY:
1265                 max_len = cli->max_xmit_frag
1266                                 - DCERPC_REQUEST_LENGTH
1267                                 - DCERPC_AUTH_TRAILER_LENGTH;
1268
1269                 /* Treat the same for all authenticated rpc requests. */
1270                 switch(cli->auth->auth_type) {
1271                 case DCERPC_AUTH_TYPE_SPNEGO:
1272                         status = spnego_get_negotiated_mech(
1273                                         cli->auth->a_u.spnego_state,
1274                                         &auth_type, &auth_ctx);
1275                         if (!NT_STATUS_IS_OK(status)) {
1276                                 return status;
1277                         }
1278                         switch (auth_type) {
1279                         case DCERPC_AUTH_TYPE_NTLMSSP:
1280                                 *p_auth_len = NTLMSSP_SIG_SIZE;
1281                                 break;
1282                         case DCERPC_AUTH_TYPE_KRB5:
1283                                 gse_ctx = talloc_get_type(auth_ctx,
1284                                                           struct gse_context);
1285                                 if (!gse_ctx) {
1286                                         return NT_STATUS_INVALID_PARAMETER;
1287                                 }
1288                                 *p_auth_len = gse_get_signature_length(gse_ctx,
1289                                                 (cli->auth->auth_level ==
1290                                                   DCERPC_AUTH_LEVEL_PRIVACY),
1291                                                 max_len);
1292                                 break;
1293                         default:
1294                                 return NT_STATUS_INVALID_PARAMETER;
1295                         }
1296                         break;
1297                 case DCERPC_AUTH_TYPE_NTLMSSP:
1298                         *p_auth_len = NTLMSSP_SIG_SIZE;
1299                         break;
1300                 case DCERPC_AUTH_TYPE_SCHANNEL:
1301                         *p_auth_len = NL_AUTH_SIGNATURE_SIZE;
1302                         break;
1303                 case DCERPC_AUTH_TYPE_KRB5:
1304                         *p_auth_len = gse_get_signature_length(
1305                                         cli->auth->a_u.gssapi_state,
1306                                         (cli->auth->auth_level ==
1307                                                 DCERPC_AUTH_LEVEL_PRIVACY),
1308                                         max_len);
1309                         break;
1310                 default:
1311                         return NT_STATUS_INVALID_PARAMETER;
1312                 }
1313
1314                 data_space = max_len - *p_auth_len;
1315
1316                 data_len = MIN(data_space, data_left);
1317                 *p_ss_padding = 0;
1318                 if (data_len % CLIENT_NDR_PADDING_SIZE) {
1319                         *p_ss_padding = CLIENT_NDR_PADDING_SIZE - (data_len % CLIENT_NDR_PADDING_SIZE);
1320                 }
1321                 *p_frag_len = DCERPC_REQUEST_LENGTH
1322                                 + data_len + *p_ss_padding
1323                                 + DCERPC_AUTH_TRAILER_LENGTH
1324                                 + *p_auth_len;
1325                 *data_to_send = data_len;
1326                 return NT_STATUS_OK;
1327
1328         default:
1329                 break;
1330         }
1331
1332         return NT_STATUS_INVALID_PARAMETER;
1333 }
1334
1335 /*******************************************************************
1336  External interface.
1337  Does an rpc request on a pipe. Incoming data is NDR encoded in in_data.
1338  Reply is NDR encoded in out_data. Splits the data stream into RPC PDU's
1339  and deals with signing/sealing details.
1340  ********************************************************************/
1341
1342 struct rpc_api_pipe_req_state {
1343         struct event_context *ev;
1344         struct rpc_pipe_client *cli;
1345         uint8_t op_num;
1346         uint32_t call_id;
1347         DATA_BLOB *req_data;
1348         uint32_t req_data_sent;
1349         DATA_BLOB rpc_out;
1350         DATA_BLOB reply_pdu;
1351 };
1352
1353 static void rpc_api_pipe_req_write_done(struct tevent_req *subreq);
1354 static void rpc_api_pipe_req_done(struct tevent_req *subreq);
1355 static NTSTATUS prepare_next_frag(struct rpc_api_pipe_req_state *state,
1356                                   bool *is_last_frag);
1357
1358 struct tevent_req *rpc_api_pipe_req_send(TALLOC_CTX *mem_ctx,
1359                                          struct event_context *ev,
1360                                          struct rpc_pipe_client *cli,
1361                                          uint8_t op_num,
1362                                          DATA_BLOB *req_data)
1363 {
1364         struct tevent_req *req, *subreq;
1365         struct rpc_api_pipe_req_state *state;
1366         NTSTATUS status;
1367         bool is_last_frag;
1368
1369         req = tevent_req_create(mem_ctx, &state,
1370                                 struct rpc_api_pipe_req_state);
1371         if (req == NULL) {
1372                 return NULL;
1373         }
1374         state->ev = ev;
1375         state->cli = cli;
1376         state->op_num = op_num;
1377         state->req_data = req_data;
1378         state->req_data_sent = 0;
1379         state->call_id = get_rpc_call_id();
1380         state->reply_pdu = data_blob_null;
1381         state->rpc_out = data_blob_null;
1382
1383         if (cli->max_xmit_frag < DCERPC_REQUEST_LENGTH
1384                                         + RPC_MAX_SIGN_SIZE) {
1385                 /* Server is screwed up ! */
1386                 status = NT_STATUS_INVALID_PARAMETER;
1387                 goto post_status;
1388         }
1389
1390         status = prepare_next_frag(state, &is_last_frag);
1391         if (!NT_STATUS_IS_OK(status)) {
1392                 goto post_status;
1393         }
1394
1395         if (is_last_frag) {
1396                 subreq = rpc_api_pipe_send(state, ev, state->cli,
1397                                            &state->rpc_out,
1398                                            DCERPC_PKT_RESPONSE);
1399                 if (subreq == NULL) {
1400                         goto fail;
1401                 }
1402                 tevent_req_set_callback(subreq, rpc_api_pipe_req_done, req);
1403         } else {
1404                 subreq = rpc_write_send(state, ev, cli->transport,
1405                                         state->rpc_out.data,
1406                                         state->rpc_out.length);
1407                 if (subreq == NULL) {
1408                         goto fail;
1409                 }
1410                 tevent_req_set_callback(subreq, rpc_api_pipe_req_write_done,
1411                                         req);
1412         }
1413         return req;
1414
1415  post_status:
1416         tevent_req_nterror(req, status);
1417         return tevent_req_post(req, ev);
1418  fail:
1419         TALLOC_FREE(req);
1420         return NULL;
1421 }
1422
1423 static NTSTATUS prepare_next_frag(struct rpc_api_pipe_req_state *state,
1424                                   bool *is_last_frag)
1425 {
1426         uint32_t data_sent_thistime;
1427         uint16_t auth_len;
1428         uint16_t frag_len;
1429         uint8_t flags = 0;
1430         uint32_t pad_len;
1431         uint32_t data_left;
1432         NTSTATUS status;
1433         union dcerpc_payload u;
1434
1435         data_left = state->req_data->length - state->req_data_sent;
1436
1437         status = calculate_data_len_tosend(state->cli, data_left,
1438                                            &data_sent_thistime,
1439                                            &frag_len, &auth_len,
1440                                            &pad_len);
1441         if (!NT_STATUS_IS_OK(status)) {
1442                 return status;
1443         }
1444
1445         if (state->req_data_sent == 0) {
1446                 flags = DCERPC_PFC_FLAG_FIRST;
1447         }
1448
1449         if (data_sent_thistime == data_left) {
1450                 flags |= DCERPC_PFC_FLAG_LAST;
1451         }
1452
1453         data_blob_free(&state->rpc_out);
1454
1455         ZERO_STRUCT(u.request);
1456
1457         u.request.alloc_hint    = state->req_data->length;
1458         u.request.context_id    = 0;
1459         u.request.opnum         = state->op_num;
1460
1461         status = dcerpc_push_ncacn_packet(state,
1462                                           DCERPC_PKT_REQUEST,
1463                                           flags,
1464                                           auth_len,
1465                                           state->call_id,
1466                                           &u,
1467                                           &state->rpc_out);
1468         if (!NT_STATUS_IS_OK(status)) {
1469                 return status;
1470         }
1471
1472         /* explicitly set frag_len here as dcerpc_push_ncacn_packet() can't
1473          * compute it right for requests because the auth trailer is missing
1474          * at this stage */
1475         dcerpc_set_frag_length(&state->rpc_out, frag_len);
1476
1477         /* Copy in the data. */
1478         if (!data_blob_append(NULL, &state->rpc_out,
1479                                 state->req_data->data + state->req_data_sent,
1480                                 data_sent_thistime)) {
1481                 return NT_STATUS_NO_MEMORY;
1482         }
1483
1484         switch (state->cli->auth->auth_level) {
1485         case DCERPC_AUTH_LEVEL_NONE:
1486         case DCERPC_AUTH_LEVEL_CONNECT:
1487         case DCERPC_AUTH_LEVEL_PACKET:
1488                 break;
1489         case DCERPC_AUTH_LEVEL_INTEGRITY:
1490         case DCERPC_AUTH_LEVEL_PRIVACY:
1491                 status = dcerpc_add_auth_footer(state->cli->auth, pad_len,
1492                                                 &state->rpc_out);
1493                 if (!NT_STATUS_IS_OK(status)) {
1494                         return status;
1495                 }
1496                 break;
1497         default:
1498                 return NT_STATUS_INVALID_PARAMETER;
1499         }
1500
1501         state->req_data_sent += data_sent_thistime;
1502         *is_last_frag = ((flags & DCERPC_PFC_FLAG_LAST) != 0);
1503
1504         return status;
1505 }
1506
1507 static void rpc_api_pipe_req_write_done(struct tevent_req *subreq)
1508 {
1509         struct tevent_req *req = tevent_req_callback_data(
1510                 subreq, struct tevent_req);
1511         struct rpc_api_pipe_req_state *state = tevent_req_data(
1512                 req, struct rpc_api_pipe_req_state);
1513         NTSTATUS status;
1514         bool is_last_frag;
1515
1516         status = rpc_write_recv(subreq);
1517         TALLOC_FREE(subreq);
1518         if (!NT_STATUS_IS_OK(status)) {
1519                 tevent_req_nterror(req, status);
1520                 return;
1521         }
1522
1523         status = prepare_next_frag(state, &is_last_frag);
1524         if (!NT_STATUS_IS_OK(status)) {
1525                 tevent_req_nterror(req, status);
1526                 return;
1527         }
1528
1529         if (is_last_frag) {
1530                 subreq = rpc_api_pipe_send(state, state->ev, state->cli,
1531                                            &state->rpc_out,
1532                                            DCERPC_PKT_RESPONSE);
1533                 if (tevent_req_nomem(subreq, req)) {
1534                         return;
1535                 }
1536                 tevent_req_set_callback(subreq, rpc_api_pipe_req_done, req);
1537         } else {
1538                 subreq = rpc_write_send(state, state->ev,
1539                                         state->cli->transport,
1540                                         state->rpc_out.data,
1541                                         state->rpc_out.length);
1542                 if (tevent_req_nomem(subreq, req)) {
1543                         return;
1544                 }
1545                 tevent_req_set_callback(subreq, rpc_api_pipe_req_write_done,
1546                                         req);
1547         }
1548 }
1549
1550 static void rpc_api_pipe_req_done(struct tevent_req *subreq)
1551 {
1552         struct tevent_req *req = tevent_req_callback_data(
1553                 subreq, struct tevent_req);
1554         struct rpc_api_pipe_req_state *state = tevent_req_data(
1555                 req, struct rpc_api_pipe_req_state);
1556         NTSTATUS status;
1557
1558         status = rpc_api_pipe_recv(subreq, state, NULL, &state->reply_pdu);
1559         TALLOC_FREE(subreq);
1560         if (!NT_STATUS_IS_OK(status)) {
1561                 tevent_req_nterror(req, status);
1562                 return;
1563         }
1564         tevent_req_done(req);
1565 }
1566
1567 NTSTATUS rpc_api_pipe_req_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
1568                                DATA_BLOB *reply_pdu)
1569 {
1570         struct rpc_api_pipe_req_state *state = tevent_req_data(
1571                 req, struct rpc_api_pipe_req_state);
1572         NTSTATUS status;
1573
1574         if (tevent_req_is_nterror(req, &status)) {
1575                 /*
1576                  * We always have to initialize to reply pdu, even if there is
1577                  * none. The rpccli_* caller routines expect this.
1578                  */
1579                 *reply_pdu = data_blob_null;
1580                 return status;
1581         }
1582
1583         /* return data to caller and assign it ownership of memory */
1584         reply_pdu->data = talloc_move(mem_ctx, &state->reply_pdu.data);
1585         reply_pdu->length = state->reply_pdu.length;
1586         state->reply_pdu.length = 0;
1587
1588         return NT_STATUS_OK;
1589 }
1590
1591 #if 0
1592 /****************************************************************************
1593  Set the handle state.
1594 ****************************************************************************/
1595
1596 static bool rpc_pipe_set_hnd_state(struct rpc_pipe_client *cli,
1597                                    const char *pipe_name, uint16 device_state)
1598 {
1599         bool state_set = False;
1600         char param[2];
1601         uint16 setup[2]; /* only need 2 uint16 setup parameters */
1602         char *rparam = NULL;
1603         char *rdata = NULL;
1604         uint32 rparam_len, rdata_len;
1605
1606         if (pipe_name == NULL)
1607                 return False;
1608
1609         DEBUG(5,("Set Handle state Pipe[%x]: %s - device state:%x\n",
1610                  cli->fnum, pipe_name, device_state));
1611
1612         /* create parameters: device state */
1613         SSVAL(param, 0, device_state);
1614
1615         /* create setup parameters. */
1616         setup[0] = 0x0001; 
1617         setup[1] = cli->fnum; /* pipe file handle.  got this from an SMBOpenX. */
1618
1619         /* send the data on \PIPE\ */
1620         if (cli_api_pipe(cli->cli, "\\PIPE\\",
1621                     setup, 2, 0,                /* setup, length, max */
1622                     param, 2, 0,                /* param, length, max */
1623                     NULL, 0, 1024,              /* data, length, max */
1624                     &rparam, &rparam_len,        /* return param, length */
1625                     &rdata, &rdata_len))         /* return data, length */
1626         {
1627                 DEBUG(5, ("Set Handle state: return OK\n"));
1628                 state_set = True;
1629         }
1630
1631         SAFE_FREE(rparam);
1632         SAFE_FREE(rdata);
1633
1634         return state_set;
1635 }
1636 #endif
1637
1638 /****************************************************************************
1639  Check the rpc bind acknowledge response.
1640 ****************************************************************************/
1641
1642 static bool check_bind_response(const struct dcerpc_bind_ack *r,
1643                                 const struct ndr_syntax_id *transfer)
1644 {
1645         struct dcerpc_ack_ctx ctx;
1646
1647         if (r->secondary_address_size == 0) {
1648                 DEBUG(4,("Ignoring length check -- ASU bug (server didn't fill in the pipe name correctly)"));
1649         }
1650
1651         if (r->num_results < 1 || !r->ctx_list) {
1652                 return false;
1653         }
1654
1655         ctx = r->ctx_list[0];
1656
1657         /* check the transfer syntax */
1658         if ((ctx.syntax.if_version != transfer->if_version) ||
1659              (memcmp(&ctx.syntax.uuid, &transfer->uuid, sizeof(transfer->uuid)) !=0)) {
1660                 DEBUG(2,("bind_rpc_pipe: transfer syntax differs\n"));
1661                 return False;
1662         }
1663
1664         if (r->num_results != 0x1 || ctx.result != 0) {
1665                 DEBUG(2,("bind_rpc_pipe: bind denied results: %d reason: %x\n",
1666                           r->num_results, ctx.reason));
1667         }
1668
1669         DEBUG(5,("check_bind_response: accepted!\n"));
1670         return True;
1671 }
1672
1673 /*******************************************************************
1674  Creates a DCE/RPC bind authentication response.
1675  This is the packet that is sent back to the server once we
1676  have received a BIND-ACK, to finish the third leg of
1677  the authentication handshake.
1678  ********************************************************************/
1679
1680 static NTSTATUS create_rpc_bind_auth3(TALLOC_CTX *mem_ctx,
1681                                 struct rpc_pipe_client *cli,
1682                                 uint32 rpc_call_id,
1683                                 enum dcerpc_AuthType auth_type,
1684                                 enum dcerpc_AuthLevel auth_level,
1685                                 DATA_BLOB *pauth_blob,
1686                                 DATA_BLOB *rpc_out)
1687 {
1688         NTSTATUS status;
1689         union dcerpc_payload u;
1690
1691         u.auth3._pad = 0;
1692
1693         status = dcerpc_push_dcerpc_auth(mem_ctx,
1694                                          auth_type,
1695                                          auth_level,
1696                                          0, /* auth_pad_length */
1697                                          1, /* auth_context_id */
1698                                          pauth_blob,
1699                                          &u.auth3.auth_info);
1700         if (!NT_STATUS_IS_OK(status)) {
1701                 return status;
1702         }
1703
1704         status = dcerpc_push_ncacn_packet(mem_ctx,
1705                                           DCERPC_PKT_AUTH3,
1706                                           DCERPC_PFC_FLAG_FIRST |
1707                                           DCERPC_PFC_FLAG_LAST,
1708                                           pauth_blob->length,
1709                                           rpc_call_id,
1710                                           &u,
1711                                           rpc_out);
1712         data_blob_free(&u.auth3.auth_info);
1713         if (!NT_STATUS_IS_OK(status)) {
1714                 DEBUG(0,("create_bind_or_alt_ctx_internal: failed to marshall RPC_HDR_RB.\n"));
1715                 return status;
1716         }
1717
1718         return NT_STATUS_OK;
1719 }
1720
1721 /*******************************************************************
1722  Creates a DCE/RPC bind alter context authentication request which
1723  may contain a spnego auth blobl
1724  ********************************************************************/
1725
1726 static NTSTATUS create_rpc_alter_context(TALLOC_CTX *mem_ctx,
1727                                         enum dcerpc_AuthType auth_type,
1728                                         enum dcerpc_AuthLevel auth_level,
1729                                         uint32 rpc_call_id,
1730                                         const struct ndr_syntax_id *abstract,
1731                                         const struct ndr_syntax_id *transfer,
1732                                         const DATA_BLOB *pauth_blob, /* spnego auth blob already created. */
1733                                         DATA_BLOB *rpc_out)
1734 {
1735         DATA_BLOB auth_info;
1736         NTSTATUS status;
1737
1738         status = dcerpc_push_dcerpc_auth(mem_ctx,
1739                                          auth_type,
1740                                          auth_level,
1741                                          0, /* auth_pad_length */
1742                                          1, /* auth_context_id */
1743                                          pauth_blob,
1744                                          &auth_info);
1745         if (!NT_STATUS_IS_OK(status)) {
1746                 return status;
1747         }
1748
1749         status = create_bind_or_alt_ctx_internal(mem_ctx,
1750                                                  DCERPC_PKT_ALTER,
1751                                                  rpc_call_id,
1752                                                  abstract,
1753                                                  transfer,
1754                                                  &auth_info,
1755                                                  rpc_out);
1756         data_blob_free(&auth_info);
1757         return status;
1758 }
1759
1760 /****************************************************************************
1761  Do an rpc bind.
1762 ****************************************************************************/
1763
1764 struct rpc_pipe_bind_state {
1765         struct event_context *ev;
1766         struct rpc_pipe_client *cli;
1767         DATA_BLOB rpc_out;
1768         uint32_t rpc_call_id;
1769 };
1770
1771 static void rpc_pipe_bind_step_one_done(struct tevent_req *subreq);
1772 static NTSTATUS rpc_finish_auth3_bind_send(struct tevent_req *req,
1773                                            struct rpc_pipe_bind_state *state,
1774                                            DATA_BLOB *credentials);
1775 static void rpc_bind_auth3_write_done(struct tevent_req *subreq);
1776 static NTSTATUS rpc_bind_next_send(struct tevent_req *req,
1777                                    struct rpc_pipe_bind_state *state,
1778                                    DATA_BLOB *credentials);
1779 static NTSTATUS rpc_bind_finish_send(struct tevent_req *req,
1780                                      struct rpc_pipe_bind_state *state,
1781                                      DATA_BLOB *credentials);
1782
1783 struct tevent_req *rpc_pipe_bind_send(TALLOC_CTX *mem_ctx,
1784                                       struct event_context *ev,
1785                                       struct rpc_pipe_client *cli,
1786                                       struct pipe_auth_data *auth)
1787 {
1788         struct tevent_req *req, *subreq;
1789         struct rpc_pipe_bind_state *state;
1790         NTSTATUS status;
1791
1792         req = tevent_req_create(mem_ctx, &state, struct rpc_pipe_bind_state);
1793         if (req == NULL) {
1794                 return NULL;
1795         }
1796
1797         DEBUG(5,("Bind RPC Pipe: %s auth_type %u(%u), auth_level %u\n",
1798                 rpccli_pipe_txt(talloc_tos(), cli),
1799                 (unsigned int)auth->auth_type,
1800                 (unsigned int)auth->spnego_type,
1801                 (unsigned int)auth->auth_level ));
1802
1803         state->ev = ev;
1804         state->cli = cli;
1805         state->rpc_call_id = get_rpc_call_id();
1806         state->rpc_out = data_blob_null;
1807
1808         cli->auth = talloc_move(cli, &auth);
1809
1810         /* Marshall the outgoing data. */
1811         status = create_rpc_bind_req(state, cli,
1812                                      cli->auth,
1813                                      state->rpc_call_id,
1814                                      &cli->abstract_syntax,
1815                                      &cli->transfer_syntax,
1816                                      &state->rpc_out);
1817
1818         if (!NT_STATUS_IS_OK(status)) {
1819                 goto post_status;
1820         }
1821
1822         subreq = rpc_api_pipe_send(state, ev, cli, &state->rpc_out,
1823                                    DCERPC_PKT_BIND_ACK);
1824         if (subreq == NULL) {
1825                 goto fail;
1826         }
1827         tevent_req_set_callback(subreq, rpc_pipe_bind_step_one_done, req);
1828         return req;
1829
1830  post_status:
1831         tevent_req_nterror(req, status);
1832         return tevent_req_post(req, ev);
1833  fail:
1834         TALLOC_FREE(req);
1835         return NULL;
1836 }
1837
1838 static void rpc_pipe_bind_step_one_done(struct tevent_req *subreq)
1839 {
1840         struct tevent_req *req = tevent_req_callback_data(
1841                 subreq, struct tevent_req);
1842         struct rpc_pipe_bind_state *state = tevent_req_data(
1843                 req, struct rpc_pipe_bind_state);
1844         struct pipe_auth_data *pauth = state->cli->auth;
1845         DATA_BLOB reply_pdu;
1846         struct ncacn_packet *pkt;
1847         struct dcerpc_auth auth;
1848         DATA_BLOB auth_token = data_blob_null;
1849         NTSTATUS status;
1850
1851         status = rpc_api_pipe_recv(subreq, talloc_tos(), &pkt, &reply_pdu);
1852         TALLOC_FREE(subreq);
1853         if (!NT_STATUS_IS_OK(status)) {
1854                 DEBUG(3, ("rpc_pipe_bind: %s bind request returned %s\n",
1855                           rpccli_pipe_txt(talloc_tos(), state->cli),
1856                           nt_errstr(status)));
1857                 tevent_req_nterror(req, status);
1858                 return;
1859         }
1860
1861         if (!check_bind_response(&pkt->u.bind_ack, &state->cli->transfer_syntax)) {
1862                 DEBUG(2, ("rpc_pipe_bind: check_bind_response failed.\n"));
1863                 tevent_req_nterror(req, NT_STATUS_BUFFER_TOO_SMALL);
1864                 return;
1865         }
1866
1867         state->cli->max_xmit_frag = pkt->u.bind_ack.max_xmit_frag;
1868         state->cli->max_recv_frag = pkt->u.bind_ack.max_recv_frag;
1869
1870         switch(state->cli->auth->auth_type) {
1871
1872         case DCERPC_AUTH_TYPE_NONE:
1873         case DCERPC_AUTH_TYPE_SCHANNEL:
1874                 /* Bind complete. */
1875                 tevent_req_done(req);
1876                 return;
1877
1878         case DCERPC_AUTH_TYPE_NTLMSSP:
1879         case DCERPC_AUTH_TYPE_SPNEGO:
1880         case DCERPC_AUTH_TYPE_KRB5:
1881                 /* Paranoid lenght checks */
1882                 if (pkt->frag_length < DCERPC_AUTH_TRAILER_LENGTH
1883                                                 + pkt->auth_length) {
1884                         tevent_req_nterror(req,
1885                                         NT_STATUS_INFO_LENGTH_MISMATCH);
1886                         return;
1887                 }
1888                 /* get auth credentials */
1889                 status = dcerpc_pull_dcerpc_auth(talloc_tos(),
1890                                                  &pkt->u.bind_ack.auth_info,
1891                                                  &auth, false);
1892                 if (!NT_STATUS_IS_OK(status)) {
1893                         DEBUG(0, ("Failed to pull dcerpc auth: %s.\n",
1894                                   nt_errstr(status)));
1895                         tevent_req_nterror(req, status);
1896                         return;
1897                 }
1898                 break;
1899
1900         default:
1901                 goto err_out;
1902         }
1903
1904         /*
1905          * For authenticated binds we may need to do 3 or 4 leg binds.
1906          */
1907
1908         switch(state->cli->auth->auth_type) {
1909
1910         case DCERPC_AUTH_TYPE_NONE:
1911         case DCERPC_AUTH_TYPE_SCHANNEL:
1912                 /* Bind complete. */
1913                 tevent_req_done(req);
1914                 return;
1915
1916         case DCERPC_AUTH_TYPE_NTLMSSP:
1917                 /* Need to send AUTH3 packet - no reply. */
1918                 status = rpc_finish_auth3_bind_send(req, state,
1919                                                     &auth.credentials);
1920                 break;
1921
1922         case DCERPC_AUTH_TYPE_SPNEGO:
1923                 status = spnego_get_client_auth_token(state,
1924                                                 pauth->a_u.spnego_state,
1925                                                 &auth.credentials,
1926                                                 &auth_token);
1927                 if (!NT_STATUS_IS_OK(status)) {
1928                         break;
1929                 }
1930                 if (auth_token.length == 0) {
1931                         /* Bind complete. */
1932                         tevent_req_done(req);
1933                         return;
1934                 }
1935                 if (spnego_require_more_processing(pauth->a_u.spnego_state)) {
1936                         status = rpc_bind_next_send(req, state,
1937                                                         &auth_token);
1938                 } else {
1939                         status = rpc_bind_finish_send(req, state,
1940                                                         &auth_token);
1941                 }
1942                 break;
1943
1944         case DCERPC_AUTH_TYPE_KRB5:
1945                 status = gse_get_client_auth_token(state,
1946                                                    pauth->a_u.gssapi_state,
1947                                                    &auth.credentials,
1948                                                    &auth_token);
1949                 if (!NT_STATUS_IS_OK(status)) {
1950                         break;
1951                 }
1952
1953                 if (gse_require_more_processing(pauth->a_u.gssapi_state)) {
1954                         status = rpc_bind_next_send(req, state, &auth_token);
1955                 } else {
1956                         status = rpc_bind_finish_send(req, state, &auth_token);
1957                 }
1958                 break;
1959
1960         default:
1961                 goto err_out;
1962         }
1963
1964         if (!NT_STATUS_IS_OK(status)) {
1965                 tevent_req_nterror(req, status);
1966         }
1967         return;
1968
1969 err_out:
1970         DEBUG(0,("cli_finish_bind_auth: unknown auth type %u(%u)\n",
1971                  (unsigned int)state->cli->auth->auth_type,
1972                  (unsigned int)state->cli->auth->spnego_type));
1973         tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
1974 }
1975
1976 static NTSTATUS rpc_finish_auth3_bind_send(struct tevent_req *req,
1977                                            struct rpc_pipe_bind_state *state,
1978                                            DATA_BLOB *credentials)
1979 {
1980         struct pipe_auth_data *auth = state->cli->auth;
1981         DATA_BLOB client_reply = data_blob_null;
1982         struct tevent_req *subreq;
1983         NTSTATUS status;
1984
1985         /* TODO - check auth_type/auth_level match. */
1986
1987         status = auth_ntlmssp_update(auth->a_u.auth_ntlmssp_state,
1988                                      *credentials, &client_reply);
1989
1990         if (!NT_STATUS_IS_OK(status)) {
1991                 DEBUG(0, ("rpc_finish_auth3_bind: NTLMSSP update using server "
1992                           "blob failed: %s.\n", nt_errstr(status)));
1993                 return status;
1994         }
1995
1996         data_blob_free(&state->rpc_out);
1997
1998         status = create_rpc_bind_auth3(state, state->cli,
1999                                         state->rpc_call_id,
2000                                         auth->auth_type,
2001                                         auth->auth_level,
2002                                         &client_reply,
2003                                         &state->rpc_out);
2004         data_blob_free(&client_reply);
2005
2006         if (!NT_STATUS_IS_OK(status)) {
2007                 return status;
2008         }
2009
2010         subreq = rpc_write_send(state, state->ev, state->cli->transport,
2011                                 state->rpc_out.data, state->rpc_out.length);
2012         if (subreq == NULL) {
2013                 return NT_STATUS_NO_MEMORY;
2014         }
2015         tevent_req_set_callback(subreq, rpc_bind_auth3_write_done, req);
2016         return NT_STATUS_OK;
2017 }
2018
2019 static void rpc_bind_auth3_write_done(struct tevent_req *subreq)
2020 {
2021         struct tevent_req *req = tevent_req_callback_data(
2022                 subreq, struct tevent_req);
2023         NTSTATUS status;
2024
2025         status = rpc_write_recv(subreq);
2026         TALLOC_FREE(subreq);
2027         if (!NT_STATUS_IS_OK(status)) {
2028                 tevent_req_nterror(req, status);
2029                 return;
2030         }
2031         tevent_req_done(req);
2032 }
2033
2034 static NTSTATUS rpc_bind_next_send(struct tevent_req *req,
2035                                    struct rpc_pipe_bind_state *state,
2036                                    DATA_BLOB *auth_token)
2037 {
2038         struct pipe_auth_data *auth = state->cli->auth;
2039         struct tevent_req *subreq;
2040         NTSTATUS status;
2041
2042         /* Now prepare the alter context pdu. */
2043         data_blob_free(&state->rpc_out);
2044
2045         status = create_rpc_alter_context(state,
2046                                           auth->auth_type,
2047                                           auth->auth_level,
2048                                           state->rpc_call_id,
2049                                           &state->cli->abstract_syntax,
2050                                           &state->cli->transfer_syntax,
2051                                           auth_token,
2052                                           &state->rpc_out);
2053         if (!NT_STATUS_IS_OK(status)) {
2054                 return status;
2055         }
2056
2057         subreq = rpc_api_pipe_send(state, state->ev, state->cli,
2058                                    &state->rpc_out, DCERPC_PKT_ALTER_RESP);
2059         if (subreq == NULL) {
2060                 return NT_STATUS_NO_MEMORY;
2061         }
2062         tevent_req_set_callback(subreq, rpc_pipe_bind_step_one_done, req);
2063         return NT_STATUS_OK;
2064 }
2065
2066 static NTSTATUS rpc_bind_finish_send(struct tevent_req *req,
2067                                      struct rpc_pipe_bind_state *state,
2068                                      DATA_BLOB *auth_token)
2069 {
2070         struct pipe_auth_data *auth = state->cli->auth;
2071         struct tevent_req *subreq;
2072         NTSTATUS status;
2073
2074         /* Now prepare the auth3 context pdu. */
2075         data_blob_free(&state->rpc_out);
2076
2077         status = create_rpc_bind_auth3(state, state->cli,
2078                                         state->rpc_call_id,
2079                                         auth->auth_type,
2080                                         auth->auth_level,
2081                                         auth_token,
2082                                         &state->rpc_out);
2083         if (!NT_STATUS_IS_OK(status)) {
2084                 return status;
2085         }
2086
2087         subreq = rpc_write_send(state, state->ev, state->cli->transport,
2088                                 state->rpc_out.data, state->rpc_out.length);
2089         if (subreq == NULL) {
2090                 return NT_STATUS_NO_MEMORY;
2091         }
2092         tevent_req_set_callback(subreq, rpc_bind_auth3_write_done, req);
2093         return NT_STATUS_OK;
2094 }
2095
2096 NTSTATUS rpc_pipe_bind_recv(struct tevent_req *req)
2097 {
2098         return tevent_req_simple_recv_ntstatus(req);
2099 }
2100
2101 NTSTATUS rpc_pipe_bind(struct rpc_pipe_client *cli,
2102                        struct pipe_auth_data *auth)
2103 {
2104         TALLOC_CTX *frame = talloc_stackframe();
2105         struct event_context *ev;
2106         struct tevent_req *req;
2107         NTSTATUS status = NT_STATUS_OK;
2108
2109         ev = event_context_init(frame);
2110         if (ev == NULL) {
2111                 status = NT_STATUS_NO_MEMORY;
2112                 goto fail;
2113         }
2114
2115         req = rpc_pipe_bind_send(frame, ev, cli, auth);
2116         if (req == NULL) {
2117                 status = NT_STATUS_NO_MEMORY;
2118                 goto fail;
2119         }
2120
2121         if (!tevent_req_poll(req, ev)) {
2122                 status = map_nt_error_from_unix(errno);
2123                 goto fail;
2124         }
2125
2126         status = rpc_pipe_bind_recv(req);
2127  fail:
2128         TALLOC_FREE(frame);
2129         return status;
2130 }
2131
2132 #define RPCCLI_DEFAULT_TIMEOUT 10000 /* 10 seconds. */
2133
2134 unsigned int rpccli_set_timeout(struct rpc_pipe_client *rpc_cli,
2135                                 unsigned int timeout)
2136 {
2137         unsigned int old;
2138
2139         if (rpc_cli->transport == NULL) {
2140                 return RPCCLI_DEFAULT_TIMEOUT;
2141         }
2142
2143         if (rpc_cli->transport->set_timeout == NULL) {
2144                 return RPCCLI_DEFAULT_TIMEOUT;
2145         }
2146
2147         old = rpc_cli->transport->set_timeout(rpc_cli->transport->priv, timeout);
2148         if (old == 0) {
2149                 return RPCCLI_DEFAULT_TIMEOUT;
2150         }
2151
2152         return old;
2153 }
2154
2155 bool rpccli_is_connected(struct rpc_pipe_client *rpc_cli)
2156 {
2157         if (rpc_cli == NULL) {
2158                 return false;
2159         }
2160
2161         if (rpc_cli->transport == NULL) {
2162                 return false;
2163         }
2164
2165         return rpc_cli->transport->is_connected(rpc_cli->transport->priv);
2166 }
2167
2168 bool rpccli_get_pwd_hash(struct rpc_pipe_client *rpc_cli, uint8_t nt_hash[16])
2169 {
2170         struct auth_ntlmssp_state *a = NULL;
2171         struct cli_state *cli;
2172
2173         if (rpc_cli->auth->auth_type == DCERPC_AUTH_TYPE_NTLMSSP) {
2174                 a = rpc_cli->auth->a_u.auth_ntlmssp_state;
2175         } else if (rpc_cli->auth->auth_type == DCERPC_AUTH_TYPE_SPNEGO) {
2176                 enum dcerpc_AuthType auth_type;
2177                 void *auth_ctx;
2178                 NTSTATUS status;
2179
2180                 status = spnego_get_negotiated_mech(
2181                                         rpc_cli->auth->a_u.spnego_state,
2182                                         &auth_type, &auth_ctx);
2183                 if (!NT_STATUS_IS_OK(status)) {
2184                         return false;
2185                 }
2186
2187                 if (auth_type == DCERPC_AUTH_TYPE_NTLMSSP) {
2188                         a = talloc_get_type(auth_ctx,
2189                                             struct auth_ntlmssp_state);
2190                 }
2191         }
2192
2193         if (a) {
2194                 memcpy(nt_hash, auth_ntlmssp_get_nt_hash(a), 16);
2195                 return true;
2196         }
2197
2198         cli = rpc_pipe_np_smb_conn(rpc_cli);
2199         if (cli == NULL) {
2200                 return false;
2201         }
2202         E_md4hash(cli->password ? cli->password : "", nt_hash);
2203         return true;
2204 }
2205
2206 NTSTATUS rpccli_anon_bind_data(TALLOC_CTX *mem_ctx,
2207                                struct pipe_auth_data **presult)
2208 {
2209         struct pipe_auth_data *result;
2210
2211         result = talloc(mem_ctx, struct pipe_auth_data);
2212         if (result == NULL) {
2213                 return NT_STATUS_NO_MEMORY;
2214         }
2215
2216         result->auth_type = DCERPC_AUTH_TYPE_NONE;
2217         result->spnego_type = PIPE_AUTH_TYPE_SPNEGO_NONE;
2218         result->auth_level = DCERPC_AUTH_LEVEL_NONE;
2219
2220         result->user_name = talloc_strdup(result, "");
2221         result->domain = talloc_strdup(result, "");
2222         if ((result->user_name == NULL) || (result->domain == NULL)) {
2223                 TALLOC_FREE(result);
2224                 return NT_STATUS_NO_MEMORY;
2225         }
2226
2227         *presult = result;
2228         return NT_STATUS_OK;
2229 }
2230
2231 static int cli_auth_ntlmssp_data_destructor(struct pipe_auth_data *auth)
2232 {
2233         TALLOC_FREE(auth->a_u.auth_ntlmssp_state);
2234         return 0;
2235 }
2236
2237 static NTSTATUS rpccli_ntlmssp_bind_data(TALLOC_CTX *mem_ctx,
2238                                   enum dcerpc_AuthType auth_type,
2239                                   enum dcerpc_AuthLevel auth_level,
2240                                   const char *domain,
2241                                   const char *username,
2242                                   const char *password,
2243                                   struct pipe_auth_data **presult)
2244 {
2245         struct pipe_auth_data *result;
2246         NTSTATUS status;
2247
2248         result = talloc(mem_ctx, struct pipe_auth_data);
2249         if (result == NULL) {
2250                 return NT_STATUS_NO_MEMORY;
2251         }
2252
2253         result->auth_type = auth_type;
2254         result->auth_level = auth_level;
2255
2256         result->user_name = talloc_strdup(result, username);
2257         result->domain = talloc_strdup(result, domain);
2258         if ((result->user_name == NULL) || (result->domain == NULL)) {
2259                 status = NT_STATUS_NO_MEMORY;
2260                 goto fail;
2261         }
2262
2263         status = auth_ntlmssp_client_start(NULL,
2264                                       global_myname(),
2265                                       lp_workgroup(),
2266                                       lp_client_ntlmv2_auth(),
2267                                       &result->a_u.auth_ntlmssp_state);
2268         if (!NT_STATUS_IS_OK(status)) {
2269                 goto fail;
2270         }
2271
2272         talloc_set_destructor(result, cli_auth_ntlmssp_data_destructor);
2273
2274         status = auth_ntlmssp_set_username(result->a_u.auth_ntlmssp_state,
2275                                            username);
2276         if (!NT_STATUS_IS_OK(status)) {
2277                 goto fail;
2278         }
2279
2280         status = auth_ntlmssp_set_domain(result->a_u.auth_ntlmssp_state,
2281                                          domain);
2282         if (!NT_STATUS_IS_OK(status)) {
2283                 goto fail;
2284         }
2285
2286         status = auth_ntlmssp_set_password(result->a_u.auth_ntlmssp_state,
2287                                            password);
2288         if (!NT_STATUS_IS_OK(status)) {
2289                 goto fail;
2290         }
2291
2292         /*
2293          * Turn off sign+seal to allow selected auth level to turn it back on.
2294          */
2295         auth_ntlmssp_and_flags(result->a_u.auth_ntlmssp_state,
2296                                                 ~(NTLMSSP_NEGOTIATE_SIGN |
2297                                                   NTLMSSP_NEGOTIATE_SEAL));
2298
2299         if (auth_level == DCERPC_AUTH_LEVEL_INTEGRITY) {
2300                 auth_ntlmssp_or_flags(result->a_u.auth_ntlmssp_state,
2301                                                 NTLMSSP_NEGOTIATE_SIGN);
2302         } else if (auth_level == DCERPC_AUTH_LEVEL_PRIVACY) {
2303                 auth_ntlmssp_or_flags(result->a_u.auth_ntlmssp_state,
2304                                                 NTLMSSP_NEGOTIATE_SEAL |
2305                                                 NTLMSSP_NEGOTIATE_SIGN);
2306         }
2307
2308         *presult = result;
2309         return NT_STATUS_OK;
2310
2311  fail:
2312         TALLOC_FREE(result);
2313         return status;
2314 }
2315
2316 NTSTATUS rpccli_schannel_bind_data(TALLOC_CTX *mem_ctx, const char *domain,
2317                                    enum dcerpc_AuthLevel auth_level,
2318                                    struct netlogon_creds_CredentialState *creds,
2319                                    struct pipe_auth_data **presult)
2320 {
2321         struct pipe_auth_data *result;
2322
2323         result = talloc(mem_ctx, struct pipe_auth_data);
2324         if (result == NULL) {
2325                 return NT_STATUS_NO_MEMORY;
2326         }
2327
2328         result->auth_type = DCERPC_AUTH_TYPE_SCHANNEL;
2329         result->spnego_type = PIPE_AUTH_TYPE_SPNEGO_NONE;
2330         result->auth_level = auth_level;
2331
2332         result->user_name = talloc_strdup(result, "");
2333         result->domain = talloc_strdup(result, domain);
2334         if ((result->user_name == NULL) || (result->domain == NULL)) {
2335                 goto fail;
2336         }
2337
2338         result->a_u.schannel_auth = talloc(result, struct schannel_state);
2339         if (result->a_u.schannel_auth == NULL) {
2340                 goto fail;
2341         }
2342
2343         result->a_u.schannel_auth->state = SCHANNEL_STATE_START;
2344         result->a_u.schannel_auth->seq_num = 0;
2345         result->a_u.schannel_auth->initiator = true;
2346         result->a_u.schannel_auth->creds = creds;
2347
2348         *presult = result;
2349         return NT_STATUS_OK;
2350
2351  fail:
2352         TALLOC_FREE(result);
2353         return NT_STATUS_NO_MEMORY;
2354 }
2355
2356 /**
2357  * Create an rpc pipe client struct, connecting to a tcp port.
2358  */
2359 static NTSTATUS rpc_pipe_open_tcp_port(TALLOC_CTX *mem_ctx, const char *host,
2360                                        uint16_t port,
2361                                        const struct ndr_syntax_id *abstract_syntax,
2362                                        struct rpc_pipe_client **presult)
2363 {
2364         struct rpc_pipe_client *result;
2365         struct sockaddr_storage addr;
2366         NTSTATUS status;
2367         int fd;
2368
2369         result = TALLOC_ZERO_P(mem_ctx, struct rpc_pipe_client);
2370         if (result == NULL) {
2371                 return NT_STATUS_NO_MEMORY;
2372         }
2373
2374         result->abstract_syntax = *abstract_syntax;
2375         result->transfer_syntax = ndr_transfer_syntax;
2376         result->dispatch = cli_do_rpc_ndr;
2377         result->dispatch_send = cli_do_rpc_ndr_send;
2378         result->dispatch_recv = cli_do_rpc_ndr_recv;
2379
2380         result->desthost = talloc_strdup(result, host);
2381         result->srv_name_slash = talloc_asprintf_strupper_m(
2382                 result, "\\\\%s", result->desthost);
2383         if ((result->desthost == NULL) || (result->srv_name_slash == NULL)) {
2384                 status = NT_STATUS_NO_MEMORY;
2385                 goto fail;
2386         }
2387
2388         result->max_xmit_frag = RPC_MAX_PDU_FRAG_LEN;
2389         result->max_recv_frag = RPC_MAX_PDU_FRAG_LEN;
2390
2391         if (!resolve_name(host, &addr, 0, false)) {
2392                 status = NT_STATUS_NOT_FOUND;
2393                 goto fail;
2394         }
2395
2396         status = open_socket_out(&addr, port, 60, &fd);
2397         if (!NT_STATUS_IS_OK(status)) {
2398                 goto fail;
2399         }
2400         set_socket_options(fd, lp_socket_options());
2401
2402         status = rpc_transport_sock_init(result, fd, &result->transport);
2403         if (!NT_STATUS_IS_OK(status)) {
2404                 close(fd);
2405                 goto fail;
2406         }
2407
2408         result->transport->transport = NCACN_IP_TCP;
2409
2410         *presult = result;
2411         return NT_STATUS_OK;
2412
2413  fail:
2414         TALLOC_FREE(result);
2415         return status;
2416 }
2417
2418 /**
2419  * Determine the tcp port on which a dcerpc interface is listening
2420  * for the ncacn_ip_tcp transport via the endpoint mapper of the
2421  * target host.
2422  */
2423 static NTSTATUS rpc_pipe_get_tcp_port(const char *host,
2424                                       const struct ndr_syntax_id *abstract_syntax,
2425                                       uint16_t *pport)
2426 {
2427         NTSTATUS status;
2428         struct rpc_pipe_client *epm_pipe = NULL;
2429         struct pipe_auth_data *auth = NULL;
2430         struct dcerpc_binding *map_binding = NULL;
2431         struct dcerpc_binding *res_binding = NULL;
2432         struct epm_twr_t *map_tower = NULL;
2433         struct epm_twr_t *res_towers = NULL;
2434         struct policy_handle *entry_handle = NULL;
2435         uint32_t num_towers = 0;
2436         uint32_t max_towers = 1;
2437         struct epm_twr_p_t towers;
2438         TALLOC_CTX *tmp_ctx = talloc_stackframe();
2439
2440         if (pport == NULL) {
2441                 status = NT_STATUS_INVALID_PARAMETER;
2442                 goto done;
2443         }
2444
2445         /* open the connection to the endpoint mapper */
2446         status = rpc_pipe_open_tcp_port(tmp_ctx, host, 135,
2447                                         &ndr_table_epmapper.syntax_id,
2448                                         &epm_pipe);
2449
2450         if (!NT_STATUS_IS_OK(status)) {
2451                 goto done;
2452         }
2453
2454         status = rpccli_anon_bind_data(tmp_ctx, &auth);
2455         if (!NT_STATUS_IS_OK(status)) {
2456                 goto done;
2457         }
2458
2459         status = rpc_pipe_bind(epm_pipe, auth);
2460         if (!NT_STATUS_IS_OK(status)) {
2461                 goto done;
2462         }
2463
2464         /* create tower for asking the epmapper */
2465
2466         map_binding = TALLOC_ZERO_P(tmp_ctx, struct dcerpc_binding);
2467         if (map_binding == NULL) {
2468                 status = NT_STATUS_NO_MEMORY;
2469                 goto done;
2470         }
2471
2472         map_binding->transport = NCACN_IP_TCP;
2473         map_binding->object = *abstract_syntax;
2474         map_binding->host = host; /* needed? */
2475         map_binding->endpoint = "0"; /* correct? needed? */
2476
2477         map_tower = TALLOC_ZERO_P(tmp_ctx, struct epm_twr_t);
2478         if (map_tower == NULL) {
2479                 status = NT_STATUS_NO_MEMORY;
2480                 goto done;
2481         }
2482
2483         status = dcerpc_binding_build_tower(tmp_ctx, map_binding,
2484                                             &(map_tower->tower));
2485         if (!NT_STATUS_IS_OK(status)) {
2486                 goto done;
2487         }
2488
2489         /* allocate further parameters for the epm_Map call */
2490
2491         res_towers = TALLOC_ARRAY(tmp_ctx, struct epm_twr_t, max_towers);
2492         if (res_towers == NULL) {
2493                 status = NT_STATUS_NO_MEMORY;
2494                 goto done;
2495         }
2496         towers.twr = res_towers;
2497
2498         entry_handle = TALLOC_ZERO_P(tmp_ctx, struct policy_handle);
2499         if (entry_handle == NULL) {
2500                 status = NT_STATUS_NO_MEMORY;
2501                 goto done;
2502         }
2503
2504         /* ask the endpoint mapper for the port */
2505
2506         status = rpccli_epm_Map(epm_pipe,
2507                                 tmp_ctx,
2508                                 CONST_DISCARD(struct GUID *,
2509                                               &(abstract_syntax->uuid)),
2510                                 map_tower,
2511                                 entry_handle,
2512                                 max_towers,
2513                                 &num_towers,
2514                                 &towers);
2515
2516         if (!NT_STATUS_IS_OK(status)) {
2517                 goto done;
2518         }
2519
2520         if (num_towers != 1) {
2521                 status = NT_STATUS_UNSUCCESSFUL;
2522                 goto done;
2523         }
2524
2525         /* extract the port from the answer */
2526
2527         status = dcerpc_binding_from_tower(tmp_ctx,
2528                                            &(towers.twr->tower),
2529                                            &res_binding);
2530         if (!NT_STATUS_IS_OK(status)) {
2531                 goto done;
2532         }
2533
2534         /* are further checks here necessary? */
2535         if (res_binding->transport != NCACN_IP_TCP) {
2536                 status = NT_STATUS_UNSUCCESSFUL;
2537                 goto done;
2538         }
2539
2540         *pport = (uint16_t)atoi(res_binding->endpoint);
2541
2542 done:
2543         TALLOC_FREE(tmp_ctx);
2544         return status;
2545 }
2546
2547 /**
2548  * Create a rpc pipe client struct, connecting to a host via tcp.
2549  * The port is determined by asking the endpoint mapper on the given
2550  * host.
2551  */
2552 NTSTATUS rpc_pipe_open_tcp(TALLOC_CTX *mem_ctx, const char *host,
2553                            const struct ndr_syntax_id *abstract_syntax,
2554                            struct rpc_pipe_client **presult)
2555 {
2556         NTSTATUS status;
2557         uint16_t port = 0;
2558
2559         status = rpc_pipe_get_tcp_port(host, abstract_syntax, &port);
2560         if (!NT_STATUS_IS_OK(status)) {
2561                 return status;
2562         }
2563
2564         return rpc_pipe_open_tcp_port(mem_ctx, host, port,
2565                                         abstract_syntax, presult);
2566 }
2567
2568 /********************************************************************
2569  Create a rpc pipe client struct, connecting to a unix domain socket
2570  ********************************************************************/
2571 NTSTATUS rpc_pipe_open_ncalrpc(TALLOC_CTX *mem_ctx, const char *socket_path,
2572                                const struct ndr_syntax_id *abstract_syntax,
2573                                struct rpc_pipe_client **presult)
2574 {
2575         struct rpc_pipe_client *result;
2576         struct sockaddr_un addr;
2577         NTSTATUS status;
2578         int fd;
2579
2580         result = talloc_zero(mem_ctx, struct rpc_pipe_client);
2581         if (result == NULL) {
2582                 return NT_STATUS_NO_MEMORY;
2583         }
2584
2585         result->abstract_syntax = *abstract_syntax;
2586         result->transfer_syntax = ndr_transfer_syntax;
2587         result->dispatch = cli_do_rpc_ndr;
2588         result->dispatch_send = cli_do_rpc_ndr_send;
2589         result->dispatch_recv = cli_do_rpc_ndr_recv;
2590
2591         result->desthost = get_myname(result);
2592         result->srv_name_slash = talloc_asprintf_strupper_m(
2593                 result, "\\\\%s", result->desthost);
2594         if ((result->desthost == NULL) || (result->srv_name_slash == NULL)) {
2595                 status = NT_STATUS_NO_MEMORY;
2596                 goto fail;
2597         }
2598
2599         result->max_xmit_frag = RPC_MAX_PDU_FRAG_LEN;
2600         result->max_recv_frag = RPC_MAX_PDU_FRAG_LEN;
2601
2602         fd = socket(AF_UNIX, SOCK_STREAM, 0);
2603         if (fd == -1) {
2604                 status = map_nt_error_from_unix(errno);
2605                 goto fail;
2606         }
2607
2608         ZERO_STRUCT(addr);
2609         addr.sun_family = AF_UNIX;
2610         strncpy(addr.sun_path, socket_path, sizeof(addr.sun_path));
2611
2612         if (sys_connect(fd, (struct sockaddr *)(void *)&addr) == -1) {
2613                 DEBUG(0, ("connect(%s) failed: %s\n", socket_path,
2614                           strerror(errno)));
2615                 close(fd);
2616                 return map_nt_error_from_unix(errno);
2617         }
2618
2619         status = rpc_transport_sock_init(result, fd, &result->transport);
2620         if (!NT_STATUS_IS_OK(status)) {
2621                 close(fd);
2622                 goto fail;
2623         }
2624
2625         result->transport->transport = NCALRPC;
2626
2627         *presult = result;
2628         return NT_STATUS_OK;
2629
2630  fail:
2631         TALLOC_FREE(result);
2632         return status;
2633 }
2634
2635 struct rpc_pipe_client_np_ref {
2636         struct cli_state *cli;
2637         struct rpc_pipe_client *pipe;
2638 };
2639
2640 static int rpc_pipe_client_np_ref_destructor(struct rpc_pipe_client_np_ref *np_ref)
2641 {
2642         DLIST_REMOVE(np_ref->cli->pipe_list, np_ref->pipe);
2643         return 0;
2644 }
2645
2646 /****************************************************************************
2647  Open a named pipe over SMB to a remote server.
2648  *
2649  * CAVEAT CALLER OF THIS FUNCTION:
2650  *    The returned rpc_pipe_client saves a copy of the cli_state cli pointer,
2651  *    so be sure that this function is called AFTER any structure (vs pointer)
2652  *    assignment of the cli.  In particular, libsmbclient does structure
2653  *    assignments of cli, which invalidates the data in the returned
2654  *    rpc_pipe_client if this function is called before the structure assignment
2655  *    of cli.
2656  * 
2657  ****************************************************************************/
2658
2659 static NTSTATUS rpc_pipe_open_np(struct cli_state *cli,
2660                                  const struct ndr_syntax_id *abstract_syntax,
2661                                  struct rpc_pipe_client **presult)
2662 {
2663         struct rpc_pipe_client *result;
2664         NTSTATUS status;
2665         struct rpc_pipe_client_np_ref *np_ref;
2666
2667         /* sanity check to protect against crashes */
2668
2669         if ( !cli ) {
2670                 return NT_STATUS_INVALID_HANDLE;
2671         }
2672
2673         result = TALLOC_ZERO_P(NULL, struct rpc_pipe_client);
2674         if (result == NULL) {
2675                 return NT_STATUS_NO_MEMORY;
2676         }
2677
2678         result->abstract_syntax = *abstract_syntax;
2679         result->transfer_syntax = ndr_transfer_syntax;
2680         result->dispatch = cli_do_rpc_ndr;
2681         result->dispatch_send = cli_do_rpc_ndr_send;
2682         result->dispatch_recv = cli_do_rpc_ndr_recv;
2683         result->desthost = talloc_strdup(result, cli->desthost);
2684         result->srv_name_slash = talloc_asprintf_strupper_m(
2685                 result, "\\\\%s", result->desthost);
2686
2687         result->max_xmit_frag = RPC_MAX_PDU_FRAG_LEN;
2688         result->max_recv_frag = RPC_MAX_PDU_FRAG_LEN;
2689
2690         if ((result->desthost == NULL) || (result->srv_name_slash == NULL)) {
2691                 TALLOC_FREE(result);
2692                 return NT_STATUS_NO_MEMORY;
2693         }
2694
2695         status = rpc_transport_np_init(result, cli, abstract_syntax,
2696                                        &result->transport);
2697         if (!NT_STATUS_IS_OK(status)) {
2698                 TALLOC_FREE(result);
2699                 return status;
2700         }
2701
2702         result->transport->transport = NCACN_NP;
2703
2704         np_ref = talloc(result->transport, struct rpc_pipe_client_np_ref);
2705         if (np_ref == NULL) {
2706                 TALLOC_FREE(result);
2707                 return NT_STATUS_NO_MEMORY;
2708         }
2709         np_ref->cli = cli;
2710         np_ref->pipe = result;
2711
2712         DLIST_ADD(np_ref->cli->pipe_list, np_ref->pipe);
2713         talloc_set_destructor(np_ref, rpc_pipe_client_np_ref_destructor);
2714
2715         *presult = result;
2716         return NT_STATUS_OK;
2717 }
2718
2719 NTSTATUS rpc_pipe_open_local(TALLOC_CTX *mem_ctx,
2720                              struct rpc_cli_smbd_conn *conn,
2721                              const struct ndr_syntax_id *syntax,
2722                              struct rpc_pipe_client **presult)
2723 {
2724         struct rpc_pipe_client *result;
2725         struct pipe_auth_data *auth;
2726         NTSTATUS status;
2727
2728         result = talloc(mem_ctx, struct rpc_pipe_client);
2729         if (result == NULL) {
2730                 return NT_STATUS_NO_MEMORY;
2731         }
2732         result->abstract_syntax = *syntax;
2733         result->transfer_syntax = ndr_transfer_syntax;
2734         result->dispatch = cli_do_rpc_ndr;
2735         result->dispatch_send = cli_do_rpc_ndr_send;
2736         result->dispatch_recv = cli_do_rpc_ndr_recv;
2737         result->max_xmit_frag = RPC_MAX_PDU_FRAG_LEN;
2738         result->max_recv_frag = RPC_MAX_PDU_FRAG_LEN;
2739
2740         result->desthost = talloc_strdup(result, global_myname());
2741         result->srv_name_slash = talloc_asprintf_strupper_m(
2742                 result, "\\\\%s", global_myname());
2743         if ((result->desthost == NULL) || (result->srv_name_slash == NULL)) {
2744                 TALLOC_FREE(result);
2745                 return NT_STATUS_NO_MEMORY;
2746         }
2747
2748         status = rpc_transport_smbd_init(result, conn, syntax,
2749                                          &result->transport);
2750         if (!NT_STATUS_IS_OK(status)) {
2751                 DEBUG(1, ("rpc_transport_smbd_init failed: %s\n",
2752                           nt_errstr(status)));
2753                 TALLOC_FREE(result);
2754                 return status;
2755         }
2756
2757         status = rpccli_anon_bind_data(result, &auth);
2758         if (!NT_STATUS_IS_OK(status)) {
2759                 DEBUG(1, ("rpccli_anon_bind_data failed: %s\n",
2760                           nt_errstr(status)));
2761                 TALLOC_FREE(result);
2762                 return status;
2763         }
2764
2765         status = rpc_pipe_bind(result, auth);
2766         if (!NT_STATUS_IS_OK(status)) {
2767                 DEBUG(1, ("rpc_pipe_bind failed: %s\n", nt_errstr(status)));
2768                 TALLOC_FREE(result);
2769                 return status;
2770         }
2771
2772         result->transport->transport = NCACN_INTERNAL;
2773
2774         *presult = result;
2775         return NT_STATUS_OK;
2776 }
2777
2778 /****************************************************************************
2779  Open a pipe to a remote server.
2780  ****************************************************************************/
2781
2782 static NTSTATUS cli_rpc_pipe_open(struct cli_state *cli,
2783                                   enum dcerpc_transport_t transport,
2784                                   const struct ndr_syntax_id *interface,
2785                                   struct rpc_pipe_client **presult)
2786 {
2787         switch (transport) {
2788         case NCACN_IP_TCP:
2789                 return rpc_pipe_open_tcp(NULL, cli->desthost, interface,
2790                                          presult);
2791         case NCACN_NP:
2792                 return rpc_pipe_open_np(cli, interface, presult);
2793         default:
2794                 return NT_STATUS_NOT_IMPLEMENTED;
2795         }
2796 }
2797
2798 /****************************************************************************
2799  Open a named pipe to an SMB server and bind anonymously.
2800  ****************************************************************************/
2801
2802 NTSTATUS cli_rpc_pipe_open_noauth_transport(struct cli_state *cli,
2803                                             enum dcerpc_transport_t transport,
2804                                             const struct ndr_syntax_id *interface,
2805                                             struct rpc_pipe_client **presult)
2806 {
2807         struct rpc_pipe_client *result;
2808         struct pipe_auth_data *auth;
2809         NTSTATUS status;
2810
2811         status = cli_rpc_pipe_open(cli, transport, interface, &result);
2812         if (!NT_STATUS_IS_OK(status)) {
2813                 return status;
2814         }
2815
2816         status = rpccli_anon_bind_data(result, &auth);
2817         if (!NT_STATUS_IS_OK(status)) {
2818                 DEBUG(0, ("rpccli_anon_bind_data returned %s\n",
2819                           nt_errstr(status)));
2820                 TALLOC_FREE(result);
2821                 return status;
2822         }
2823
2824         /*
2825          * This is a bit of an abstraction violation due to the fact that an
2826          * anonymous bind on an authenticated SMB inherits the user/domain
2827          * from the enclosing SMB creds
2828          */
2829
2830         TALLOC_FREE(auth->user_name);
2831         TALLOC_FREE(auth->domain);
2832
2833         auth->user_name = talloc_strdup(auth, cli->user_name);
2834         auth->domain = talloc_strdup(auth, cli->domain);
2835         auth->user_session_key = data_blob_talloc(auth,
2836                 cli->user_session_key.data,
2837                 cli->user_session_key.length);
2838
2839         if ((auth->user_name == NULL) || (auth->domain == NULL)) {
2840                 TALLOC_FREE(result);
2841                 return NT_STATUS_NO_MEMORY;
2842         }
2843
2844         status = rpc_pipe_bind(result, auth);
2845         if (!NT_STATUS_IS_OK(status)) {
2846                 int lvl = 0;
2847                 if (ndr_syntax_id_equal(interface,
2848                                         &ndr_table_dssetup.syntax_id)) {
2849                         /* non AD domains just don't have this pipe, avoid
2850                          * level 0 statement in that case - gd */
2851                         lvl = 3;
2852                 }
2853                 DEBUG(lvl, ("cli_rpc_pipe_open_noauth: rpc_pipe_bind for pipe "
2854                             "%s failed with error %s\n",
2855                             get_pipe_name_from_syntax(talloc_tos(), interface),
2856                             nt_errstr(status) ));
2857                 TALLOC_FREE(result);
2858                 return status;
2859         }
2860
2861         DEBUG(10,("cli_rpc_pipe_open_noauth: opened pipe %s to machine "
2862                   "%s and bound anonymously.\n",
2863                   get_pipe_name_from_syntax(talloc_tos(), interface),
2864                   cli->desthost));
2865
2866         *presult = result;
2867         return NT_STATUS_OK;
2868 }
2869
2870 /****************************************************************************
2871  ****************************************************************************/
2872
2873 NTSTATUS cli_rpc_pipe_open_noauth(struct cli_state *cli,
2874                                   const struct ndr_syntax_id *interface,
2875                                   struct rpc_pipe_client **presult)
2876 {
2877         return cli_rpc_pipe_open_noauth_transport(cli, NCACN_NP,
2878                                                   interface, presult);
2879 }
2880
2881 /****************************************************************************
2882  Open a named pipe to an SMB server and bind using NTLMSSP or SPNEGO NTLMSSP
2883  ****************************************************************************/
2884
2885 NTSTATUS cli_rpc_pipe_open_ntlmssp(struct cli_state *cli,
2886                                    const struct ndr_syntax_id *interface,
2887                                    enum dcerpc_transport_t transport,
2888                                    enum dcerpc_AuthLevel auth_level,
2889                                    const char *domain,
2890                                    const char *username,
2891                                    const char *password,
2892                                    struct rpc_pipe_client **presult)
2893 {
2894         struct rpc_pipe_client *result;
2895         struct pipe_auth_data *auth;
2896         enum dcerpc_AuthType auth_type = DCERPC_AUTH_TYPE_NTLMSSP;
2897         NTSTATUS status;
2898
2899         status = cli_rpc_pipe_open(cli, transport, interface, &result);
2900         if (!NT_STATUS_IS_OK(status)) {
2901                 return status;
2902         }
2903
2904         status = rpccli_ntlmssp_bind_data(result,
2905                                           auth_type, auth_level,
2906                                           domain, username, password,
2907                                           &auth);
2908         if (!NT_STATUS_IS_OK(status)) {
2909                 DEBUG(0, ("rpccli_ntlmssp_bind_data returned %s\n",
2910                           nt_errstr(status)));
2911                 goto err;
2912         }
2913
2914         status = rpc_pipe_bind(result, auth);
2915         if (!NT_STATUS_IS_OK(status)) {
2916                 DEBUG(0, ("cli_rpc_pipe_open_ntlmssp_internal: cli_rpc_pipe_bind failed with error %s\n",
2917                         nt_errstr(status) ));
2918                 goto err;
2919         }
2920
2921         DEBUG(10,("cli_rpc_pipe_open_ntlmssp_internal: opened pipe %s to "
2922                 "machine %s and bound NTLMSSP as user %s\\%s.\n",
2923                   get_pipe_name_from_syntax(talloc_tos(), interface),
2924                   cli->desthost, domain, username ));
2925
2926         *presult = result;
2927         return NT_STATUS_OK;
2928
2929   err:
2930
2931         TALLOC_FREE(result);
2932         return status;
2933 }
2934
2935 /****************************************************************************
2936   Get a the schannel session key out of an already opened netlogon pipe.
2937  ****************************************************************************/
2938 static NTSTATUS get_schannel_session_key_common(struct rpc_pipe_client *netlogon_pipe,
2939                                                 struct cli_state *cli,
2940                                                 const char *domain,
2941                                                 uint32 *pneg_flags)
2942 {
2943         enum netr_SchannelType sec_chan_type = 0;
2944         unsigned char machine_pwd[16];
2945         const char *machine_account;
2946         NTSTATUS status;
2947
2948         /* Get the machine account credentials from secrets.tdb. */
2949         if (!get_trust_pw_hash(domain, machine_pwd, &machine_account,
2950                                &sec_chan_type))
2951         {
2952                 DEBUG(0, ("get_schannel_session_key: could not fetch "
2953                         "trust account password for domain '%s'\n",
2954                         domain));
2955                 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
2956         }
2957
2958         status = rpccli_netlogon_setup_creds(netlogon_pipe,
2959                                         cli->desthost, /* server name */
2960                                         domain,        /* domain */
2961                                         global_myname(), /* client name */
2962                                         machine_account, /* machine account name */
2963                                         machine_pwd,
2964                                         sec_chan_type,
2965                                         pneg_flags);
2966
2967         if (!NT_STATUS_IS_OK(status)) {
2968                 DEBUG(3, ("get_schannel_session_key_common: "
2969                           "rpccli_netlogon_setup_creds failed with result %s "
2970                           "to server %s, domain %s, machine account %s.\n",
2971                           nt_errstr(status), cli->desthost, domain,
2972                           machine_account ));
2973                 return status;
2974         }
2975
2976         if (((*pneg_flags) & NETLOGON_NEG_SCHANNEL) == 0) {
2977                 DEBUG(3, ("get_schannel_session_key: Server %s did not offer schannel\n",
2978                         cli->desthost));
2979                 return NT_STATUS_INVALID_NETWORK_RESPONSE;
2980         }
2981
2982         return NT_STATUS_OK;;
2983 }
2984
2985 /****************************************************************************
2986  Open a netlogon pipe and get the schannel session key.
2987  Now exposed to external callers.
2988  ****************************************************************************/
2989
2990
2991 NTSTATUS get_schannel_session_key(struct cli_state *cli,
2992                                   const char *domain,
2993                                   uint32 *pneg_flags,
2994                                   struct rpc_pipe_client **presult)
2995 {
2996         struct rpc_pipe_client *netlogon_pipe = NULL;
2997         NTSTATUS status;
2998
2999         status = cli_rpc_pipe_open_noauth(cli, &ndr_table_netlogon.syntax_id,
3000                                           &netlogon_pipe);
3001         if (!NT_STATUS_IS_OK(status)) {
3002                 return status;
3003         }
3004
3005         status = get_schannel_session_key_common(netlogon_pipe, cli, domain,
3006                                                  pneg_flags);
3007         if (!NT_STATUS_IS_OK(status)) {
3008                 TALLOC_FREE(netlogon_pipe);
3009                 return status;
3010         }
3011
3012         *presult = netlogon_pipe;
3013         return NT_STATUS_OK;
3014 }
3015
3016 /****************************************************************************
3017  External interface.
3018  Open a named pipe to an SMB server and bind using schannel (bind type 68)
3019  using session_key. sign and seal.
3020
3021  The *pdc will be stolen onto this new pipe
3022  ****************************************************************************/
3023
3024 NTSTATUS cli_rpc_pipe_open_schannel_with_key(struct cli_state *cli,
3025                                              const struct ndr_syntax_id *interface,
3026                                              enum dcerpc_transport_t transport,
3027                                              enum dcerpc_AuthLevel auth_level,
3028                                              const char *domain,
3029                                              struct netlogon_creds_CredentialState **pdc,
3030                                              struct rpc_pipe_client **presult)
3031 {
3032         struct rpc_pipe_client *result;
3033         struct pipe_auth_data *auth;
3034         NTSTATUS status;
3035
3036         status = cli_rpc_pipe_open(cli, transport, interface, &result);
3037         if (!NT_STATUS_IS_OK(status)) {
3038                 return status;
3039         }
3040
3041         status = rpccli_schannel_bind_data(result, domain, auth_level,
3042                                            *pdc, &auth);
3043         if (!NT_STATUS_IS_OK(status)) {
3044                 DEBUG(0, ("rpccli_schannel_bind_data returned %s\n",
3045                           nt_errstr(status)));
3046                 TALLOC_FREE(result);
3047                 return status;
3048         }
3049
3050         status = rpc_pipe_bind(result, auth);
3051         if (!NT_STATUS_IS_OK(status)) {
3052                 DEBUG(0, ("cli_rpc_pipe_open_schannel_with_key: "
3053                           "cli_rpc_pipe_bind failed with error %s\n",
3054                           nt_errstr(status) ));
3055                 TALLOC_FREE(result);
3056                 return status;
3057         }
3058
3059         /*
3060          * The credentials on a new netlogon pipe are the ones we are passed
3061          * in - reference them in
3062          */
3063         result->dc = talloc_move(result, pdc);
3064
3065         DEBUG(10,("cli_rpc_pipe_open_schannel_with_key: opened pipe %s to machine %s "
3066                   "for domain %s and bound using schannel.\n",
3067                   get_pipe_name_from_syntax(talloc_tos(), interface),
3068                   cli->desthost, domain ));
3069
3070         *presult = result;
3071         return NT_STATUS_OK;
3072 }
3073
3074 /****************************************************************************
3075  Open a named pipe to an SMB server and bind using schannel (bind type 68).
3076  Fetch the session key ourselves using a temporary netlogon pipe. This
3077  version uses an ntlmssp auth bound netlogon pipe to get the key.
3078  ****************************************************************************/
3079
3080 static NTSTATUS get_schannel_session_key_auth_ntlmssp(struct cli_state *cli,
3081                                                       const char *domain,
3082                                                       const char *username,
3083                                                       const char *password,
3084                                                       uint32 *pneg_flags,
3085                                                       struct rpc_pipe_client **presult)
3086 {
3087         struct rpc_pipe_client *netlogon_pipe = NULL;
3088         NTSTATUS status;
3089
3090         status = cli_rpc_pipe_open_spnego_ntlmssp(
3091                 cli, &ndr_table_netlogon.syntax_id, NCACN_NP,
3092                 DCERPC_AUTH_LEVEL_PRIVACY,
3093                 domain, username, password, &netlogon_pipe);
3094         if (!NT_STATUS_IS_OK(status)) {
3095                 return status;
3096         }
3097
3098         status = get_schannel_session_key_common(netlogon_pipe, cli, domain,
3099                                                  pneg_flags);
3100         if (!NT_STATUS_IS_OK(status)) {
3101                 TALLOC_FREE(netlogon_pipe);
3102                 return status;
3103         }
3104
3105         *presult = netlogon_pipe;
3106         return NT_STATUS_OK;
3107 }
3108
3109 /****************************************************************************
3110  Open a named pipe to an SMB server and bind using schannel (bind type 68).
3111  Fetch the session key ourselves using a temporary netlogon pipe. This version
3112  uses an ntlmssp bind to get the session key.
3113  ****************************************************************************/
3114
3115 NTSTATUS cli_rpc_pipe_open_ntlmssp_auth_schannel(struct cli_state *cli,
3116                                                  const struct ndr_syntax_id *interface,
3117                                                  enum dcerpc_transport_t transport,
3118                                                  enum dcerpc_AuthLevel auth_level,
3119                                                  const char *domain,
3120                                                  const char *username,
3121                                                  const char *password,
3122                                                  struct rpc_pipe_client **presult)
3123 {
3124         uint32_t neg_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS;
3125         struct rpc_pipe_client *netlogon_pipe = NULL;
3126         struct rpc_pipe_client *result = NULL;
3127         NTSTATUS status;
3128
3129         status = get_schannel_session_key_auth_ntlmssp(
3130                 cli, domain, username, password, &neg_flags, &netlogon_pipe);
3131         if (!NT_STATUS_IS_OK(status)) {
3132                 DEBUG(0,("cli_rpc_pipe_open_ntlmssp_auth_schannel: failed to get schannel session "
3133                         "key from server %s for domain %s.\n",
3134                         cli->desthost, domain ));
3135                 return status;
3136         }
3137
3138         status = cli_rpc_pipe_open_schannel_with_key(
3139                 cli, interface, transport, auth_level, domain, &netlogon_pipe->dc,
3140                 &result);
3141
3142         /* Now we've bound using the session key we can close the netlog pipe. */
3143         TALLOC_FREE(netlogon_pipe);
3144
3145         if (NT_STATUS_IS_OK(status)) {
3146                 *presult = result;
3147         }
3148         return status;
3149 }
3150
3151 /****************************************************************************
3152  Open a named pipe to an SMB server and bind using schannel (bind type 68).
3153  Fetch the session key ourselves using a temporary netlogon pipe.
3154  ****************************************************************************/
3155
3156 NTSTATUS cli_rpc_pipe_open_schannel(struct cli_state *cli,
3157                                     const struct ndr_syntax_id *interface,
3158                                     enum dcerpc_transport_t transport,
3159                                     enum dcerpc_AuthLevel auth_level,
3160                                     const char *domain,
3161                                     struct rpc_pipe_client **presult)
3162 {
3163         uint32_t neg_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS;
3164         struct rpc_pipe_client *netlogon_pipe = NULL;
3165         struct rpc_pipe_client *result = NULL;
3166         NTSTATUS status;
3167
3168         status = get_schannel_session_key(cli, domain, &neg_flags,
3169                                           &netlogon_pipe);
3170         if (!NT_STATUS_IS_OK(status)) {
3171                 DEBUG(0,("cli_rpc_pipe_open_schannel: failed to get schannel session "
3172                         "key from server %s for domain %s.\n",
3173                         cli->desthost, domain ));
3174                 return status;
3175         }
3176
3177         status = cli_rpc_pipe_open_schannel_with_key(
3178                 cli, interface, transport, auth_level, domain, &netlogon_pipe->dc,
3179                 &result);
3180
3181         /* Now we've bound using the session key we can close the netlog pipe. */
3182         TALLOC_FREE(netlogon_pipe);
3183
3184         if (NT_STATUS_IS_OK(status)) {
3185                 *presult = result;
3186         }
3187
3188         return status;
3189 }
3190
3191 /****************************************************************************
3192  Open a named pipe to an SMB server and bind using krb5 (bind type 16).
3193  The idea is this can be called with service_princ, username and password all
3194  NULL so long as the caller has a TGT.
3195  ****************************************************************************/
3196
3197 NTSTATUS cli_rpc_pipe_open_krb5(struct cli_state *cli,
3198                                 const struct ndr_syntax_id *interface,
3199                                 enum dcerpc_transport_t transport,
3200                                 enum dcerpc_AuthLevel auth_level,
3201                                 const char *server,
3202                                 const char *username,
3203                                 const char *password,
3204                                 struct rpc_pipe_client **presult)
3205 {
3206         struct rpc_pipe_client *result;
3207         struct pipe_auth_data *auth;
3208         NTSTATUS status;
3209
3210         status = cli_rpc_pipe_open(cli, transport, interface, &result);
3211         if (!NT_STATUS_IS_OK(status)) {
3212                 return status;
3213         }
3214
3215         auth = talloc(result, struct pipe_auth_data);
3216         if (auth == NULL) {
3217                 status = NT_STATUS_NO_MEMORY;
3218                 goto err_out;
3219         }
3220         auth->auth_type = DCERPC_AUTH_TYPE_KRB5;
3221         auth->auth_level = auth_level;
3222
3223         if (!username) {
3224                 username = "";
3225         }
3226         auth->user_name = talloc_strdup(auth, username);
3227         if (!auth->user_name) {
3228                 status = NT_STATUS_NO_MEMORY;
3229                 goto err_out;
3230         }
3231
3232         /* Fixme, should we fetch/set the Realm ? */
3233         auth->domain = talloc_strdup(auth, "");
3234         if (!auth->domain) {
3235                 status = NT_STATUS_NO_MEMORY;
3236                 goto err_out;
3237         }
3238
3239         status = gse_init_client(auth, auth->auth_type, auth->auth_level,
3240                                  NULL, server, "cifs", username, password,
3241                                  GSS_C_DCE_STYLE, &auth->a_u.gssapi_state);
3242
3243         if (!NT_STATUS_IS_OK(status)) {
3244                 DEBUG(0, ("gse_init_client returned %s\n",
3245                           nt_errstr(status)));
3246                 goto err_out;
3247         }
3248
3249         status = rpc_pipe_bind(result, auth);
3250         if (!NT_STATUS_IS_OK(status)) {
3251                 DEBUG(0, ("cli_rpc_pipe_bind failed with error %s\n",
3252                           nt_errstr(status)));
3253                 goto err_out;
3254         }
3255
3256         *presult = result;
3257         return NT_STATUS_OK;
3258
3259 err_out:
3260         TALLOC_FREE(result);
3261         return status;
3262 }
3263
3264 NTSTATUS cli_rpc_pipe_open_spnego_krb5(struct cli_state *cli,
3265                                         const struct ndr_syntax_id *interface,
3266                                         enum dcerpc_transport_t transport,
3267                                         enum dcerpc_AuthLevel auth_level,
3268                                         const char *server,
3269                                         const char *username,
3270                                         const char *password,
3271                                         struct rpc_pipe_client **presult)
3272 {
3273         struct rpc_pipe_client *result;
3274         struct pipe_auth_data *auth;
3275         NTSTATUS status;
3276
3277         status = cli_rpc_pipe_open(cli, transport, interface, &result);
3278         if (!NT_STATUS_IS_OK(status)) {
3279                 return status;
3280         }
3281
3282         auth = talloc(result, struct pipe_auth_data);
3283         if (auth == NULL) {
3284                 status = NT_STATUS_NO_MEMORY;
3285                 goto err_out;
3286         }
3287         auth->auth_type = DCERPC_AUTH_TYPE_SPNEGO;
3288         auth->auth_level = auth_level;
3289         /* compat */
3290         auth->spnego_type = PIPE_AUTH_TYPE_SPNEGO_KRB5;
3291
3292         if (!username) {
3293                 username = "";
3294         }
3295         auth->user_name = talloc_strdup(auth, username);
3296         if (!auth->user_name) {
3297                 status = NT_STATUS_NO_MEMORY;
3298                 goto err_out;
3299         }
3300
3301         /* Fixme, should we fetch/set the Realm ? */
3302         auth->domain = talloc_strdup(auth, "");
3303         if (!auth->domain) {
3304                 status = NT_STATUS_NO_MEMORY;
3305                 goto err_out;
3306         }
3307
3308         status = spnego_gssapi_init_client(auth, auth->auth_level,
3309                                            NULL, server, "cifs",
3310                                            username, password,
3311                                            GSS_C_DCE_STYLE,
3312                                            &auth->a_u.spnego_state);
3313         if (!NT_STATUS_IS_OK(status)) {
3314                 DEBUG(0, ("spnego_init_client returned %s\n",
3315                           nt_errstr(status)));
3316                 goto err_out;
3317         }
3318
3319         status = rpc_pipe_bind(result, auth);
3320         if (!NT_STATUS_IS_OK(status)) {
3321                 DEBUG(0, ("cli_rpc_pipe_bind failed with error %s\n",
3322                           nt_errstr(status)));
3323                 goto err_out;
3324         }
3325
3326         *presult = result;
3327         return NT_STATUS_OK;
3328
3329 err_out:
3330         TALLOC_FREE(result);
3331         return status;
3332 }
3333
3334 NTSTATUS cli_rpc_pipe_open_spnego_ntlmssp(struct cli_state *cli,
3335                                           const struct ndr_syntax_id *interface,
3336                                           enum dcerpc_transport_t transport,
3337                                           enum dcerpc_AuthLevel auth_level,
3338                                           const char *domain,
3339                                           const char *username,
3340                                           const char *password,
3341                                           struct rpc_pipe_client **presult)
3342 {
3343         struct rpc_pipe_client *result;
3344         struct pipe_auth_data *auth;
3345         NTSTATUS status;
3346
3347         status = cli_rpc_pipe_open(cli, transport, interface, &result);
3348         if (!NT_STATUS_IS_OK(status)) {
3349                 return status;
3350         }
3351
3352         auth = talloc(result, struct pipe_auth_data);
3353         if (auth == NULL) {
3354                 status = NT_STATUS_NO_MEMORY;
3355                 goto err_out;
3356         }
3357         auth->auth_type = DCERPC_AUTH_TYPE_SPNEGO;
3358         auth->auth_level = auth_level;
3359
3360         if (!username) {
3361                 username = "";
3362         }
3363         auth->user_name = talloc_strdup(auth, username);
3364         if (!auth->user_name) {
3365                 status = NT_STATUS_NO_MEMORY;
3366                 goto err_out;
3367         }
3368
3369         if (!domain) {
3370                 domain = "";
3371         }
3372         auth->domain = talloc_strdup(auth, domain);
3373         if (!auth->domain) {
3374                 status = NT_STATUS_NO_MEMORY;
3375                 goto err_out;
3376         }
3377
3378         status = spnego_ntlmssp_init_client(auth, auth->auth_level,
3379                                             domain, username, password,
3380                                             &auth->a_u.spnego_state);
3381         if (!NT_STATUS_IS_OK(status)) {
3382                 DEBUG(0, ("spnego_init_client returned %s\n",
3383                           nt_errstr(status)));
3384                 goto err_out;
3385         }
3386
3387         status = rpc_pipe_bind(result, auth);
3388         if (!NT_STATUS_IS_OK(status)) {
3389                 DEBUG(0, ("cli_rpc_pipe_bind failed with error %s\n",
3390                           nt_errstr(status)));
3391                 goto err_out;
3392         }
3393
3394         *presult = result;
3395         return NT_STATUS_OK;
3396
3397 err_out:
3398         TALLOC_FREE(result);
3399         return status;
3400 }
3401
3402 NTSTATUS cli_get_session_key(TALLOC_CTX *mem_ctx,
3403                              struct rpc_pipe_client *cli,
3404                              DATA_BLOB *session_key)
3405 {
3406         struct pipe_auth_data *a = cli->auth;
3407         DATA_BLOB sk;
3408
3409         if (!session_key || !cli) {
3410                 return NT_STATUS_INVALID_PARAMETER;
3411         }
3412
3413         if (!cli->auth) {
3414                 return NT_STATUS_INVALID_PARAMETER;
3415         }
3416
3417         switch (cli->auth->auth_type) {
3418         case DCERPC_AUTH_TYPE_SCHANNEL:
3419                 sk = data_blob_const(a->a_u.schannel_auth->creds->session_key,
3420                                      16);
3421                 break;
3422         case DCERPC_AUTH_TYPE_SPNEGO:
3423                 sk = spnego_get_session_key(a->a_u.spnego_state);
3424                 if (sk.length == 0) {
3425                         return NT_STATUS_NO_USER_SESSION_KEY;
3426                 }
3427                 break;
3428         case DCERPC_AUTH_TYPE_NTLMSSP:
3429                 sk = auth_ntlmssp_get_session_key(a->a_u.auth_ntlmssp_state);
3430                 break;
3431         case DCERPC_AUTH_TYPE_KRB5:
3432                 sk = gse_get_session_key(a->a_u.gssapi_state);
3433                 break;
3434         case DCERPC_AUTH_TYPE_NONE:
3435                 sk = data_blob_const(a->user_session_key.data,
3436                                      a->user_session_key.length);
3437                 break;
3438         default:
3439                 return NT_STATUS_NO_USER_SESSION_KEY;
3440         }
3441
3442         *session_key = data_blob_dup_talloc(mem_ctx, &sk);
3443         return NT_STATUS_OK;
3444 }