s3:smbd:smb2: change smbXsrv_session0 to smbXsrv_session in struct user_struct.
[Samba/gebeck_regimport.git] / source3 / rpc_server / srv_pipe.c
blob18356382ed73e419dfee6e24306af626ad05996e
1 /*
2 * Unix SMB/CIFS implementation.
3 * RPC Pipe client / server routines
4 * Almost completely rewritten by (C) Jeremy Allison 2005 - 2010
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.
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.
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/>.
20 /* this module apparently provides an implementation of DCE/RPC over a
21 * named pipe (IPC$ connection using SMBtrans). details of DCE/RPC
22 * documentation are available (in on-line form) from the X-Open group.
24 * this module should provide a level of abstraction between SMB
25 * and DCE/RPC, while minimising the amount of mallocs, unnecessary
26 * data copies, and network traffic.
30 #include "includes.h"
31 #include "system/filesys.h"
32 #include "srv_pipe_internal.h"
33 #include "../librpc/gen_ndr/ndr_schannel.h"
34 #include "../libcli/auth/schannel.h"
35 #include "../libcli/auth/spnego.h"
36 #include "dcesrv_auth_generic.h"
37 #include "rpc_server.h"
38 #include "rpc_dce.h"
39 #include "smbd/smbd.h"
40 #include "auth.h"
41 #include "ntdomain.h"
42 #include "rpc_server/srv_pipe.h"
43 #include "rpc_server/rpc_contexts.h"
44 #include "lib/param/param.h"
46 #undef DBGC_CLASS
47 #define DBGC_CLASS DBGC_RPC_SRV
49 /**
50 * Dump everything from the start of the end up of the provided data
51 * into a file, but only at debug level >= 50
52 **/
53 static void dump_pdu_region(const char *name, int v,
54 DATA_BLOB *data, size_t start, size_t end)
56 int fd, i;
57 char *fname = NULL;
58 ssize_t sz;
60 if (DEBUGLEVEL < 50) return;
62 if (start > data->length || end > data->length || start > end) return;
64 for (i = 1; i < 100; i++) {
65 if (v != -1) {
66 fname = talloc_asprintf(talloc_tos(),
67 "/tmp/%s_%d.%d.prs",
68 name, v, i);
69 } else {
70 fname = talloc_asprintf(talloc_tos(),
71 "/tmp/%s_%d.prs",
72 name, i);
74 if (!fname) {
75 return;
77 fd = open(fname, O_WRONLY|O_CREAT|O_EXCL, 0644);
78 if (fd != -1 || errno != EEXIST) break;
80 if (fd != -1) {
81 sz = write(fd, data->data + start, end - start);
82 i = close(fd);
83 if ((sz != end - start) || (i != 0) ) {
84 DEBUG(0, ("Error writing/closing %s: %ld!=%ld %d\n",
85 fname, (unsigned long)sz,
86 (unsigned long)end - start, i));
87 } else {
88 DEBUG(0,("created %s\n", fname));
91 TALLOC_FREE(fname);
94 static DATA_BLOB generic_session_key(void)
96 return data_blob_const("SystemLibraryDTC", 16);
99 /*******************************************************************
100 Generate the next PDU to be returned from the data.
101 ********************************************************************/
103 static NTSTATUS create_next_packet(TALLOC_CTX *mem_ctx,
104 struct pipe_auth_data *auth,
105 uint32_t call_id,
106 DATA_BLOB *rdata,
107 size_t data_sent_length,
108 DATA_BLOB *frag,
109 size_t *pdu_size)
111 union dcerpc_payload u;
112 uint8_t pfc_flags;
113 size_t data_left;
114 size_t data_to_send;
115 size_t frag_len;
116 size_t pad_len = 0;
117 size_t auth_len = 0;
118 NTSTATUS status;
120 ZERO_STRUCT(u.response);
122 /* Set up rpc packet pfc flags. */
123 if (data_sent_length == 0) {
124 pfc_flags = DCERPC_PFC_FLAG_FIRST;
125 } else {
126 pfc_flags = 0;
129 /* Work out how much we can fit in a single PDU. */
130 data_left = rdata->length - data_sent_length;
132 /* Ensure there really is data left to send. */
133 if (!data_left) {
134 DEBUG(0, ("No data left to send !\n"));
135 return NT_STATUS_BUFFER_TOO_SMALL;
138 status = dcerpc_guess_sizes(auth,
139 DCERPC_RESPONSE_LENGTH,
140 data_left,
141 RPC_MAX_PDU_FRAG_LEN,
142 SERVER_NDR_PADDING_SIZE,
143 &data_to_send, &frag_len,
144 &auth_len, &pad_len);
145 if (!NT_STATUS_IS_OK(status)) {
146 return status;
149 /* Set up the alloc hint. This should be the data left to send. */
150 u.response.alloc_hint = data_left;
152 /* Work out if this PDU will be the last. */
153 if (data_sent_length + data_to_send >= rdata->length) {
154 pfc_flags |= DCERPC_PFC_FLAG_LAST;
157 /* Prepare data to be NDR encoded. */
158 u.response.stub_and_verifier =
159 data_blob_const(rdata->data + data_sent_length, data_to_send);
161 /* Store the packet in the data stream. */
162 status = dcerpc_push_ncacn_packet(mem_ctx, DCERPC_PKT_RESPONSE,
163 pfc_flags, auth_len, call_id,
164 &u, frag);
165 if (!NT_STATUS_IS_OK(status)) {
166 DEBUG(0, ("Failed to marshall RPC Packet.\n"));
167 return status;
170 if (auth_len) {
171 /* Set the proper length on the pdu, including padding.
172 * Only needed if an auth trailer will be appended. */
173 dcerpc_set_frag_length(frag, frag->length
174 + pad_len
175 + DCERPC_AUTH_TRAILER_LENGTH
176 + auth_len);
179 if (auth_len) {
180 status = dcerpc_add_auth_footer(auth, pad_len, frag);
181 if (!NT_STATUS_IS_OK(status)) {
182 data_blob_free(frag);
183 return status;
187 *pdu_size = data_to_send;
188 return NT_STATUS_OK;
191 /*******************************************************************
192 Generate the next PDU to be returned from the data in p->rdata.
193 ********************************************************************/
195 bool create_next_pdu(struct pipes_struct *p)
197 size_t pdu_size = 0;
198 NTSTATUS status;
201 * If we're in the fault state, keep returning fault PDU's until
202 * the pipe gets closed. JRA.
204 if (p->fault_state) {
205 setup_fault_pdu(p, NT_STATUS(DCERPC_FAULT_OP_RNG_ERROR));
206 return true;
209 status = create_next_packet(p->mem_ctx, &p->auth,
210 p->call_id, &p->out_data.rdata,
211 p->out_data.data_sent_length,
212 &p->out_data.frag, &pdu_size);
213 if (!NT_STATUS_IS_OK(status)) {
214 DEBUG(0, ("Failed to create packet with error %s, "
215 "(auth level %u / type %u)\n",
216 nt_errstr(status),
217 (unsigned int)p->auth.auth_level,
218 (unsigned int)p->auth.auth_type));
219 return false;
222 /* Setup the counts for this PDU. */
223 p->out_data.data_sent_length += pdu_size;
224 p->out_data.current_pdu_sent = 0;
225 return true;
229 static bool pipe_init_outgoing_data(struct pipes_struct *p);
231 /*******************************************************************
232 Marshall a bind_nak pdu.
233 *******************************************************************/
235 static bool setup_bind_nak(struct pipes_struct *p, struct ncacn_packet *pkt)
237 NTSTATUS status;
238 union dcerpc_payload u;
240 /* Free any memory in the current return data buffer. */
241 pipe_init_outgoing_data(p);
244 * Initialize a bind_nak header.
247 ZERO_STRUCT(u);
249 u.bind_nak.reject_reason = 0;
252 * Marshall directly into the outgoing PDU space. We
253 * must do this as we need to set to the bind response
254 * header and are never sending more than one PDU here.
257 status = dcerpc_push_ncacn_packet(p->mem_ctx,
258 DCERPC_PKT_BIND_NAK,
259 DCERPC_PFC_FLAG_FIRST |
260 DCERPC_PFC_FLAG_LAST,
262 pkt->call_id,
264 &p->out_data.frag);
265 if (!NT_STATUS_IS_OK(status)) {
266 return False;
269 p->out_data.data_sent_length = 0;
270 p->out_data.current_pdu_sent = 0;
272 TALLOC_FREE(p->auth.auth_ctx);
273 p->auth.auth_level = DCERPC_AUTH_LEVEL_NONE;
274 p->auth.auth_type = DCERPC_AUTH_TYPE_NONE;
275 p->pipe_bound = False;
277 return True;
280 /*******************************************************************
281 Marshall a fault pdu.
282 *******************************************************************/
284 bool setup_fault_pdu(struct pipes_struct *p, NTSTATUS fault_status)
286 NTSTATUS status;
287 union dcerpc_payload u;
289 /* Free any memory in the current return data buffer. */
290 pipe_init_outgoing_data(p);
293 * Initialize a fault header.
296 ZERO_STRUCT(u);
298 u.fault.status = NT_STATUS_V(fault_status);
299 u.fault._pad = data_blob_talloc_zero(p->mem_ctx, 4);
302 * Marshall directly into the outgoing PDU space. We
303 * must do this as we need to set to the bind response
304 * header and are never sending more than one PDU here.
307 status = dcerpc_push_ncacn_packet(p->mem_ctx,
308 DCERPC_PKT_FAULT,
309 DCERPC_PFC_FLAG_FIRST |
310 DCERPC_PFC_FLAG_LAST |
311 DCERPC_PFC_FLAG_DID_NOT_EXECUTE,
313 p->call_id,
315 &p->out_data.frag);
316 if (!NT_STATUS_IS_OK(status)) {
317 return False;
320 p->out_data.data_sent_length = 0;
321 p->out_data.current_pdu_sent = 0;
323 return True;
326 /*******************************************************************
327 Ensure a bind request has the correct abstract & transfer interface.
328 Used to reject unknown binds from Win2k.
329 *******************************************************************/
331 static bool check_bind_req(struct pipes_struct *p,
332 struct ndr_syntax_id* abstract,
333 struct ndr_syntax_id* transfer,
334 uint32_t context_id)
336 struct pipe_rpc_fns *context_fns;
337 bool ok;
339 DEBUG(3,("check_bind_req for %s\n",
340 get_pipe_name_from_syntax(talloc_tos(), abstract)));
342 /* we have to check all now since win2k introduced a new UUID on the lsaprpc pipe */
343 if (rpc_srv_pipe_exists_by_id(abstract) &&
344 ndr_syntax_id_equal(transfer, &ndr_transfer_syntax_ndr)) {
345 DEBUG(3, ("check_bind_req: %s -> %s rpc service\n",
346 rpc_srv_get_pipe_cli_name(abstract),
347 rpc_srv_get_pipe_srv_name(abstract)));
348 } else {
349 return false;
352 ok = init_pipe_handles(p, abstract);
353 if (!ok) {
354 DEBUG(1, ("Failed to init pipe handles!\n"));
355 return false;
358 context_fns = talloc(p, struct pipe_rpc_fns);
359 if (context_fns == NULL) {
360 DEBUG(0,("check_bind_req: talloc() failed!\n"));
361 return false;
364 context_fns->next = context_fns->prev = NULL;
365 context_fns->n_cmds = rpc_srv_get_pipe_num_cmds(abstract);
366 context_fns->cmds = rpc_srv_get_pipe_cmds(abstract);
367 context_fns->context_id = context_id;
368 context_fns->syntax = *abstract;
370 /* add to the list of open contexts */
372 DLIST_ADD( p->contexts, context_fns );
374 return True;
378 * Is a named pipe known?
379 * @param[in] pipename Just the filename
380 * @result Do we want to serve this?
382 bool is_known_pipename(const char *pipename, struct ndr_syntax_id *syntax)
384 NTSTATUS status;
386 if (lp_disable_spoolss() && strequal(pipename, "spoolss")) {
387 DEBUG(10, ("refusing spoolss access\n"));
388 return false;
391 if (rpc_srv_get_pipe_interface_by_cli_name(pipename, syntax)) {
392 return true;
395 status = smb_probe_module("rpc", pipename);
396 if (!NT_STATUS_IS_OK(status)) {
397 DEBUG(10, ("is_known_pipename: %s unknown\n", pipename));
398 return false;
400 DEBUG(10, ("is_known_pipename: %s loaded dynamically\n", pipename));
403 * Scan the list again for the interface id
405 if (rpc_srv_get_pipe_interface_by_cli_name(pipename, syntax)) {
406 return true;
409 DEBUG(10, ("is_known_pipename: pipe %s did not register itself!\n",
410 pipename));
412 return false;
415 /*******************************************************************
416 Handle an schannel bind auth.
417 *******************************************************************/
419 static bool pipe_schannel_auth_bind(struct pipes_struct *p,
420 TALLOC_CTX *mem_ctx,
421 struct dcerpc_auth *auth_info,
422 DATA_BLOB *response)
424 struct NL_AUTH_MESSAGE neg;
425 struct NL_AUTH_MESSAGE reply;
426 bool ret;
427 NTSTATUS status;
428 struct netlogon_creds_CredentialState *creds;
429 enum ndr_err_code ndr_err;
430 struct schannel_state *schannel_auth;
431 struct loadparm_context *lp_ctx;
433 ndr_err = ndr_pull_struct_blob(
434 &auth_info->credentials, mem_ctx, &neg,
435 (ndr_pull_flags_fn_t)ndr_pull_NL_AUTH_MESSAGE);
436 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
437 DEBUG(0,("pipe_schannel_auth_bind: Could not unmarshal SCHANNEL auth neg\n"));
438 return false;
441 if (DEBUGLEVEL >= 10) {
442 NDR_PRINT_DEBUG(NL_AUTH_MESSAGE, &neg);
445 if (!(neg.Flags & NL_FLAG_OEM_NETBIOS_COMPUTER_NAME)) {
446 DEBUG(0,("pipe_schannel_auth_bind: Did not receive netbios computer name\n"));
447 return false;
450 lp_ctx = loadparm_init_s3(p, loadparm_s3_helpers());
451 if (!lp_ctx) {
452 DEBUG(0,("pipe_schannel_auth_bind: loadparm_init_s3() failed!\n"));
453 return false;
457 * The neg.oem_netbios_computer.a key here must match the remote computer name
458 * given in the DOM_CLNT_SRV.uni_comp_name used on all netlogon pipe
459 * operations that use credentials.
462 become_root();
463 status = schannel_get_creds_state(p, lp_ctx,
464 neg.oem_netbios_computer.a, &creds);
465 unbecome_root();
467 talloc_unlink(p, lp_ctx);
468 if (!NT_STATUS_IS_OK(status)) {
469 DEBUG(0, ("pipe_schannel_auth_bind: Attempt to bind using schannel without successful serverauth2\n"));
470 return False;
473 schannel_auth = talloc_zero(p, struct schannel_state);
474 if (!schannel_auth) {
475 TALLOC_FREE(creds);
476 return False;
479 schannel_auth->state = SCHANNEL_STATE_START;
480 schannel_auth->initiator = false;
481 schannel_auth->creds = creds;
484 * JRA. Should we also copy the schannel session key into the pipe session key p->session_key
485 * here ? We do that for NTLMSSP, but the session key is already set up from the vuser
486 * struct of the person who opened the pipe. I need to test this further. JRA.
488 * VL. As we are mapping this to guest set the generic key
489 * "SystemLibraryDTC" key here. It's a bit difficult to test against
490 * W2k3, as it does not allow schannel binds against SAMR and LSA
491 * anymore.
494 ret = session_info_set_session_key(p->session_info, generic_session_key());
496 if (!ret) {
497 DEBUG(0, ("session_info_set_session_key failed\n"));
498 return false;
501 /*** SCHANNEL verifier ***/
503 reply.MessageType = NL_NEGOTIATE_RESPONSE;
504 reply.Flags = 0;
505 reply.Buffer.dummy = 5; /* ??? actually I don't think
506 * this has any meaning
507 * here - gd */
509 ndr_err = ndr_push_struct_blob(response, mem_ctx, &reply,
510 (ndr_push_flags_fn_t)ndr_push_NL_AUTH_MESSAGE);
511 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
512 DEBUG(0,("Failed to marshall NL_AUTH_MESSAGE.\n"));
513 return false;
516 if (DEBUGLEVEL >= 10) {
517 NDR_PRINT_DEBUG(NL_AUTH_MESSAGE, &reply);
520 DEBUG(10,("pipe_schannel_auth_bind: schannel auth: domain [%s] myname [%s]\n",
521 neg.oem_netbios_domain.a, neg.oem_netbios_computer.a));
523 /* We're finished with this bind - no more packets. */
524 p->auth.auth_ctx = schannel_auth;
525 p->auth.auth_type = DCERPC_AUTH_TYPE_SCHANNEL;
527 p->pipe_bound = True;
529 return True;
532 /*******************************************************************
533 Handle an NTLMSSP bind auth.
534 *******************************************************************/
536 static bool pipe_auth_generic_bind(struct pipes_struct *p,
537 TALLOC_CTX *mem_ctx,
538 struct dcerpc_auth *auth_info,
539 DATA_BLOB *response)
541 struct gensec_security *gensec_security = NULL;
542 NTSTATUS status;
544 status = auth_generic_server_authtype_start(p,
545 auth_info->auth_type,
546 auth_info->auth_level,
547 &auth_info->credentials,
548 response,
549 p->remote_address,
550 &gensec_security);
551 if (!NT_STATUS_EQUAL(status, NT_STATUS_OK)) {
552 DEBUG(0, (__location__ ": auth_generic_server_authtype_start failed: %s\n",
553 nt_errstr(status)));
554 return false;
557 /* Make sure data is bound to the memctx, to be freed the caller */
558 talloc_steal(mem_ctx, response->data);
560 p->auth.auth_ctx = gensec_security;
561 p->auth.auth_type = auth_info->auth_type;
563 return true;
566 /*******************************************************************
567 Process an NTLMSSP authentication response.
568 If this function succeeds, the user has been authenticated
569 and their domain, name and calling workstation stored in
570 the pipe struct.
571 *******************************************************************/
573 static bool pipe_auth_generic_verify_final(TALLOC_CTX *mem_ctx,
574 struct gensec_security *gensec_security,
575 enum dcerpc_AuthLevel auth_level,
576 struct auth_session_info **session_info)
578 NTSTATUS status;
579 bool ret;
581 DEBUG(5, (__location__ ": checking user details\n"));
583 /* Finally - if the pipe negotiated integrity (sign) or privacy (seal)
584 ensure the underlying NTLMSSP flags are also set. If not we should
585 refuse the bind. */
587 status = auth_generic_server_check_flags(gensec_security,
588 (auth_level ==
589 DCERPC_AUTH_LEVEL_INTEGRITY),
590 (auth_level ==
591 DCERPC_AUTH_LEVEL_PRIVACY));
592 if (!NT_STATUS_IS_OK(status)) {
593 DEBUG(0, (__location__ ": Client failed to negotatie proper "
594 "security for rpc connection\n"));
595 return false;
598 TALLOC_FREE(*session_info);
600 status = auth_generic_server_get_user_info(gensec_security,
601 mem_ctx, session_info);
602 if (!NT_STATUS_IS_OK(status)) {
603 DEBUG(0, (__location__ ": failed to obtain the server info "
604 "for authenticated user: %s\n", nt_errstr(status)));
605 return false;
608 if ((*session_info)->security_token == NULL) {
609 DEBUG(1, ("Auth module failed to provide nt_user_token\n"));
610 return false;
614 * We're an authenticated bind over smb, so the session key needs to
615 * be set to "SystemLibraryDTC". Weird, but this is what Windows
616 * does. See the RPC-SAMBA3SESSIONKEY.
619 ret = session_info_set_session_key((*session_info), generic_session_key());
620 if (!ret) {
621 DEBUG(0, ("Failed to set session key!\n"));
622 return false;
625 return true;
628 static NTSTATUS pipe_auth_verify_final(struct pipes_struct *p)
630 struct gensec_security *gensec_security;
632 switch (p->auth.auth_type) {
633 case DCERPC_AUTH_TYPE_NTLMSSP:
634 case DCERPC_AUTH_TYPE_KRB5:
635 case DCERPC_AUTH_TYPE_SPNEGO:
636 gensec_security = talloc_get_type_abort(p->auth.auth_ctx,
637 struct gensec_security);
638 if (!pipe_auth_generic_verify_final(p, gensec_security,
639 p->auth.auth_level,
640 &p->session_info)) {
641 return NT_STATUS_ACCESS_DENIED;
643 break;
644 default:
645 DEBUG(0, (__location__ ": incorrect auth type (%u).\n",
646 (unsigned int)p->auth.auth_type));
647 return NT_STATUS_ACCESS_DENIED;
650 p->pipe_bound = true;
652 return NT_STATUS_OK;
655 /*******************************************************************
656 Respond to a pipe bind request.
657 *******************************************************************/
659 static bool api_pipe_bind_req(struct pipes_struct *p,
660 struct ncacn_packet *pkt)
662 struct dcerpc_auth auth_info;
663 uint16 assoc_gid;
664 unsigned int auth_type = DCERPC_AUTH_TYPE_NONE;
665 NTSTATUS status;
666 struct ndr_syntax_id id;
667 union dcerpc_payload u;
668 struct dcerpc_ack_ctx bind_ack_ctx;
669 DATA_BLOB auth_resp = data_blob_null;
670 DATA_BLOB auth_blob = data_blob_null;
672 /* No rebinds on a bound pipe - use alter context. */
673 if (p->pipe_bound) {
674 DEBUG(2,("Rejecting bind request on bound rpc connection\n"));
675 return setup_bind_nak(p, pkt);
678 if (pkt->u.bind.num_contexts == 0) {
679 DEBUG(0, ("api_pipe_bind_req: no rpc contexts around\n"));
680 goto err_exit;
684 * Try and find the correct pipe name to ensure
685 * that this is a pipe name we support.
687 id = pkt->u.bind.ctx_list[0].abstract_syntax;
688 if (rpc_srv_pipe_exists_by_id(&id)) {
689 DEBUG(3, ("api_pipe_bind_req: %s -> %s rpc service\n",
690 rpc_srv_get_pipe_cli_name(&id),
691 rpc_srv_get_pipe_srv_name(&id)));
692 } else {
693 status = smb_probe_module(
694 "rpc", get_pipe_name_from_syntax(
695 talloc_tos(),
696 &id));
698 if (NT_STATUS_IS_ERR(status)) {
699 DEBUG(3,("api_pipe_bind_req: Unknown rpc service name "
700 "%s in bind request.\n",
701 get_pipe_name_from_syntax(talloc_tos(), &id)));
703 return setup_bind_nak(p, pkt);
706 if (rpc_srv_get_pipe_interface_by_cli_name(
707 get_pipe_name_from_syntax(talloc_tos(),
708 &id),
709 &id)) {
710 DEBUG(3, ("api_pipe_bind_req: %s -> %s rpc service\n",
711 rpc_srv_get_pipe_cli_name(&id),
712 rpc_srv_get_pipe_srv_name(&id)));
713 } else {
714 DEBUG(0, ("module %s doesn't provide functions for "
715 "pipe %s!\n",
716 get_pipe_name_from_syntax(talloc_tos(), &id),
717 get_pipe_name_from_syntax(talloc_tos(), &id)));
718 return setup_bind_nak(p, pkt);
722 DEBUG(5,("api_pipe_bind_req: make response. %d\n", __LINE__));
724 if (pkt->u.bind.assoc_group_id != 0) {
725 assoc_gid = pkt->u.bind.assoc_group_id;
726 } else {
727 assoc_gid = 0x53f0;
731 * Create the bind response struct.
734 /* If the requested abstract synt uuid doesn't match our client pipe,
735 reject the bind_ack & set the transfer interface synt to all 0's,
736 ver 0 (observed when NT5 attempts to bind to abstract interfaces
737 unknown to NT4)
738 Needed when adding entries to a DACL from NT5 - SK */
740 if (check_bind_req(p,
741 &pkt->u.bind.ctx_list[0].abstract_syntax,
742 &pkt->u.bind.ctx_list[0].transfer_syntaxes[0],
743 pkt->u.bind.ctx_list[0].context_id)) {
745 bind_ack_ctx.result = 0;
746 bind_ack_ctx.reason = 0;
747 bind_ack_ctx.syntax = pkt->u.bind.ctx_list[0].transfer_syntaxes[0];
748 } else {
749 p->pipe_bound = False;
750 /* Rejection reason: abstract syntax not supported */
751 bind_ack_ctx.result = DCERPC_BIND_PROVIDER_REJECT;
752 bind_ack_ctx.reason = DCERPC_BIND_REASON_ASYNTAX;
753 bind_ack_ctx.syntax = ndr_syntax_id_null;
757 * Check if this is an authenticated bind request.
759 if (pkt->auth_length) {
760 /* Quick length check. Won't catch a bad auth footer,
761 * prevents overrun. */
763 if (pkt->frag_length < RPC_HEADER_LEN +
764 DCERPC_AUTH_TRAILER_LENGTH +
765 pkt->auth_length) {
766 DEBUG(0,("api_pipe_bind_req: auth_len (%u) "
767 "too long for fragment %u.\n",
768 (unsigned int)pkt->auth_length,
769 (unsigned int)pkt->frag_length));
770 goto err_exit;
774 * Decode the authentication verifier.
776 status = dcerpc_pull_dcerpc_auth(pkt,
777 &pkt->u.bind.auth_info,
778 &auth_info, p->endian);
779 if (!NT_STATUS_IS_OK(status)) {
780 DEBUG(0, ("Unable to unmarshall dcerpc_auth.\n"));
781 goto err_exit;
784 auth_type = auth_info.auth_type;
786 /* Work out if we have to sign or seal etc. */
787 switch (auth_info.auth_level) {
788 case DCERPC_AUTH_LEVEL_INTEGRITY:
789 p->auth.auth_level = DCERPC_AUTH_LEVEL_INTEGRITY;
790 break;
791 case DCERPC_AUTH_LEVEL_PRIVACY:
792 p->auth.auth_level = DCERPC_AUTH_LEVEL_PRIVACY;
793 break;
794 case DCERPC_AUTH_LEVEL_CONNECT:
795 p->auth.auth_level = DCERPC_AUTH_LEVEL_CONNECT;
796 break;
797 default:
798 DEBUG(0, ("Unexpected auth level (%u).\n",
799 (unsigned int)auth_info.auth_level ));
800 goto err_exit;
803 switch (auth_type) {
804 case DCERPC_AUTH_TYPE_NTLMSSP:
805 if (!pipe_auth_generic_bind(p, pkt,
806 &auth_info, &auth_resp)) {
807 goto err_exit;
809 assoc_gid = 0x7a77;
810 break;
812 case DCERPC_AUTH_TYPE_SCHANNEL:
813 if (!pipe_schannel_auth_bind(p, pkt,
814 &auth_info, &auth_resp)) {
815 goto err_exit;
817 break;
819 case DCERPC_AUTH_TYPE_SPNEGO:
820 case DCERPC_AUTH_TYPE_KRB5:
821 if (!pipe_auth_generic_bind(p, pkt,
822 &auth_info, &auth_resp)) {
823 goto err_exit;
825 break;
827 case DCERPC_AUTH_TYPE_NCALRPC_AS_SYSTEM:
828 if (p->transport == NCALRPC && p->ncalrpc_as_system) {
829 TALLOC_FREE(p->session_info);
831 status = make_session_info_system(p,
832 &p->session_info);
833 if (!NT_STATUS_IS_OK(status)) {
834 goto err_exit;
837 auth_resp = data_blob_talloc(pkt,
838 "NCALRPC_AUTH_OK",
839 15);
841 p->auth.auth_type = DCERPC_AUTH_TYPE_NCALRPC_AS_SYSTEM;
842 p->pipe_bound = true;
843 } else {
844 goto err_exit;
846 break;
848 case DCERPC_AUTH_TYPE_NONE:
849 break;
851 default:
852 DEBUG(0, ("Unknown auth type %x requested.\n", auth_type));
853 goto err_exit;
857 if (auth_type == DCERPC_AUTH_TYPE_NONE) {
858 /* Unauthenticated bind request. */
859 /* We're finished - no more packets. */
860 p->auth.auth_type = DCERPC_AUTH_TYPE_NONE;
861 /* We must set the pipe auth_level here also. */
862 p->auth.auth_level = DCERPC_AUTH_LEVEL_NONE;
863 p->pipe_bound = True;
864 /* The session key was initialized from the SMB
865 * session in make_internal_rpc_pipe_p */
868 ZERO_STRUCT(u.bind_ack);
869 u.bind_ack.max_xmit_frag = RPC_MAX_PDU_FRAG_LEN;
870 u.bind_ack.max_recv_frag = RPC_MAX_PDU_FRAG_LEN;
871 u.bind_ack.assoc_group_id = assoc_gid;
873 /* name has to be \PIPE\xxxxx */
874 u.bind_ack.secondary_address =
875 talloc_asprintf(pkt, "\\PIPE\\%s",
876 rpc_srv_get_pipe_srv_name(&id));
877 if (!u.bind_ack.secondary_address) {
878 DEBUG(0, ("Out of memory!\n"));
879 goto err_exit;
881 u.bind_ack.secondary_address_size =
882 strlen(u.bind_ack.secondary_address) + 1;
884 u.bind_ack.num_results = 1;
885 u.bind_ack.ctx_list = &bind_ack_ctx;
887 /* NOTE: We leave the auth_info empty so we can calculate the padding
888 * later and then append the auth_info --simo */
891 * Marshall directly into the outgoing PDU space. We
892 * must do this as we need to set to the bind response
893 * header and are never sending more than one PDU here.
896 status = dcerpc_push_ncacn_packet(p->mem_ctx,
897 DCERPC_PKT_BIND_ACK,
898 DCERPC_PFC_FLAG_FIRST |
899 DCERPC_PFC_FLAG_LAST,
900 auth_resp.length,
901 pkt->call_id,
903 &p->out_data.frag);
904 if (!NT_STATUS_IS_OK(status)) {
905 DEBUG(0, ("Failed to marshall bind_ack packet. (%s)\n",
906 nt_errstr(status)));
909 if (auth_resp.length) {
911 status = dcerpc_push_dcerpc_auth(pkt,
912 auth_type,
913 auth_info.auth_level,
915 1, /* auth_context_id */
916 &auth_resp,
917 &auth_blob);
918 if (!NT_STATUS_IS_OK(status)) {
919 DEBUG(0, ("Marshalling of dcerpc_auth failed.\n"));
920 goto err_exit;
924 /* Now that we have the auth len store it into the right place in
925 * the dcerpc header */
926 dcerpc_set_frag_length(&p->out_data.frag,
927 p->out_data.frag.length + auth_blob.length);
929 if (auth_blob.length) {
931 if (!data_blob_append(p->mem_ctx, &p->out_data.frag,
932 auth_blob.data, auth_blob.length)) {
933 DEBUG(0, ("Append of auth info failed.\n"));
934 goto err_exit;
939 * Setup the lengths for the initial reply.
942 p->out_data.data_sent_length = 0;
943 p->out_data.current_pdu_sent = 0;
945 TALLOC_FREE(auth_blob.data);
946 return True;
948 err_exit:
950 data_blob_free(&p->out_data.frag);
951 TALLOC_FREE(auth_blob.data);
952 return setup_bind_nak(p, pkt);
955 /*******************************************************************
956 This is the "stage3" response after a bind request and reply.
957 *******************************************************************/
959 bool api_pipe_bind_auth3(struct pipes_struct *p, struct ncacn_packet *pkt)
961 struct dcerpc_auth auth_info;
962 DATA_BLOB response = data_blob_null;
963 struct gensec_security *gensec_security;
964 NTSTATUS status;
966 DEBUG(5, ("api_pipe_bind_auth3: decode request. %d\n", __LINE__));
968 if (pkt->auth_length == 0) {
969 DEBUG(0, ("No auth field sent for bind request!\n"));
970 goto err;
973 /* Ensure there's enough data for an authenticated request. */
974 if (pkt->frag_length < RPC_HEADER_LEN
975 + DCERPC_AUTH_TRAILER_LENGTH
976 + pkt->auth_length) {
977 DEBUG(0,("api_pipe_ntlmssp_auth_process: auth_len "
978 "%u is too large.\n",
979 (unsigned int)pkt->auth_length));
980 goto err;
984 * Decode the authentication verifier response.
987 status = dcerpc_pull_dcerpc_auth(pkt,
988 &pkt->u.auth3.auth_info,
989 &auth_info, p->endian);
990 if (!NT_STATUS_IS_OK(status)) {
991 DEBUG(0, ("Failed to unmarshall dcerpc_auth.\n"));
992 goto err;
995 /* We must NEVER look at auth_info->auth_pad_len here,
996 * as old Samba client code gets it wrong and sends it
997 * as zero. JRA.
1000 if (auth_info.auth_type != p->auth.auth_type) {
1001 DEBUG(0, ("Auth type mismatch! Client sent %d, "
1002 "but auth was started as type %d!\n",
1003 auth_info.auth_type, p->auth.auth_type));
1004 goto err;
1007 switch (auth_info.auth_type) {
1008 case DCERPC_AUTH_TYPE_NTLMSSP:
1009 case DCERPC_AUTH_TYPE_KRB5:
1010 case DCERPC_AUTH_TYPE_SPNEGO:
1011 gensec_security = talloc_get_type_abort(p->auth.auth_ctx,
1012 struct gensec_security);
1013 status = auth_generic_server_step(gensec_security,
1014 pkt, &auth_info.credentials,
1015 &response);
1016 break;
1017 default:
1018 DEBUG(0, (__location__ ": incorrect auth type (%u).\n",
1019 (unsigned int)auth_info.auth_type));
1020 return false;
1023 if (NT_STATUS_EQUAL(status,
1024 NT_STATUS_MORE_PROCESSING_REQUIRED) ||
1025 response.length) {
1026 DEBUG(0, (__location__ ": This was supposed to be the final "
1027 "leg, but crypto machinery claims a response is "
1028 "needed, aborting auth!\n"));
1029 data_blob_free(&response);
1030 goto err;
1032 if (!NT_STATUS_IS_OK(status)) {
1033 DEBUG(0, ("Auth failed (%s)\n", nt_errstr(status)));
1034 goto err;
1037 /* Now verify auth was indeed successful and extract server info */
1038 status = pipe_auth_verify_final(p);
1039 if (!NT_STATUS_IS_OK(status)) {
1040 DEBUG(0, ("Auth Verify failed (%s)\n", nt_errstr(status)));
1041 goto err;
1044 return true;
1046 err:
1048 TALLOC_FREE(p->auth.auth_ctx);
1049 return false;
1052 /****************************************************************************
1053 Deal with an alter context call. Can be third part of 3 leg auth request for
1054 SPNEGO calls.
1055 ****************************************************************************/
1057 static bool api_pipe_alter_context(struct pipes_struct *p,
1058 struct ncacn_packet *pkt)
1060 struct dcerpc_auth auth_info;
1061 uint16 assoc_gid;
1062 NTSTATUS status;
1063 union dcerpc_payload u;
1064 struct dcerpc_ack_ctx bind_ack_ctx;
1065 DATA_BLOB auth_resp = data_blob_null;
1066 DATA_BLOB auth_blob = data_blob_null;
1067 int pad_len = 0;
1068 struct gensec_security *gensec_security;
1070 DEBUG(5,("api_pipe_alter_context: make response. %d\n", __LINE__));
1072 if (pkt->u.bind.assoc_group_id != 0) {
1073 assoc_gid = pkt->u.bind.assoc_group_id;
1074 } else {
1075 assoc_gid = 0x53f0;
1079 * Create the bind response struct.
1082 /* If the requested abstract synt uuid doesn't match our client pipe,
1083 reject the bind_ack & set the transfer interface synt to all 0's,
1084 ver 0 (observed when NT5 attempts to bind to abstract interfaces
1085 unknown to NT4)
1086 Needed when adding entries to a DACL from NT5 - SK */
1088 if (check_bind_req(p,
1089 &pkt->u.bind.ctx_list[0].abstract_syntax,
1090 &pkt->u.bind.ctx_list[0].transfer_syntaxes[0],
1091 pkt->u.bind.ctx_list[0].context_id)) {
1093 bind_ack_ctx.result = 0;
1094 bind_ack_ctx.reason = 0;
1095 bind_ack_ctx.syntax = pkt->u.bind.ctx_list[0].transfer_syntaxes[0];
1096 } else {
1097 p->pipe_bound = False;
1098 /* Rejection reason: abstract syntax not supported */
1099 bind_ack_ctx.result = DCERPC_BIND_PROVIDER_REJECT;
1100 bind_ack_ctx.reason = DCERPC_BIND_REASON_ASYNTAX;
1101 bind_ack_ctx.syntax = ndr_syntax_id_null;
1105 * Check if this is an authenticated alter context request.
1107 if (pkt->auth_length) {
1108 /* Quick length check. Won't catch a bad auth footer,
1109 * prevents overrun. */
1111 if (pkt->frag_length < RPC_HEADER_LEN +
1112 DCERPC_AUTH_TRAILER_LENGTH +
1113 pkt->auth_length) {
1114 DEBUG(0,("api_pipe_alter_context: auth_len (%u) "
1115 "too long for fragment %u.\n",
1116 (unsigned int)pkt->auth_length,
1117 (unsigned int)pkt->frag_length ));
1118 goto err_exit;
1121 status = dcerpc_pull_dcerpc_auth(pkt,
1122 &pkt->u.bind.auth_info,
1123 &auth_info, p->endian);
1124 if (!NT_STATUS_IS_OK(status)) {
1125 DEBUG(0, ("Unable to unmarshall dcerpc_auth.\n"));
1126 goto err_exit;
1129 /* We can only finish if the pipe is unbound for now */
1130 if (p->pipe_bound) {
1131 DEBUG(0, (__location__ ": Pipe already bound, "
1132 "Altering Context not yet supported!\n"));
1133 goto err_exit;
1136 if (auth_info.auth_type != p->auth.auth_type) {
1137 DEBUG(0, ("Auth type mismatch! Client sent %d, "
1138 "but auth was started as type %d!\n",
1139 auth_info.auth_type, p->auth.auth_type));
1140 goto err_exit;
1144 switch (auth_info.auth_type) {
1145 case DCERPC_AUTH_TYPE_SPNEGO:
1146 case DCERPC_AUTH_TYPE_KRB5:
1147 case DCERPC_AUTH_TYPE_NTLMSSP:
1148 gensec_security = talloc_get_type_abort(p->auth.auth_ctx,
1149 struct gensec_security);
1150 status = auth_generic_server_step(gensec_security,
1151 pkt,
1152 &auth_info.credentials,
1153 &auth_resp);
1154 break;
1156 default:
1157 DEBUG(3, (__location__ ": Usupported auth type (%d) "
1158 "in alter-context call\n",
1159 auth_info.auth_type));
1160 goto err_exit;
1163 if (NT_STATUS_IS_OK(status)) {
1164 /* third leg of auth, verify auth info */
1165 status = pipe_auth_verify_final(p);
1166 if (!NT_STATUS_IS_OK(status)) {
1167 DEBUG(0, ("Auth Verify failed (%s)\n",
1168 nt_errstr(status)));
1169 goto err_exit;
1171 } else if (NT_STATUS_EQUAL(status,
1172 NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1173 DEBUG(10, ("More auth legs required.\n"));
1174 } else {
1175 DEBUG(0, ("Auth step returned an error (%s)\n",
1176 nt_errstr(status)));
1177 goto err_exit;
1181 ZERO_STRUCT(u.alter_resp);
1182 u.alter_resp.max_xmit_frag = RPC_MAX_PDU_FRAG_LEN;
1183 u.alter_resp.max_recv_frag = RPC_MAX_PDU_FRAG_LEN;
1184 u.alter_resp.assoc_group_id = assoc_gid;
1186 /* secondary address CAN be NULL
1187 * as the specs say it's ignored.
1188 * It MUST be NULL to have the spoolss working.
1190 u.alter_resp.secondary_address = "";
1191 u.alter_resp.secondary_address_size = 1;
1193 u.alter_resp.num_results = 1;
1194 u.alter_resp.ctx_list = &bind_ack_ctx;
1196 /* NOTE: We leave the auth_info empty so we can calculate the padding
1197 * later and then append the auth_info --simo */
1200 * Marshall directly into the outgoing PDU space. We
1201 * must do this as we need to set to the bind response
1202 * header and are never sending more than one PDU here.
1205 status = dcerpc_push_ncacn_packet(p->mem_ctx,
1206 DCERPC_PKT_ALTER_RESP,
1207 DCERPC_PFC_FLAG_FIRST |
1208 DCERPC_PFC_FLAG_LAST,
1209 auth_resp.length,
1210 pkt->call_id,
1212 &p->out_data.frag);
1213 if (!NT_STATUS_IS_OK(status)) {
1214 DEBUG(0, ("Failed to marshall bind_ack packet. (%s)\n",
1215 nt_errstr(status)));
1218 if (auth_resp.length) {
1220 /* Work out any padding needed before the auth footer. */
1221 pad_len = p->out_data.frag.length % SERVER_NDR_PADDING_SIZE;
1222 if (pad_len) {
1223 pad_len = SERVER_NDR_PADDING_SIZE - pad_len;
1224 DEBUG(10, ("auth pad_len = %u\n",
1225 (unsigned int)pad_len));
1228 status = dcerpc_push_dcerpc_auth(pkt,
1229 auth_info.auth_type,
1230 auth_info.auth_level,
1231 pad_len,
1232 1, /* auth_context_id */
1233 &auth_resp,
1234 &auth_blob);
1235 if (!NT_STATUS_IS_OK(status)) {
1236 DEBUG(0, ("Marshalling of dcerpc_auth failed.\n"));
1237 goto err_exit;
1241 /* Now that we have the auth len store it into the right place in
1242 * the dcerpc header */
1243 dcerpc_set_frag_length(&p->out_data.frag,
1244 p->out_data.frag.length +
1245 pad_len + auth_blob.length);
1247 if (auth_resp.length) {
1248 if (pad_len) {
1249 char pad[SERVER_NDR_PADDING_SIZE];
1250 memset(pad, '\0', SERVER_NDR_PADDING_SIZE);
1251 if (!data_blob_append(p->mem_ctx,
1252 &p->out_data.frag,
1253 pad, pad_len)) {
1254 DEBUG(0, ("api_pipe_bind_req: failed to add "
1255 "%u bytes of pad data.\n",
1256 (unsigned int)pad_len));
1257 goto err_exit;
1261 if (!data_blob_append(p->mem_ctx, &p->out_data.frag,
1262 auth_blob.data, auth_blob.length)) {
1263 DEBUG(0, ("Append of auth info failed.\n"));
1264 goto err_exit;
1269 * Setup the lengths for the initial reply.
1272 p->out_data.data_sent_length = 0;
1273 p->out_data.current_pdu_sent = 0;
1275 TALLOC_FREE(auth_blob.data);
1276 return True;
1278 err_exit:
1280 data_blob_free(&p->out_data.frag);
1281 TALLOC_FREE(auth_blob.data);
1282 return setup_bind_nak(p, pkt);
1285 static bool api_rpcTNP(struct pipes_struct *p, struct ncacn_packet *pkt,
1286 const struct api_struct *api_rpc_cmds, int n_cmds,
1287 const struct ndr_syntax_id *syntax);
1289 /****************************************************************************
1290 Find the correct RPC function to call for this request.
1291 If the pipe is authenticated then become the correct UNIX user
1292 before doing the call.
1293 ****************************************************************************/
1295 static bool api_pipe_request(struct pipes_struct *p,
1296 struct ncacn_packet *pkt)
1298 bool ret = False;
1299 struct pipe_rpc_fns *pipe_fns;
1301 if (!p->pipe_bound) {
1302 DEBUG(1, ("Pipe not bound!\n"));
1303 data_blob_free(&p->out_data.rdata);
1304 return false;
1307 if (!become_authenticated_pipe_user(p->session_info)) {
1308 DEBUG(1, ("Failed to become pipe user!\n"));
1309 data_blob_free(&p->out_data.rdata);
1310 return false;
1313 /* get the set of RPC functions for this context */
1315 pipe_fns = find_pipe_fns_by_context(p->contexts,
1316 pkt->u.request.context_id);
1318 if ( pipe_fns ) {
1319 TALLOC_CTX *frame = talloc_stackframe();
1321 DEBUG(5, ("Requested %s rpc service\n",
1322 get_pipe_name_from_syntax(talloc_tos(), &pipe_fns->syntax)));
1324 ret = api_rpcTNP(p, pkt, pipe_fns->cmds, pipe_fns->n_cmds,
1325 &pipe_fns->syntax);
1327 TALLOC_FREE(frame);
1329 else {
1330 DEBUG(0, ("No rpc function table associated with context "
1331 "[%d]\n",
1332 pkt->u.request.context_id));
1335 unbecome_authenticated_pipe_user();
1337 return ret;
1340 /*******************************************************************
1341 Calls the underlying RPC function for a named pipe.
1342 ********************************************************************/
1344 static bool api_rpcTNP(struct pipes_struct *p, struct ncacn_packet *pkt,
1345 const struct api_struct *api_rpc_cmds, int n_cmds,
1346 const struct ndr_syntax_id *syntax)
1348 int fn_num;
1349 uint32_t offset1;
1351 /* interpret the command */
1352 DEBUG(4,("api_rpcTNP: %s op 0x%x - ",
1353 get_pipe_name_from_syntax(talloc_tos(), syntax),
1354 pkt->u.request.opnum));
1356 if (DEBUGLEVEL >= 50) {
1357 fstring name;
1358 slprintf(name, sizeof(name)-1, "in_%s",
1359 get_pipe_name_from_syntax(talloc_tos(), syntax));
1360 dump_pdu_region(name, pkt->u.request.opnum,
1361 &p->in_data.data, 0,
1362 p->in_data.data.length);
1365 for (fn_num = 0; fn_num < n_cmds; fn_num++) {
1366 if (api_rpc_cmds[fn_num].opnum == pkt->u.request.opnum &&
1367 api_rpc_cmds[fn_num].fn != NULL) {
1368 DEBUG(3, ("api_rpcTNP: rpc command: %s\n",
1369 api_rpc_cmds[fn_num].name));
1370 break;
1374 if (fn_num == n_cmds) {
1376 * For an unknown RPC just return a fault PDU but
1377 * return True to allow RPC's on the pipe to continue
1378 * and not put the pipe into fault state. JRA.
1380 DEBUG(4, ("unknown\n"));
1381 setup_fault_pdu(p, NT_STATUS(DCERPC_FAULT_OP_RNG_ERROR));
1382 return True;
1385 offset1 = p->out_data.rdata.length;
1387 DEBUG(6, ("api_rpc_cmds[%d].fn == %p\n",
1388 fn_num, api_rpc_cmds[fn_num].fn));
1389 /* do the actual command */
1390 if(!api_rpc_cmds[fn_num].fn(p)) {
1391 DEBUG(0,("api_rpcTNP: %s: %s failed.\n",
1392 get_pipe_name_from_syntax(talloc_tos(), syntax),
1393 api_rpc_cmds[fn_num].name));
1394 data_blob_free(&p->out_data.rdata);
1395 return False;
1398 if (p->bad_handle_fault_state) {
1399 DEBUG(4,("api_rpcTNP: bad handle fault return.\n"));
1400 p->bad_handle_fault_state = False;
1401 setup_fault_pdu(p, NT_STATUS(DCERPC_FAULT_CONTEXT_MISMATCH));
1402 return True;
1405 if (p->rng_fault_state) {
1406 DEBUG(4, ("api_rpcTNP: rng fault return\n"));
1407 p->rng_fault_state = False;
1408 setup_fault_pdu(p, NT_STATUS(DCERPC_FAULT_OP_RNG_ERROR));
1409 return True;
1412 if (DEBUGLEVEL >= 50) {
1413 fstring name;
1414 slprintf(name, sizeof(name)-1, "out_%s",
1415 get_pipe_name_from_syntax(talloc_tos(), syntax));
1416 dump_pdu_region(name, pkt->u.request.opnum,
1417 &p->out_data.rdata, offset1,
1418 p->out_data.rdata.length);
1421 DEBUG(5,("api_rpcTNP: called %s successfully\n",
1422 get_pipe_name_from_syntax(talloc_tos(), syntax)));
1424 /* Check for buffer underflow in rpc parsing */
1425 if ((DEBUGLEVEL >= 10) &&
1426 (pkt->frag_length < p->in_data.data.length)) {
1427 DEBUG(10, ("api_rpcTNP: rpc input buffer underflow (parse error?)\n"));
1428 dump_data(10, p->in_data.data.data + pkt->frag_length,
1429 p->in_data.data.length - pkt->frag_length);
1432 return True;
1435 /****************************************************************************
1436 Initialise an outgoing packet.
1437 ****************************************************************************/
1439 static bool pipe_init_outgoing_data(struct pipes_struct *p)
1441 output_data *o_data = &p->out_data;
1443 /* Reset the offset counters. */
1444 o_data->data_sent_length = 0;
1445 o_data->current_pdu_sent = 0;
1447 data_blob_free(&o_data->frag);
1449 /* Free any memory in the current return data buffer. */
1450 data_blob_free(&o_data->rdata);
1452 return True;
1455 /****************************************************************************
1456 Sets the fault state on incoming packets.
1457 ****************************************************************************/
1459 void set_incoming_fault(struct pipes_struct *p)
1461 data_blob_free(&p->in_data.data);
1462 p->in_data.pdu_needed_len = 0;
1463 p->in_data.pdu.length = 0;
1464 p->fault_state = True;
1466 DEBUG(10, ("Setting fault state\n"));
1469 static NTSTATUS dcesrv_auth_request(struct pipe_auth_data *auth,
1470 struct ncacn_packet *pkt,
1471 DATA_BLOB *raw_pkt)
1473 NTSTATUS status;
1474 size_t hdr_size = DCERPC_REQUEST_LENGTH;
1475 size_t pad_len;
1477 DEBUG(10, ("Checking request auth.\n"));
1479 if (pkt->pfc_flags & DCERPC_PFC_FLAG_OBJECT_UUID) {
1480 hdr_size += 16;
1483 /* in case of sealing this function will unseal the data in place */
1484 status = dcerpc_check_auth(auth, pkt,
1485 &pkt->u.request.stub_and_verifier,
1486 hdr_size, raw_pkt,
1487 &pad_len);
1488 if (!NT_STATUS_IS_OK(status)) {
1489 return status;
1493 /* remove padding and auth trailer,
1494 * this way the caller will get just the data */
1495 if (pkt->auth_length) {
1496 size_t trail_len = pad_len
1497 + DCERPC_AUTH_TRAILER_LENGTH
1498 + pkt->auth_length;
1499 if (pkt->u.request.stub_and_verifier.length < trail_len) {
1500 return NT_STATUS_INFO_LENGTH_MISMATCH;
1502 pkt->u.request.stub_and_verifier.length -= trail_len;
1505 return NT_STATUS_OK;
1508 /****************************************************************************
1509 Processes a request pdu. This will do auth processing if needed, and
1510 appends the data into the complete stream if the LAST flag is not set.
1511 ****************************************************************************/
1513 static bool process_request_pdu(struct pipes_struct *p, struct ncacn_packet *pkt)
1515 NTSTATUS status;
1516 DATA_BLOB data;
1518 if (!p->pipe_bound) {
1519 DEBUG(0,("process_request_pdu: rpc request with no bind.\n"));
1520 set_incoming_fault(p);
1521 return False;
1524 /* Store the opnum */
1525 p->opnum = pkt->u.request.opnum;
1527 status = dcesrv_auth_request(&p->auth, pkt, &p->in_data.pdu);
1528 if (!NT_STATUS_IS_OK(status)) {
1529 DEBUG(0, ("Failed to check packet auth. (%s)\n",
1530 nt_errstr(status)));
1531 set_incoming_fault(p);
1532 return false;
1535 data = pkt->u.request.stub_and_verifier;
1538 * Check the data length doesn't go over the 15Mb limit.
1539 * increased after observing a bug in the Windows NT 4.0 SP6a
1540 * spoolsv.exe when the response to a GETPRINTERDRIVER2 RPC
1541 * will not fit in the initial buffer of size 0x1068 --jerry 22/01/2002
1544 if (p->in_data.data.length + data.length > MAX_RPC_DATA_SIZE) {
1545 DEBUG(0, ("process_request_pdu: "
1546 "rpc data buffer too large (%u) + (%u)\n",
1547 (unsigned int)p->in_data.data.length,
1548 (unsigned int)data.length));
1549 set_incoming_fault(p);
1550 return False;
1554 * Append the data portion into the buffer and return.
1557 if (data.length) {
1558 if (!data_blob_append(p->mem_ctx, &p->in_data.data,
1559 data.data, data.length)) {
1560 DEBUG(0, ("Unable to append data size %u "
1561 "to parse buffer of size %u.\n",
1562 (unsigned int)data.length,
1563 (unsigned int)p->in_data.data.length));
1564 set_incoming_fault(p);
1565 return False;
1569 if (pkt->pfc_flags & DCERPC_PFC_FLAG_LAST) {
1570 bool ret = False;
1572 * Ok - we finally have a complete RPC stream.
1573 * Call the rpc command to process it.
1577 * Process the complete data stream here.
1579 if (pipe_init_outgoing_data(p)) {
1580 ret = api_pipe_request(p, pkt);
1583 return ret;
1586 return True;
1589 /****************************************************************************
1590 Processes a finished PDU stored in p->in_data.pdu.
1591 ****************************************************************************/
1593 void process_complete_pdu(struct pipes_struct *p)
1595 struct ncacn_packet *pkt = NULL;
1596 NTSTATUS status;
1597 bool reply = False;
1599 if(p->fault_state) {
1600 DEBUG(10,("RPC connection in fault state.\n"));
1601 goto done;
1604 pkt = talloc(p->mem_ctx, struct ncacn_packet);
1605 if (!pkt) {
1606 DEBUG(0, ("Out of memory!\n"));
1607 goto done;
1611 * Ensure we're using the corrent endianness for both the
1612 * RPC header flags and the raw data we will be reading from.
1614 if (dcerpc_get_endian_flag(&p->in_data.pdu) & DCERPC_DREP_LE) {
1615 p->endian = RPC_LITTLE_ENDIAN;
1616 } else {
1617 p->endian = RPC_BIG_ENDIAN;
1619 DEBUG(10, ("PDU is in %s Endian format!\n", p->endian?"Big":"Little"));
1621 status = dcerpc_pull_ncacn_packet(pkt, &p->in_data.pdu,
1622 pkt, p->endian);
1623 if (!NT_STATUS_IS_OK(status)) {
1624 DEBUG(0, ("Failed to unmarshal rpc packet: %s!\n",
1625 nt_errstr(status)));
1626 goto done;
1629 /* Store the call_id */
1630 p->call_id = pkt->call_id;
1632 DEBUG(10, ("Processing packet type %u\n", (unsigned int)pkt->ptype));
1634 switch (pkt->ptype) {
1635 case DCERPC_PKT_REQUEST:
1636 reply = process_request_pdu(p, pkt);
1637 break;
1639 case DCERPC_PKT_PING: /* CL request - ignore... */
1640 DEBUG(0, ("Error - Connectionless packet type %u received\n",
1641 (unsigned int)pkt->ptype));
1642 break;
1644 case DCERPC_PKT_RESPONSE: /* No responses here. */
1645 DEBUG(0, ("Error - DCERPC_PKT_RESPONSE received from client"));
1646 break;
1648 case DCERPC_PKT_FAULT:
1649 case DCERPC_PKT_WORKING:
1650 /* CL request - reply to a ping when a call in process. */
1651 case DCERPC_PKT_NOCALL:
1652 /* CL - server reply to a ping call. */
1653 case DCERPC_PKT_REJECT:
1654 case DCERPC_PKT_ACK:
1655 case DCERPC_PKT_CL_CANCEL:
1656 case DCERPC_PKT_FACK:
1657 case DCERPC_PKT_CANCEL_ACK:
1658 DEBUG(0, ("Error - Connectionless packet type %u received\n",
1659 (unsigned int)pkt->ptype));
1660 break;
1662 case DCERPC_PKT_BIND:
1664 * We assume that a pipe bind is only in one pdu.
1666 if (pipe_init_outgoing_data(p)) {
1667 reply = api_pipe_bind_req(p, pkt);
1669 break;
1671 case DCERPC_PKT_BIND_ACK:
1672 case DCERPC_PKT_BIND_NAK:
1673 DEBUG(0, ("Error - DCERPC_PKT_BINDACK/DCERPC_PKT_BINDNACK "
1674 "packet type %u received.\n",
1675 (unsigned int)pkt->ptype));
1676 break;
1679 case DCERPC_PKT_ALTER:
1681 * We assume that a pipe bind is only in one pdu.
1683 if (pipe_init_outgoing_data(p)) {
1684 reply = api_pipe_alter_context(p, pkt);
1686 break;
1688 case DCERPC_PKT_ALTER_RESP:
1689 DEBUG(0, ("Error - DCERPC_PKT_ALTER_RESP received: "
1690 "Should only be server -> client.\n"));
1691 break;
1693 case DCERPC_PKT_AUTH3:
1695 * The third packet in an auth exchange.
1697 if (pipe_init_outgoing_data(p)) {
1698 reply = api_pipe_bind_auth3(p, pkt);
1700 break;
1702 case DCERPC_PKT_SHUTDOWN:
1703 DEBUG(0, ("Error - DCERPC_PKT_SHUTDOWN received: "
1704 "Should only be server -> client.\n"));
1705 break;
1707 case DCERPC_PKT_CO_CANCEL:
1708 /* For now just free all client data and continue
1709 * processing. */
1710 DEBUG(3,("process_complete_pdu: DCERPC_PKT_CO_CANCEL."
1711 " Abandoning rpc call.\n"));
1712 /* As we never do asynchronous RPC serving, we can
1713 * never cancel a call (as far as I know).
1714 * If we ever did we'd have to send a cancel_ack reply.
1715 * For now, just free all client data and continue
1716 * processing. */
1717 reply = True;
1718 break;
1720 #if 0
1721 /* Enable this if we're doing async rpc. */
1722 /* We must check the outstanding callid matches. */
1723 if (pipe_init_outgoing_data(p)) {
1724 /* Send a cancel_ack PDU reply. */
1725 /* We should probably check the auth-verifier here. */
1726 reply = setup_cancel_ack_reply(p, pkt);
1728 break;
1729 #endif
1731 case DCERPC_PKT_ORPHANED:
1732 /* We should probably check the auth-verifier here.
1733 * For now just free all client data and continue
1734 * processing. */
1735 DEBUG(3, ("process_complete_pdu: DCERPC_PKT_ORPHANED."
1736 " Abandoning rpc call.\n"));
1737 reply = True;
1738 break;
1740 default:
1741 DEBUG(0, ("process_complete_pdu: "
1742 "Unknown rpc type = %u received.\n",
1743 (unsigned int)pkt->ptype));
1744 break;
1747 done:
1748 if (!reply) {
1749 DEBUG(3,("DCE/RPC fault sent!"));
1750 set_incoming_fault(p);
1751 setup_fault_pdu(p, NT_STATUS(DCERPC_FAULT_OP_RNG_ERROR));
1752 TALLOC_FREE(pkt);
1753 } else {
1755 * Reset the lengths. We're ready for a new pdu.
1757 TALLOC_FREE(p->in_data.pdu.data);
1758 p->in_data.pdu_needed_len = 0;
1759 p->in_data.pdu.length = 0;
1762 TALLOC_FREE(pkt);