libwbclient4: Add wbc_xids_to_sids
[Samba.git] / source3 / rpc_server / srv_pipe.c
blob3f6f3dc38e6cb9413bc5915a667466a9afbd943c
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/dcerpc.h"
34 #include "../librpc/rpc/rpc_common.h"
35 #include "dcesrv_auth_generic.h"
36 #include "rpc_server.h"
37 #include "rpc_dce.h"
38 #include "smbd/smbd.h"
39 #include "auth.h"
40 #include "ntdomain.h"
41 #include "rpc_server/srv_pipe.h"
42 #include "rpc_server/rpc_contexts.h"
43 #include "lib/param/param.h"
44 #include "librpc/ndr/ndr_table.h"
45 #include "auth/gensec/gensec.h"
47 #undef DBGC_CLASS
48 #define DBGC_CLASS DBGC_RPC_SRV
50 /**
51 * Dump everything from the start of the end up of the provided data
52 * into a file, but only at debug level >= 50
53 **/
54 static void dump_pdu_region(const char *name, int v,
55 DATA_BLOB *data, size_t start, size_t end)
57 int fd, i;
58 char *fname = NULL;
59 ssize_t sz;
61 if (DEBUGLEVEL < 50) return;
63 if (start > data->length || end > data->length || start > end) return;
65 for (i = 1; i < 100; i++) {
66 if (v != -1) {
67 fname = talloc_asprintf(talloc_tos(),
68 "/tmp/%s_%d.%d.prs",
69 name, v, i);
70 } else {
71 fname = talloc_asprintf(talloc_tos(),
72 "/tmp/%s_%d.prs",
73 name, i);
75 if (!fname) {
76 return;
78 fd = open(fname, O_WRONLY|O_CREAT|O_EXCL, 0644);
79 if (fd != -1 || errno != EEXIST) break;
81 if (fd != -1) {
82 sz = write(fd, data->data + start, end - start);
83 i = close(fd);
84 if ((sz != end - start) || (i != 0) ) {
85 DEBUG(0, ("Error writing/closing %s: %ld!=%ld %d\n",
86 fname, (unsigned long)sz,
87 (unsigned long)end - start, i));
88 } else {
89 DEBUG(0,("created %s\n", fname));
92 TALLOC_FREE(fname);
95 static DATA_BLOB generic_session_key(void)
97 return data_blob_const("SystemLibraryDTC", 16);
100 /*******************************************************************
101 Generate the next PDU to be returned from the data.
102 ********************************************************************/
104 static NTSTATUS create_next_packet(TALLOC_CTX *mem_ctx,
105 struct pipe_auth_data *auth,
106 uint32_t call_id,
107 DATA_BLOB *rdata,
108 size_t data_sent_length,
109 DATA_BLOB *frag,
110 size_t *pdu_size)
112 union dcerpc_payload u;
113 uint8_t pfc_flags;
114 size_t data_left;
115 size_t data_to_send;
116 size_t frag_len;
117 size_t pad_len = 0;
118 size_t auth_len = 0;
119 NTSTATUS status;
121 ZERO_STRUCT(u.response);
123 /* Set up rpc packet pfc flags. */
124 if (data_sent_length == 0) {
125 pfc_flags = DCERPC_PFC_FLAG_FIRST;
126 } else {
127 pfc_flags = 0;
130 /* Work out how much we can fit in a single PDU. */
131 data_left = rdata->length - data_sent_length;
133 /* Ensure there really is data left to send. */
134 if (!data_left) {
135 DEBUG(0, ("No data left to send !\n"));
136 return NT_STATUS_BUFFER_TOO_SMALL;
139 status = dcerpc_guess_sizes(auth,
140 DCERPC_RESPONSE_LENGTH,
141 data_left,
142 RPC_MAX_PDU_FRAG_LEN,
143 SERVER_NDR_PADDING_SIZE,
144 &data_to_send, &frag_len,
145 &auth_len, &pad_len);
146 if (!NT_STATUS_IS_OK(status)) {
147 return status;
150 /* Set up the alloc hint. This should be the data left to send. */
151 u.response.alloc_hint = data_left;
153 /* Work out if this PDU will be the last. */
154 if (data_sent_length + data_to_send >= rdata->length) {
155 pfc_flags |= DCERPC_PFC_FLAG_LAST;
158 /* Prepare data to be NDR encoded. */
159 u.response.stub_and_verifier =
160 data_blob_const(rdata->data + data_sent_length, data_to_send);
162 /* Store the packet in the data stream. */
163 status = dcerpc_push_ncacn_packet(mem_ctx, DCERPC_PKT_RESPONSE,
164 pfc_flags, auth_len, call_id,
165 &u, frag);
166 if (!NT_STATUS_IS_OK(status)) {
167 DEBUG(0, ("Failed to marshall RPC Packet.\n"));
168 return status;
171 if (auth_len) {
172 /* Set the proper length on the pdu, including padding.
173 * Only needed if an auth trailer will be appended. */
174 dcerpc_set_frag_length(frag, frag->length
175 + pad_len
176 + DCERPC_AUTH_TRAILER_LENGTH
177 + auth_len);
180 if (auth_len) {
181 status = dcerpc_add_auth_footer(auth, pad_len, frag);
182 if (!NT_STATUS_IS_OK(status)) {
183 data_blob_free(frag);
184 return status;
188 *pdu_size = data_to_send;
189 return NT_STATUS_OK;
192 /*******************************************************************
193 Generate the next PDU to be returned from the data in p->rdata.
194 ********************************************************************/
196 bool create_next_pdu(struct pipes_struct *p)
198 size_t pdu_size = 0;
199 NTSTATUS status;
202 * If we're in the fault state, keep returning fault PDU's until
203 * the pipe gets closed. JRA.
205 if (p->fault_state) {
206 setup_fault_pdu(p, NT_STATUS(p->fault_state));
207 return true;
210 status = create_next_packet(p->mem_ctx, &p->auth,
211 p->call_id, &p->out_data.rdata,
212 p->out_data.data_sent_length,
213 &p->out_data.frag, &pdu_size);
214 if (!NT_STATUS_IS_OK(status)) {
215 DEBUG(0, ("Failed to create packet with error %s, "
216 "(auth level %u / type %u)\n",
217 nt_errstr(status),
218 (unsigned int)p->auth.auth_level,
219 (unsigned int)p->auth.auth_type));
220 return false;
223 /* Setup the counts for this PDU. */
224 p->out_data.data_sent_length += pdu_size;
225 p->out_data.current_pdu_sent = 0;
226 return true;
230 static bool pipe_init_outgoing_data(struct pipes_struct *p);
232 /*******************************************************************
233 Marshall a bind_nak pdu.
234 *******************************************************************/
236 static bool setup_bind_nak(struct pipes_struct *p, struct ncacn_packet *pkt)
238 NTSTATUS status;
239 union dcerpc_payload u;
241 /* Free any memory in the current return data buffer. */
242 pipe_init_outgoing_data(p);
245 * Initialize a bind_nak header.
248 ZERO_STRUCT(u);
250 u.bind_nak.reject_reason = 0;
253 * Marshall directly into the outgoing PDU space. We
254 * must do this as we need to set to the bind response
255 * header and are never sending more than one PDU here.
258 status = dcerpc_push_ncacn_packet(p->mem_ctx,
259 DCERPC_PKT_BIND_NAK,
260 DCERPC_PFC_FLAG_FIRST |
261 DCERPC_PFC_FLAG_LAST,
263 pkt->call_id,
265 &p->out_data.frag);
266 if (!NT_STATUS_IS_OK(status)) {
267 return False;
270 p->out_data.data_sent_length = 0;
271 p->out_data.current_pdu_sent = 0;
273 TALLOC_FREE(p->auth.auth_ctx);
274 p->auth.auth_level = DCERPC_AUTH_LEVEL_NONE;
275 p->auth.auth_type = DCERPC_AUTH_TYPE_NONE;
276 p->pipe_bound = False;
278 return True;
281 /*******************************************************************
282 Marshall a fault pdu.
283 *******************************************************************/
285 bool setup_fault_pdu(struct pipes_struct *p, NTSTATUS fault_status)
287 NTSTATUS status;
288 union dcerpc_payload u;
290 /* Free any memory in the current return data buffer. */
291 pipe_init_outgoing_data(p);
294 * Initialize a fault header.
297 ZERO_STRUCT(u);
299 u.fault.status = NT_STATUS_V(fault_status);
300 u.fault._pad = data_blob_talloc_zero(p->mem_ctx, 4);
303 * Marshall directly into the outgoing PDU space. We
304 * must do this as we need to set to the bind response
305 * header and are never sending more than one PDU here.
308 status = dcerpc_push_ncacn_packet(p->mem_ctx,
309 DCERPC_PKT_FAULT,
310 DCERPC_PFC_FLAG_FIRST |
311 DCERPC_PFC_FLAG_LAST |
312 DCERPC_PFC_FLAG_DID_NOT_EXECUTE,
314 p->call_id,
316 &p->out_data.frag);
317 if (!NT_STATUS_IS_OK(status)) {
318 return False;
321 p->out_data.data_sent_length = 0;
322 p->out_data.current_pdu_sent = 0;
324 return True;
327 /*******************************************************************
328 Ensure a bind request has the correct abstract & transfer interface.
329 Used to reject unknown binds from Win2k.
330 *******************************************************************/
332 static bool check_bind_req(struct pipes_struct *p,
333 struct ndr_syntax_id* abstract,
334 struct ndr_syntax_id* transfer,
335 uint32_t context_id)
337 struct pipe_rpc_fns *context_fns;
338 bool ok;
340 DEBUG(3,("check_bind_req for %s\n",
341 ndr_interface_name(&abstract->uuid,
342 abstract->if_version)));
344 /* we have to check all now since win2k introduced a new UUID on the lsaprpc pipe */
345 if (rpc_srv_pipe_exists_by_id(abstract) &&
346 ndr_syntax_id_equal(transfer, &ndr_transfer_syntax_ndr)) {
347 DEBUG(3, ("check_bind_req: %s -> %s rpc service\n",
348 rpc_srv_get_pipe_cli_name(abstract),
349 rpc_srv_get_pipe_srv_name(abstract)));
350 } else {
351 return false;
354 ok = init_pipe_handles(p, abstract);
355 if (!ok) {
356 DEBUG(1, ("Failed to init pipe handles!\n"));
357 return false;
360 context_fns = talloc(p, struct pipe_rpc_fns);
361 if (context_fns == NULL) {
362 DEBUG(0,("check_bind_req: talloc() failed!\n"));
363 return false;
366 context_fns->next = context_fns->prev = NULL;
367 context_fns->n_cmds = rpc_srv_get_pipe_num_cmds(abstract);
368 context_fns->cmds = rpc_srv_get_pipe_cmds(abstract);
369 context_fns->context_id = context_id;
370 context_fns->syntax = *abstract;
372 /* add to the list of open contexts */
374 DLIST_ADD( p->contexts, context_fns );
376 return True;
380 * Is a named pipe known?
381 * @param[in] pipename Just the filename
382 * @result Do we want to serve this?
384 bool is_known_pipename(const char *pipename, struct ndr_syntax_id *syntax)
386 NTSTATUS status;
388 if (lp_disable_spoolss() && strequal(pipename, "spoolss")) {
389 DEBUG(10, ("refusing spoolss access\n"));
390 return false;
393 if (rpc_srv_get_pipe_interface_by_cli_name(pipename, syntax)) {
394 return true;
397 status = smb_probe_module("rpc", pipename);
398 if (!NT_STATUS_IS_OK(status)) {
399 DEBUG(10, ("is_known_pipename: %s unknown\n", pipename));
400 return false;
402 DEBUG(10, ("is_known_pipename: %s loaded dynamically\n", pipename));
405 * Scan the list again for the interface id
407 if (rpc_srv_get_pipe_interface_by_cli_name(pipename, syntax)) {
408 return true;
411 DEBUG(10, ("is_known_pipename: pipe %s did not register itself!\n",
412 pipename));
414 return false;
417 /*******************************************************************
418 Handle an NTLMSSP bind auth.
419 *******************************************************************/
421 static bool pipe_auth_generic_bind(struct pipes_struct *p,
422 struct ncacn_packet *pkt,
423 struct dcerpc_auth *auth_info,
424 DATA_BLOB *response)
426 TALLOC_CTX *mem_ctx = pkt;
427 struct gensec_security *gensec_security = NULL;
428 NTSTATUS status;
430 status = auth_generic_server_authtype_start(p,
431 auth_info->auth_type,
432 auth_info->auth_level,
433 &auth_info->credentials,
434 response,
435 p->remote_address,
436 &gensec_security);
437 if (!NT_STATUS_EQUAL(status, NT_STATUS_OK)) {
438 DEBUG(0, (__location__ ": auth_generic_server_authtype_start failed: %s\n",
439 nt_errstr(status)));
440 return false;
443 /* Make sure data is bound to the memctx, to be freed the caller */
444 talloc_steal(mem_ctx, response->data);
446 p->auth.auth_ctx = gensec_security;
447 p->auth.auth_type = auth_info->auth_type;
449 if (pkt->pfc_flags & DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN) {
450 p->auth.client_hdr_signing = true;
451 p->auth.hdr_signing = gensec_have_feature(gensec_security,
452 GENSEC_FEATURE_SIGN_PKT_HEADER);
455 if (p->auth.hdr_signing) {
456 gensec_want_feature(gensec_security,
457 GENSEC_FEATURE_SIGN_PKT_HEADER);
460 return true;
463 /*******************************************************************
464 Process an NTLMSSP authentication response.
465 If this function succeeds, the user has been authenticated
466 and their domain, name and calling workstation stored in
467 the pipe struct.
468 *******************************************************************/
470 static bool pipe_auth_generic_verify_final(TALLOC_CTX *mem_ctx,
471 struct gensec_security *gensec_security,
472 enum dcerpc_AuthLevel auth_level,
473 struct auth_session_info **session_info)
475 NTSTATUS status;
476 bool ret;
478 DEBUG(5, (__location__ ": checking user details\n"));
480 /* Finally - if the pipe negotiated integrity (sign) or privacy (seal)
481 ensure the underlying NTLMSSP flags are also set. If not we should
482 refuse the bind. */
484 status = auth_generic_server_check_flags(gensec_security,
485 (auth_level ==
486 DCERPC_AUTH_LEVEL_INTEGRITY),
487 (auth_level ==
488 DCERPC_AUTH_LEVEL_PRIVACY));
489 if (!NT_STATUS_IS_OK(status)) {
490 DEBUG(0, (__location__ ": Client failed to negotatie proper "
491 "security for rpc connection\n"));
492 return false;
495 TALLOC_FREE(*session_info);
497 status = auth_generic_server_get_user_info(gensec_security,
498 mem_ctx, session_info);
499 if (!NT_STATUS_IS_OK(status)) {
500 DEBUG(0, (__location__ ": failed to obtain the server info "
501 "for authenticated user: %s\n", nt_errstr(status)));
502 return false;
505 if ((*session_info)->security_token == NULL) {
506 DEBUG(1, ("Auth module failed to provide nt_user_token\n"));
507 return false;
511 * We're an authenticated bind over smb, so the session key needs to
512 * be set to "SystemLibraryDTC". Weird, but this is what Windows
513 * does. See the RPC-SAMBA3SESSIONKEY.
516 ret = session_info_set_session_key((*session_info), generic_session_key());
517 if (!ret) {
518 DEBUG(0, ("Failed to set session key!\n"));
519 return false;
522 return true;
525 static NTSTATUS pipe_auth_verify_final(struct pipes_struct *p)
527 struct gensec_security *gensec_security;
529 switch (p->auth.auth_type) {
530 case DCERPC_AUTH_TYPE_NTLMSSP:
531 case DCERPC_AUTH_TYPE_KRB5:
532 case DCERPC_AUTH_TYPE_SPNEGO:
533 gensec_security = talloc_get_type_abort(p->auth.auth_ctx,
534 struct gensec_security);
535 if (!pipe_auth_generic_verify_final(p, gensec_security,
536 p->auth.auth_level,
537 &p->session_info)) {
538 return NT_STATUS_ACCESS_DENIED;
540 break;
541 default:
542 DEBUG(0, (__location__ ": incorrect auth type (%u).\n",
543 (unsigned int)p->auth.auth_type));
544 return NT_STATUS_ACCESS_DENIED;
547 p->pipe_bound = true;
549 return NT_STATUS_OK;
552 /*******************************************************************
553 Respond to a pipe bind request.
554 *******************************************************************/
556 static bool api_pipe_bind_req(struct pipes_struct *p,
557 struct ncacn_packet *pkt)
559 struct dcerpc_auth auth_info;
560 uint16 assoc_gid;
561 unsigned int auth_type = DCERPC_AUTH_TYPE_NONE;
562 NTSTATUS status;
563 struct ndr_syntax_id id;
564 uint8_t pfc_flags = 0;
565 union dcerpc_payload u;
566 struct dcerpc_ack_ctx bind_ack_ctx;
567 DATA_BLOB auth_resp = data_blob_null;
568 DATA_BLOB auth_blob = data_blob_null;
569 const struct ndr_interface_table *table;
571 /* No rebinds on a bound pipe - use alter context. */
572 if (p->pipe_bound) {
573 DEBUG(2,("Rejecting bind request on bound rpc connection\n"));
574 return setup_bind_nak(p, pkt);
577 if (pkt->u.bind.num_contexts == 0) {
578 DEBUG(0, ("api_pipe_bind_req: no rpc contexts around\n"));
579 goto err_exit;
583 * Try and find the correct pipe name to ensure
584 * that this is a pipe name we support.
586 id = pkt->u.bind.ctx_list[0].abstract_syntax;
588 table = ndr_table_by_uuid(&id.uuid);
589 if (table == NULL) {
590 DEBUG(0,("unknown interface\n"));
591 return false;
594 if (rpc_srv_pipe_exists_by_id(&id)) {
595 DEBUG(3, ("api_pipe_bind_req: %s -> %s rpc service\n",
596 rpc_srv_get_pipe_cli_name(&id),
597 rpc_srv_get_pipe_srv_name(&id)));
598 } else {
599 status = smb_probe_module(
600 "rpc", dcerpc_default_transport_endpoint(pkt,
601 NCACN_NP, table));
603 if (NT_STATUS_IS_ERR(status)) {
604 DEBUG(3,("api_pipe_bind_req: Unknown rpc service name "
605 "%s in bind request.\n",
606 ndr_interface_name(&id.uuid,
607 id.if_version)));
609 return setup_bind_nak(p, pkt);
612 if (rpc_srv_get_pipe_interface_by_cli_name(
613 dcerpc_default_transport_endpoint(pkt,
614 NCACN_NP, table),
615 &id)) {
616 DEBUG(3, ("api_pipe_bind_req: %s -> %s rpc service\n",
617 rpc_srv_get_pipe_cli_name(&id),
618 rpc_srv_get_pipe_srv_name(&id)));
619 } else {
620 DEBUG(0, ("module %s doesn't provide functions for "
621 "pipe %s!\n",
622 ndr_interface_name(&id.uuid,
623 id.if_version),
624 ndr_interface_name(&id.uuid,
625 id.if_version)));
626 return setup_bind_nak(p, pkt);
630 DEBUG(5,("api_pipe_bind_req: make response. %d\n", __LINE__));
632 if (pkt->u.bind.assoc_group_id != 0) {
633 assoc_gid = pkt->u.bind.assoc_group_id;
634 } else {
635 assoc_gid = 0x53f0;
639 * Create the bind response struct.
642 /* If the requested abstract synt uuid doesn't match our client pipe,
643 reject the bind_ack & set the transfer interface synt to all 0's,
644 ver 0 (observed when NT5 attempts to bind to abstract interfaces
645 unknown to NT4)
646 Needed when adding entries to a DACL from NT5 - SK */
648 if (check_bind_req(p,
649 &pkt->u.bind.ctx_list[0].abstract_syntax,
650 &pkt->u.bind.ctx_list[0].transfer_syntaxes[0],
651 pkt->u.bind.ctx_list[0].context_id)) {
653 bind_ack_ctx.result = 0;
654 bind_ack_ctx.reason.value = 0;
655 bind_ack_ctx.syntax = pkt->u.bind.ctx_list[0].transfer_syntaxes[0];
656 } else {
657 p->pipe_bound = False;
658 /* Rejection reason: abstract syntax not supported */
659 bind_ack_ctx.result = DCERPC_BIND_PROVIDER_REJECT;
660 bind_ack_ctx.reason.value = DCERPC_BIND_REASON_ASYNTAX;
661 bind_ack_ctx.syntax = ndr_syntax_id_null;
665 * Check if this is an authenticated bind request.
667 if (pkt->auth_length) {
668 /* Quick length check. Won't catch a bad auth footer,
669 * prevents overrun. */
671 if (pkt->frag_length < RPC_HEADER_LEN +
672 DCERPC_AUTH_TRAILER_LENGTH +
673 pkt->auth_length) {
674 DEBUG(0,("api_pipe_bind_req: auth_len (%u) "
675 "too long for fragment %u.\n",
676 (unsigned int)pkt->auth_length,
677 (unsigned int)pkt->frag_length));
678 goto err_exit;
682 * Decode the authentication verifier.
684 status = dcerpc_pull_dcerpc_auth(pkt,
685 &pkt->u.bind.auth_info,
686 &auth_info, p->endian);
687 if (!NT_STATUS_IS_OK(status)) {
688 DEBUG(0, ("Unable to unmarshall dcerpc_auth.\n"));
689 goto err_exit;
692 auth_type = auth_info.auth_type;
694 /* Work out if we have to sign or seal etc. */
695 switch (auth_info.auth_level) {
696 case DCERPC_AUTH_LEVEL_INTEGRITY:
697 p->auth.auth_level = DCERPC_AUTH_LEVEL_INTEGRITY;
698 break;
699 case DCERPC_AUTH_LEVEL_PRIVACY:
700 p->auth.auth_level = DCERPC_AUTH_LEVEL_PRIVACY;
701 break;
702 case DCERPC_AUTH_LEVEL_CONNECT:
703 p->auth.auth_level = DCERPC_AUTH_LEVEL_CONNECT;
704 break;
705 default:
706 DEBUG(0, ("Unexpected auth level (%u).\n",
707 (unsigned int)auth_info.auth_level ));
708 goto err_exit;
711 switch (auth_type) {
712 case DCERPC_AUTH_TYPE_NTLMSSP:
713 if (!pipe_auth_generic_bind(p, pkt,
714 &auth_info, &auth_resp)) {
715 goto err_exit;
717 assoc_gid = 0x7a77;
718 break;
720 case DCERPC_AUTH_TYPE_SCHANNEL:
721 if (!pipe_auth_generic_bind(p, pkt,
722 &auth_info, &auth_resp)) {
723 goto err_exit;
725 if (!session_info_set_session_key(p->session_info, generic_session_key())) {
726 DEBUG(0, ("session_info_set_session_key failed\n"));
727 goto err_exit;
729 p->pipe_bound = true;
730 break;
732 case DCERPC_AUTH_TYPE_SPNEGO:
733 case DCERPC_AUTH_TYPE_KRB5:
734 if (!pipe_auth_generic_bind(p, pkt,
735 &auth_info, &auth_resp)) {
736 goto err_exit;
738 break;
740 case DCERPC_AUTH_TYPE_NCALRPC_AS_SYSTEM:
741 if (p->transport == NCALRPC && p->ncalrpc_as_system) {
742 TALLOC_FREE(p->session_info);
744 status = make_session_info_system(p,
745 &p->session_info);
746 if (!NT_STATUS_IS_OK(status)) {
747 goto err_exit;
750 auth_resp = data_blob_talloc(pkt,
751 "NCALRPC_AUTH_OK",
752 15);
754 p->auth.auth_type = DCERPC_AUTH_TYPE_NCALRPC_AS_SYSTEM;
755 p->pipe_bound = true;
756 } else {
757 goto err_exit;
759 break;
761 case DCERPC_AUTH_TYPE_NONE:
762 break;
764 default:
765 DEBUG(0, ("Unknown auth type %x requested.\n", auth_type));
766 goto err_exit;
770 if (auth_type == DCERPC_AUTH_TYPE_NONE) {
771 /* Unauthenticated bind request. */
772 /* We're finished - no more packets. */
773 p->auth.auth_type = DCERPC_AUTH_TYPE_NONE;
774 /* We must set the pipe auth_level here also. */
775 p->auth.auth_level = DCERPC_AUTH_LEVEL_NONE;
776 p->pipe_bound = True;
777 /* The session key was initialized from the SMB
778 * session in make_internal_rpc_pipe_p */
781 ZERO_STRUCT(u.bind_ack);
782 u.bind_ack.max_xmit_frag = RPC_MAX_PDU_FRAG_LEN;
783 u.bind_ack.max_recv_frag = RPC_MAX_PDU_FRAG_LEN;
784 u.bind_ack.assoc_group_id = assoc_gid;
786 /* name has to be \PIPE\xxxxx */
787 u.bind_ack.secondary_address =
788 talloc_asprintf(pkt, "\\PIPE\\%s",
789 rpc_srv_get_pipe_srv_name(&id));
790 if (!u.bind_ack.secondary_address) {
791 DEBUG(0, ("Out of memory!\n"));
792 goto err_exit;
794 u.bind_ack.secondary_address_size =
795 strlen(u.bind_ack.secondary_address) + 1;
797 u.bind_ack.num_results = 1;
798 u.bind_ack.ctx_list = &bind_ack_ctx;
800 /* NOTE: We leave the auth_info empty so we can calculate the padding
801 * later and then append the auth_info --simo */
804 * Marshall directly into the outgoing PDU space. We
805 * must do this as we need to set to the bind response
806 * header and are never sending more than one PDU here.
809 pfc_flags = DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST;
811 if (p->auth.hdr_signing) {
812 pfc_flags |= DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN;
815 status = dcerpc_push_ncacn_packet(p->mem_ctx,
816 DCERPC_PKT_BIND_ACK,
817 pfc_flags,
818 auth_resp.length,
819 pkt->call_id,
821 &p->out_data.frag);
822 if (!NT_STATUS_IS_OK(status)) {
823 DEBUG(0, ("Failed to marshall bind_ack packet. (%s)\n",
824 nt_errstr(status)));
827 if (auth_resp.length) {
829 status = dcerpc_push_dcerpc_auth(pkt,
830 auth_type,
831 auth_info.auth_level,
833 1, /* auth_context_id */
834 &auth_resp,
835 &auth_blob);
836 if (!NT_STATUS_IS_OK(status)) {
837 DEBUG(0, ("Marshalling of dcerpc_auth failed.\n"));
838 goto err_exit;
842 /* Now that we have the auth len store it into the right place in
843 * the dcerpc header */
844 dcerpc_set_frag_length(&p->out_data.frag,
845 p->out_data.frag.length + auth_blob.length);
847 if (auth_blob.length) {
849 if (!data_blob_append(p->mem_ctx, &p->out_data.frag,
850 auth_blob.data, auth_blob.length)) {
851 DEBUG(0, ("Append of auth info failed.\n"));
852 goto err_exit;
857 * Setup the lengths for the initial reply.
860 p->out_data.data_sent_length = 0;
861 p->out_data.current_pdu_sent = 0;
863 TALLOC_FREE(auth_blob.data);
864 return True;
866 err_exit:
868 data_blob_free(&p->out_data.frag);
869 TALLOC_FREE(auth_blob.data);
870 return setup_bind_nak(p, pkt);
873 /*******************************************************************
874 This is the "stage3" response after a bind request and reply.
875 *******************************************************************/
877 bool api_pipe_bind_auth3(struct pipes_struct *p, struct ncacn_packet *pkt)
879 struct dcerpc_auth auth_info;
880 DATA_BLOB response = data_blob_null;
881 struct gensec_security *gensec_security;
882 NTSTATUS status;
884 DEBUG(5, ("api_pipe_bind_auth3: decode request. %d\n", __LINE__));
886 if (pkt->auth_length == 0) {
887 DEBUG(1, ("No auth field sent for bind request!\n"));
888 goto err;
891 /* Ensure there's enough data for an authenticated request. */
892 if (pkt->frag_length < RPC_HEADER_LEN
893 + DCERPC_AUTH_TRAILER_LENGTH
894 + pkt->auth_length) {
895 DEBUG(1,("api_pipe_ntlmssp_auth_process: auth_len "
896 "%u is too large.\n",
897 (unsigned int)pkt->auth_length));
898 goto err;
902 * Decode the authentication verifier response.
905 status = dcerpc_pull_dcerpc_auth(pkt,
906 &pkt->u.auth3.auth_info,
907 &auth_info, p->endian);
908 if (!NT_STATUS_IS_OK(status)) {
909 DEBUG(1, ("Failed to unmarshall dcerpc_auth.\n"));
910 goto err;
913 /* We must NEVER look at auth_info->auth_pad_len here,
914 * as old Samba client code gets it wrong and sends it
915 * as zero. JRA.
918 if (auth_info.auth_type != p->auth.auth_type) {
919 DEBUG(1, ("Auth type mismatch! Client sent %d, "
920 "but auth was started as type %d!\n",
921 auth_info.auth_type, p->auth.auth_type));
922 goto err;
925 switch (auth_info.auth_type) {
926 case DCERPC_AUTH_TYPE_NTLMSSP:
927 case DCERPC_AUTH_TYPE_KRB5:
928 case DCERPC_AUTH_TYPE_SPNEGO:
929 gensec_security = talloc_get_type_abort(p->auth.auth_ctx,
930 struct gensec_security);
931 status = auth_generic_server_step(gensec_security,
932 pkt, &auth_info.credentials,
933 &response);
934 break;
935 default:
936 DEBUG(1, (__location__ ": incorrect auth type (%u).\n",
937 (unsigned int)auth_info.auth_type));
938 return false;
941 if (NT_STATUS_EQUAL(status,
942 NT_STATUS_MORE_PROCESSING_REQUIRED) ||
943 response.length) {
944 DEBUG(1, (__location__ ": This was supposed to be the final "
945 "leg, but crypto machinery claims a response is "
946 "needed, aborting auth!\n"));
947 data_blob_free(&response);
948 goto err;
950 if (!NT_STATUS_IS_OK(status)) {
951 DEBUG(2, ("Auth failed (%s)\n", nt_errstr(status)));
952 goto err;
955 /* Now verify auth was indeed successful and extract server info */
956 status = pipe_auth_verify_final(p);
957 if (!NT_STATUS_IS_OK(status)) {
958 DEBUG(2, ("Auth Verify failed (%s)\n", nt_errstr(status)));
959 goto err;
962 return true;
964 err:
966 TALLOC_FREE(p->auth.auth_ctx);
967 return false;
970 /****************************************************************************
971 Deal with an alter context call. Can be third part of 3 leg auth request for
972 SPNEGO calls.
973 ****************************************************************************/
975 static bool api_pipe_alter_context(struct pipes_struct *p,
976 struct ncacn_packet *pkt)
978 struct dcerpc_auth auth_info;
979 uint16 assoc_gid;
980 NTSTATUS status;
981 union dcerpc_payload u;
982 struct dcerpc_ack_ctx bind_ack_ctx;
983 DATA_BLOB auth_resp = data_blob_null;
984 DATA_BLOB auth_blob = data_blob_null;
985 int pad_len = 0;
986 struct gensec_security *gensec_security;
988 DEBUG(5,("api_pipe_alter_context: make response. %d\n", __LINE__));
990 if (pkt->u.bind.assoc_group_id != 0) {
991 assoc_gid = pkt->u.bind.assoc_group_id;
992 } else {
993 assoc_gid = 0x53f0;
997 * Create the bind response struct.
1000 /* If the requested abstract synt uuid doesn't match our client pipe,
1001 reject the bind_ack & set the transfer interface synt to all 0's,
1002 ver 0 (observed when NT5 attempts to bind to abstract interfaces
1003 unknown to NT4)
1004 Needed when adding entries to a DACL from NT5 - SK */
1006 if (check_bind_req(p,
1007 &pkt->u.bind.ctx_list[0].abstract_syntax,
1008 &pkt->u.bind.ctx_list[0].transfer_syntaxes[0],
1009 pkt->u.bind.ctx_list[0].context_id)) {
1011 bind_ack_ctx.result = 0;
1012 bind_ack_ctx.reason.value = 0;
1013 bind_ack_ctx.syntax = pkt->u.bind.ctx_list[0].transfer_syntaxes[0];
1014 } else {
1015 p->pipe_bound = False;
1016 /* Rejection reason: abstract syntax not supported */
1017 bind_ack_ctx.result = DCERPC_BIND_PROVIDER_REJECT;
1018 bind_ack_ctx.reason.value = DCERPC_BIND_REASON_ASYNTAX;
1019 bind_ack_ctx.syntax = ndr_syntax_id_null;
1023 * Check if this is an authenticated alter context request.
1025 if (pkt->auth_length) {
1026 /* Quick length check. Won't catch a bad auth footer,
1027 * prevents overrun. */
1029 if (pkt->frag_length < RPC_HEADER_LEN +
1030 DCERPC_AUTH_TRAILER_LENGTH +
1031 pkt->auth_length) {
1032 DEBUG(0,("api_pipe_alter_context: auth_len (%u) "
1033 "too long for fragment %u.\n",
1034 (unsigned int)pkt->auth_length,
1035 (unsigned int)pkt->frag_length ));
1036 goto err_exit;
1039 status = dcerpc_pull_dcerpc_auth(pkt,
1040 &pkt->u.bind.auth_info,
1041 &auth_info, p->endian);
1042 if (!NT_STATUS_IS_OK(status)) {
1043 DEBUG(0, ("Unable to unmarshall dcerpc_auth.\n"));
1044 goto err_exit;
1047 /* We can only finish if the pipe is unbound for now */
1048 if (p->pipe_bound) {
1049 DEBUG(0, (__location__ ": Pipe already bound, "
1050 "Altering Context not yet supported!\n"));
1051 goto err_exit;
1054 if (auth_info.auth_type != p->auth.auth_type) {
1055 DEBUG(0, ("Auth type mismatch! Client sent %d, "
1056 "but auth was started as type %d!\n",
1057 auth_info.auth_type, p->auth.auth_type));
1058 goto err_exit;
1062 switch (auth_info.auth_type) {
1063 case DCERPC_AUTH_TYPE_SPNEGO:
1064 case DCERPC_AUTH_TYPE_KRB5:
1065 case DCERPC_AUTH_TYPE_NTLMSSP:
1066 gensec_security = talloc_get_type_abort(p->auth.auth_ctx,
1067 struct gensec_security);
1068 status = auth_generic_server_step(gensec_security,
1069 pkt,
1070 &auth_info.credentials,
1071 &auth_resp);
1072 break;
1074 default:
1075 DEBUG(3, (__location__ ": Usupported auth type (%d) "
1076 "in alter-context call\n",
1077 auth_info.auth_type));
1078 goto err_exit;
1081 if (NT_STATUS_IS_OK(status)) {
1082 /* third leg of auth, verify auth info */
1083 status = pipe_auth_verify_final(p);
1084 if (!NT_STATUS_IS_OK(status)) {
1085 DEBUG(0, ("Auth Verify failed (%s)\n",
1086 nt_errstr(status)));
1087 goto err_exit;
1089 } else if (NT_STATUS_EQUAL(status,
1090 NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1091 DEBUG(10, ("More auth legs required.\n"));
1092 } else {
1093 DEBUG(0, ("Auth step returned an error (%s)\n",
1094 nt_errstr(status)));
1095 goto err_exit;
1099 ZERO_STRUCT(u.alter_resp);
1100 u.alter_resp.max_xmit_frag = RPC_MAX_PDU_FRAG_LEN;
1101 u.alter_resp.max_recv_frag = RPC_MAX_PDU_FRAG_LEN;
1102 u.alter_resp.assoc_group_id = assoc_gid;
1104 /* secondary address CAN be NULL
1105 * as the specs say it's ignored.
1106 * It MUST be NULL to have the spoolss working.
1108 u.alter_resp.secondary_address = "";
1109 u.alter_resp.secondary_address_size = 1;
1111 u.alter_resp.num_results = 1;
1112 u.alter_resp.ctx_list = &bind_ack_ctx;
1114 /* NOTE: We leave the auth_info empty so we can calculate the padding
1115 * later and then append the auth_info --simo */
1118 * Marshall directly into the outgoing PDU space. We
1119 * must do this as we need to set to the bind response
1120 * header and are never sending more than one PDU here.
1123 status = dcerpc_push_ncacn_packet(p->mem_ctx,
1124 DCERPC_PKT_ALTER_RESP,
1125 DCERPC_PFC_FLAG_FIRST |
1126 DCERPC_PFC_FLAG_LAST,
1127 auth_resp.length,
1128 pkt->call_id,
1130 &p->out_data.frag);
1131 if (!NT_STATUS_IS_OK(status)) {
1132 DEBUG(0, ("Failed to marshall bind_ack packet. (%s)\n",
1133 nt_errstr(status)));
1136 if (auth_resp.length) {
1138 /* Work out any padding needed before the auth footer. */
1139 pad_len = p->out_data.frag.length % SERVER_NDR_PADDING_SIZE;
1140 if (pad_len) {
1141 pad_len = SERVER_NDR_PADDING_SIZE - pad_len;
1142 DEBUG(10, ("auth pad_len = %u\n",
1143 (unsigned int)pad_len));
1146 status = dcerpc_push_dcerpc_auth(pkt,
1147 auth_info.auth_type,
1148 auth_info.auth_level,
1149 pad_len,
1150 1, /* auth_context_id */
1151 &auth_resp,
1152 &auth_blob);
1153 if (!NT_STATUS_IS_OK(status)) {
1154 DEBUG(0, ("Marshalling of dcerpc_auth failed.\n"));
1155 goto err_exit;
1159 /* Now that we have the auth len store it into the right place in
1160 * the dcerpc header */
1161 dcerpc_set_frag_length(&p->out_data.frag,
1162 p->out_data.frag.length +
1163 pad_len + auth_blob.length);
1165 if (auth_resp.length) {
1166 if (pad_len) {
1167 char pad[SERVER_NDR_PADDING_SIZE];
1168 memset(pad, '\0', SERVER_NDR_PADDING_SIZE);
1169 if (!data_blob_append(p->mem_ctx,
1170 &p->out_data.frag,
1171 pad, pad_len)) {
1172 DEBUG(0, ("api_pipe_bind_req: failed to add "
1173 "%u bytes of pad data.\n",
1174 (unsigned int)pad_len));
1175 goto err_exit;
1179 if (!data_blob_append(p->mem_ctx, &p->out_data.frag,
1180 auth_blob.data, auth_blob.length)) {
1181 DEBUG(0, ("Append of auth info failed.\n"));
1182 goto err_exit;
1187 * Setup the lengths for the initial reply.
1190 p->out_data.data_sent_length = 0;
1191 p->out_data.current_pdu_sent = 0;
1193 TALLOC_FREE(auth_blob.data);
1194 return True;
1196 err_exit:
1198 data_blob_free(&p->out_data.frag);
1199 TALLOC_FREE(auth_blob.data);
1200 return setup_bind_nak(p, pkt);
1203 static bool api_rpcTNP(struct pipes_struct *p, struct ncacn_packet *pkt,
1204 const struct api_struct *api_rpc_cmds, int n_cmds,
1205 const struct ndr_syntax_id *syntax);
1207 /****************************************************************************
1208 Find the correct RPC function to call for this request.
1209 If the pipe is authenticated then become the correct UNIX user
1210 before doing the call.
1211 ****************************************************************************/
1213 static bool api_pipe_request(struct pipes_struct *p,
1214 struct ncacn_packet *pkt)
1216 bool ret = False;
1217 struct pipe_rpc_fns *pipe_fns;
1219 if (!p->pipe_bound) {
1220 DEBUG(1, ("Pipe not bound!\n"));
1221 data_blob_free(&p->out_data.rdata);
1222 return false;
1225 if (!become_authenticated_pipe_user(p->session_info)) {
1226 DEBUG(1, ("Failed to become pipe user!\n"));
1227 data_blob_free(&p->out_data.rdata);
1228 return false;
1231 /* get the set of RPC functions for this context */
1233 pipe_fns = find_pipe_fns_by_context(p->contexts,
1234 pkt->u.request.context_id);
1236 if ( pipe_fns ) {
1237 TALLOC_CTX *frame = talloc_stackframe();
1239 DEBUG(5, ("Requested %s rpc service\n",
1240 ndr_interface_name(&pipe_fns->syntax.uuid,
1241 pipe_fns->syntax.if_version)));
1243 ret = api_rpcTNP(p, pkt, pipe_fns->cmds, pipe_fns->n_cmds,
1244 &pipe_fns->syntax);
1246 TALLOC_FREE(frame);
1248 else {
1249 DEBUG(0, ("No rpc function table associated with context "
1250 "[%d]\n",
1251 pkt->u.request.context_id));
1254 unbecome_authenticated_pipe_user();
1256 return ret;
1259 /*******************************************************************
1260 Calls the underlying RPC function for a named pipe.
1261 ********************************************************************/
1263 static bool api_rpcTNP(struct pipes_struct *p, struct ncacn_packet *pkt,
1264 const struct api_struct *api_rpc_cmds, int n_cmds,
1265 const struct ndr_syntax_id *syntax)
1267 int fn_num;
1268 uint32_t offset1;
1269 const struct ndr_interface_table *table;
1271 /* interpret the command */
1272 DEBUG(4,("api_rpcTNP: %s op 0x%x - ",
1273 ndr_interface_name(&syntax->uuid, syntax->if_version),
1274 pkt->u.request.opnum));
1276 table = ndr_table_by_uuid(&syntax->uuid);
1277 if (table == NULL) {
1278 DEBUG(0,("unknown interface\n"));
1279 return false;
1282 if (DEBUGLEVEL >= 50) {
1283 fstring name;
1284 slprintf(name, sizeof(name)-1, "in_%s",
1285 dcerpc_default_transport_endpoint(pkt, NCACN_NP, table));
1286 dump_pdu_region(name, pkt->u.request.opnum,
1287 &p->in_data.data, 0,
1288 p->in_data.data.length);
1291 for (fn_num = 0; fn_num < n_cmds; fn_num++) {
1292 if (api_rpc_cmds[fn_num].opnum == pkt->u.request.opnum &&
1293 api_rpc_cmds[fn_num].fn != NULL) {
1294 DEBUG(3, ("api_rpcTNP: rpc command: %s\n",
1295 api_rpc_cmds[fn_num].name));
1296 break;
1300 if (fn_num == n_cmds) {
1302 * For an unknown RPC just return a fault PDU but
1303 * return True to allow RPC's on the pipe to continue
1304 * and not put the pipe into fault state. JRA.
1306 DEBUG(4, ("unknown\n"));
1307 setup_fault_pdu(p, NT_STATUS(DCERPC_FAULT_OP_RNG_ERROR));
1308 return True;
1311 offset1 = p->out_data.rdata.length;
1313 DEBUG(6, ("api_rpc_cmds[%d].fn == %p\n",
1314 fn_num, api_rpc_cmds[fn_num].fn));
1315 /* do the actual command */
1316 if(!api_rpc_cmds[fn_num].fn(p)) {
1317 DEBUG(0,("api_rpcTNP: %s: %s failed.\n",
1318 ndr_interface_name(&syntax->uuid, syntax->if_version),
1319 api_rpc_cmds[fn_num].name));
1320 data_blob_free(&p->out_data.rdata);
1321 return False;
1324 if (p->fault_state) {
1325 DEBUG(4,("api_rpcTNP: fault(%d) return.\n", p->fault_state));
1326 setup_fault_pdu(p, NT_STATUS(p->fault_state));
1327 p->fault_state = 0;
1328 return true;
1331 if (DEBUGLEVEL >= 50) {
1332 fstring name;
1333 slprintf(name, sizeof(name)-1, "out_%s",
1334 dcerpc_default_transport_endpoint(pkt, NCACN_NP, table));
1335 dump_pdu_region(name, pkt->u.request.opnum,
1336 &p->out_data.rdata, offset1,
1337 p->out_data.rdata.length);
1340 DEBUG(5,("api_rpcTNP: called %s successfully\n",
1341 ndr_interface_name(&syntax->uuid, syntax->if_version)));
1343 /* Check for buffer underflow in rpc parsing */
1344 if ((DEBUGLEVEL >= 10) &&
1345 (pkt->frag_length < p->in_data.data.length)) {
1346 DEBUG(10, ("api_rpcTNP: rpc input buffer underflow (parse error?)\n"));
1347 dump_data(10, p->in_data.data.data + pkt->frag_length,
1348 p->in_data.data.length - pkt->frag_length);
1351 return True;
1354 /****************************************************************************
1355 Initialise an outgoing packet.
1356 ****************************************************************************/
1358 static bool pipe_init_outgoing_data(struct pipes_struct *p)
1360 output_data *o_data = &p->out_data;
1362 /* Reset the offset counters. */
1363 o_data->data_sent_length = 0;
1364 o_data->current_pdu_sent = 0;
1366 data_blob_free(&o_data->frag);
1368 /* Free any memory in the current return data buffer. */
1369 data_blob_free(&o_data->rdata);
1371 return True;
1374 /****************************************************************************
1375 Sets the fault state on incoming packets.
1376 ****************************************************************************/
1378 void set_incoming_fault(struct pipes_struct *p)
1380 data_blob_free(&p->in_data.data);
1381 p->in_data.pdu_needed_len = 0;
1382 p->in_data.pdu.length = 0;
1383 p->fault_state = DCERPC_FAULT_CANT_PERFORM;
1385 DEBUG(10, ("Setting fault state\n"));
1388 static NTSTATUS dcesrv_auth_request(struct pipe_auth_data *auth,
1389 struct ncacn_packet *pkt,
1390 DATA_BLOB *raw_pkt)
1392 NTSTATUS status;
1393 size_t hdr_size = DCERPC_REQUEST_LENGTH;
1394 size_t pad_len;
1396 DEBUG(10, ("Checking request auth.\n"));
1398 if (pkt->pfc_flags & DCERPC_PFC_FLAG_OBJECT_UUID) {
1399 hdr_size += 16;
1402 /* in case of sealing this function will unseal the data in place */
1403 status = dcerpc_check_auth(auth, pkt,
1404 &pkt->u.request.stub_and_verifier,
1405 hdr_size, raw_pkt,
1406 &pad_len);
1407 if (!NT_STATUS_IS_OK(status)) {
1408 return status;
1412 /* remove padding and auth trailer,
1413 * this way the caller will get just the data */
1414 if (pkt->auth_length) {
1415 size_t trail_len = pad_len
1416 + DCERPC_AUTH_TRAILER_LENGTH
1417 + pkt->auth_length;
1418 if (pkt->u.request.stub_and_verifier.length < trail_len) {
1419 return NT_STATUS_INFO_LENGTH_MISMATCH;
1421 pkt->u.request.stub_and_verifier.length -= trail_len;
1424 return NT_STATUS_OK;
1427 /****************************************************************************
1428 Processes a request pdu. This will do auth processing if needed, and
1429 appends the data into the complete stream if the LAST flag is not set.
1430 ****************************************************************************/
1432 static bool process_request_pdu(struct pipes_struct *p, struct ncacn_packet *pkt)
1434 NTSTATUS status;
1435 DATA_BLOB data;
1437 if (!p->pipe_bound) {
1438 DEBUG(0,("process_request_pdu: rpc request with no bind.\n"));
1439 set_incoming_fault(p);
1440 return False;
1443 /* Store the opnum */
1444 p->opnum = pkt->u.request.opnum;
1446 status = dcesrv_auth_request(&p->auth, pkt, &p->in_data.pdu);
1447 if (!NT_STATUS_IS_OK(status)) {
1448 DEBUG(0, ("Failed to check packet auth. (%s)\n",
1449 nt_errstr(status)));
1450 set_incoming_fault(p);
1451 return false;
1454 data = pkt->u.request.stub_and_verifier;
1457 * Check the data length doesn't go over the 15Mb limit.
1458 * increased after observing a bug in the Windows NT 4.0 SP6a
1459 * spoolsv.exe when the response to a GETPRINTERDRIVER2 RPC
1460 * will not fit in the initial buffer of size 0x1068 --jerry 22/01/2002
1463 if (p->in_data.data.length + data.length > MAX_RPC_DATA_SIZE) {
1464 DEBUG(0, ("process_request_pdu: "
1465 "rpc data buffer too large (%u) + (%u)\n",
1466 (unsigned int)p->in_data.data.length,
1467 (unsigned int)data.length));
1468 set_incoming_fault(p);
1469 return False;
1473 * Append the data portion into the buffer and return.
1476 if (data.length) {
1477 if (!data_blob_append(p->mem_ctx, &p->in_data.data,
1478 data.data, data.length)) {
1479 DEBUG(0, ("Unable to append data size %u "
1480 "to parse buffer of size %u.\n",
1481 (unsigned int)data.length,
1482 (unsigned int)p->in_data.data.length));
1483 set_incoming_fault(p);
1484 return False;
1488 if (pkt->pfc_flags & DCERPC_PFC_FLAG_LAST) {
1489 bool ret = False;
1491 * Ok - we finally have a complete RPC stream.
1492 * Call the rpc command to process it.
1496 * Process the complete data stream here.
1498 if (pipe_init_outgoing_data(p)) {
1499 ret = api_pipe_request(p, pkt);
1502 return ret;
1505 return True;
1508 void process_complete_pdu(struct pipes_struct *p, struct ncacn_packet *pkt)
1510 bool reply = false;
1512 /* Store the call_id */
1513 p->call_id = pkt->call_id;
1515 DEBUG(10, ("Processing packet type %u\n", (unsigned int)pkt->ptype));
1517 switch (pkt->ptype) {
1518 case DCERPC_PKT_REQUEST:
1519 reply = process_request_pdu(p, pkt);
1520 break;
1522 case DCERPC_PKT_PING: /* CL request - ignore... */
1523 DEBUG(0, ("Error - Connectionless packet type %u received\n",
1524 (unsigned int)pkt->ptype));
1525 break;
1527 case DCERPC_PKT_RESPONSE: /* No responses here. */
1528 DEBUG(0, ("Error - DCERPC_PKT_RESPONSE received from client"));
1529 break;
1531 case DCERPC_PKT_FAULT:
1532 case DCERPC_PKT_WORKING:
1533 /* CL request - reply to a ping when a call in process. */
1534 case DCERPC_PKT_NOCALL:
1535 /* CL - server reply to a ping call. */
1536 case DCERPC_PKT_REJECT:
1537 case DCERPC_PKT_ACK:
1538 case DCERPC_PKT_CL_CANCEL:
1539 case DCERPC_PKT_FACK:
1540 case DCERPC_PKT_CANCEL_ACK:
1541 DEBUG(0, ("Error - Connectionless packet type %u received\n",
1542 (unsigned int)pkt->ptype));
1543 break;
1545 case DCERPC_PKT_BIND:
1547 * We assume that a pipe bind is only in one pdu.
1549 if (pipe_init_outgoing_data(p)) {
1550 reply = api_pipe_bind_req(p, pkt);
1552 break;
1554 case DCERPC_PKT_BIND_ACK:
1555 case DCERPC_PKT_BIND_NAK:
1556 DEBUG(0, ("Error - DCERPC_PKT_BINDACK/DCERPC_PKT_BINDNACK "
1557 "packet type %u received.\n",
1558 (unsigned int)pkt->ptype));
1559 break;
1562 case DCERPC_PKT_ALTER:
1564 * We assume that a pipe bind is only in one pdu.
1566 if (pipe_init_outgoing_data(p)) {
1567 reply = api_pipe_alter_context(p, pkt);
1569 break;
1571 case DCERPC_PKT_ALTER_RESP:
1572 DEBUG(0, ("Error - DCERPC_PKT_ALTER_RESP received: "
1573 "Should only be server -> client.\n"));
1574 break;
1576 case DCERPC_PKT_AUTH3:
1578 * The third packet in an auth exchange.
1580 if (pipe_init_outgoing_data(p)) {
1581 reply = api_pipe_bind_auth3(p, pkt);
1583 break;
1585 case DCERPC_PKT_SHUTDOWN:
1586 DEBUG(0, ("Error - DCERPC_PKT_SHUTDOWN received: "
1587 "Should only be server -> client.\n"));
1588 break;
1590 case DCERPC_PKT_CO_CANCEL:
1591 /* For now just free all client data and continue
1592 * processing. */
1593 DEBUG(3,("process_complete_pdu: DCERPC_PKT_CO_CANCEL."
1594 " Abandoning rpc call.\n"));
1595 /* As we never do asynchronous RPC serving, we can
1596 * never cancel a call (as far as I know).
1597 * If we ever did we'd have to send a cancel_ack reply.
1598 * For now, just free all client data and continue
1599 * processing. */
1600 reply = True;
1601 break;
1603 #if 0
1604 /* Enable this if we're doing async rpc. */
1605 /* We must check the outstanding callid matches. */
1606 if (pipe_init_outgoing_data(p)) {
1607 /* Send a cancel_ack PDU reply. */
1608 /* We should probably check the auth-verifier here. */
1609 reply = setup_cancel_ack_reply(p, pkt);
1611 break;
1612 #endif
1614 case DCERPC_PKT_ORPHANED:
1615 /* We should probably check the auth-verifier here.
1616 * For now just free all client data and continue
1617 * processing. */
1618 DEBUG(3, ("process_complete_pdu: DCERPC_PKT_ORPHANED."
1619 " Abandoning rpc call.\n"));
1620 reply = True;
1621 break;
1623 default:
1624 DEBUG(0, ("process_complete_pdu: "
1625 "Unknown rpc type = %u received.\n",
1626 (unsigned int)pkt->ptype));
1627 break;
1630 if (!reply) {
1631 DEBUG(3,("DCE/RPC fault sent!"));
1632 set_incoming_fault(p);
1633 setup_fault_pdu(p, NT_STATUS(DCERPC_FAULT_OP_RNG_ERROR));
1635 /* pkt and p->in_data.pdu.data freed by caller */