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