r11950: If we got a connection oriented cancel pdu we would spin processing it.
authorJeremy Allison <jra@samba.org>
Tue, 29 Nov 2005 02:10:52 +0000 (02:10 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 16:05:39 +0000 (11:05 -0500)
Fix that, and also add in comments for all possible CL and CO PDU
types. Make sure we process them correctly.
Jeremy.
(This used to be commit 672113a627aa9060795871bc2ea3a02e696d7d7d)

source3/include/rpc_dce.h
source3/rpc_server/srv_pipe.c
source3/rpc_server/srv_pipe_hnd.c

index 3de4d2b691e71abdcb0865b5c61709d54d036549..e718d92271c70042208d1384053a24f097b829e6 100644 (file)
 /* DCE/RPC packet types */
 
 enum RPC_PKT_TYPE {
-       RPC_REQUEST = 0x00,
-       RPC_RESPONSE = 0x02,
-       RPC_FAULT    = 0x03,
-       RPC_BIND     = 0x0B,
-       RPC_BINDACK  = 0x0C,
-       RPC_BINDNACK = 0x0D,
-       RPC_ALTCONT  = 0x0E,
-       RPC_ALTCONTRESP = 0x0F,
-       RPC_AUTH3 = 0x10 /* not the real name!  this is undocumented! */
+       RPC_REQUEST  = 0x00,    /* Ordinary request. */
+       RPC_PING     = 0x01,    /* Connectionless is server alive ? */
+       RPC_RESPONSE = 0x02,    /* Ordinary reply. */
+       RPC_FAULT    = 0x03,    /* Fault in processing of call. */
+       RPC_WORKING  = 0x04,    /* Connectionless reply to a ping when server busy. */
+       RPC_NOCALL   = 0x05,    /* Connectionless reply to a ping when server has lost part of clients call. */
+       RPC_REJECT   = 0x06,    /* Refuse a request with a code. */
+       RPC_ACK      = 0x07,    /* Connectionless client to server code. */
+       RPC_CL_CANCEL= 0x08,    /* Connectionless cancel. */
+       RPC_FACK     = 0x09,    /* Connectionless fragment ack. Both client and server send. */
+       RPC_CANCEL_ACK = 0x0A,  /* Server ACK to client cancel request. */
+       RPC_BIND     = 0x0B,    /* Bind to interface. */
+       RPC_BINDACK  = 0x0C,    /* Server ack of bind. */
+       RPC_BINDNACK = 0x0D,    /* Server nack of bind. */
+       RPC_ALTCONT  = 0x0E,    /* Alter auth. */
+       RPC_ALTCONTRESP = 0x0F, /* Reply to alter auth. */
+       RPC_AUTH3    = 0x10,    /* not the real name!  this is undocumented! */
+       RPC_SHUTDOWN = 0x11,    /* Server to client request to shutdown. */
+       RPC_CO_CANCEL= 0x12,    /* Connection-oriented cancel request. */
+       RPC_ORPHANED = 0x13     /* Client telling server it's aborting a partially sent request or telling
+                                  server to stop sending replies. */
 };
 
 /* DCE/RPC flags */
index b615080d3496597fd6ed7d1df2cc50300f2894a1..8084e7673a55c6224c0688c9670afd1c741ee7ff 100644 (file)
@@ -892,6 +892,55 @@ BOOL setup_fault_pdu(pipes_struct *p, NTSTATUS status)
        return True;
 }
 
+#if 0
+/*******************************************************************
+ Marshall a cancel_ack pdu.
+ We should probably check the auth-verifier here.
+*******************************************************************/
+
+BOOL setup_cancel_ack_reply(pipes_struct *p, prs_struct *rpc_in_p)
+{
+       prs_struct outgoing_pdu;
+       RPC_HDR ack_reply_hdr;
+
+       /* Free any memory in the current return data buffer. */
+       prs_mem_free(&p->out_data.rdata);
+
+       /*
+        * Marshall directly into the outgoing PDU space. We
+        * must do this as we need to set to the bind response
+        * header and are never sending more than one PDU here.
+        */
+
+       prs_init( &outgoing_pdu, 0, p->mem_ctx, MARSHALL);
+       prs_give_memory( &outgoing_pdu, (char *)p->out_data.current_pdu, sizeof(p->out_data.current_pdu), False);
+
+       /*
+        * Initialize a cancel_ack header.
+        */
+
+       init_rpc_hdr(&ack_reply_hdr, RPC_CANCEL_ACK, RPC_FLG_FIRST | RPC_FLG_LAST,
+                       p->hdr.call_id, RPC_HEADER_LEN, 0);
+
+       /*
+        * Marshall the header into the outgoing PDU.
+        */
+
+       if(!smb_io_rpc_hdr("", &ack_reply_hdr, &outgoing_pdu, 0)) {
+               DEBUG(0,("setup_cancel_ack_reply: marshalling of RPC_HDR failed.\n"));
+               prs_mem_free(&outgoing_pdu);
+               return False;
+       }
+
+       p->out_data.data_sent_length = 0;
+       p->out_data.current_pdu_len = prs_offset(&outgoing_pdu);
+       p->out_data.current_pdu_sent = 0;
+
+       prs_mem_free(&outgoing_pdu);
+       return True;
+}
+#endif
+
 /*******************************************************************
  Ensure a bind request has the correct abstract & transfer interface.
  Used to reject unknown binds from Win2k.
index 6077faed16438cb7fb8f7d07b49b62501f4f35f7..5fb84115cc335894ea2a896ac3d9493be8c7d90d 100644 (file)
@@ -716,6 +716,32 @@ static void process_complete_pdu(pipes_struct *p)
                        (unsigned int)p->hdr.pkt_type ));
 
        switch (p->hdr.pkt_type) {
+               case RPC_REQUEST:
+                       reply = process_request_pdu(p, &rpc_in);
+                       break;
+
+               case RPC_PING: /* CL request - ignore... */
+                       DEBUG(0,("process_complete_pdu: Error. Connectionless packet type %u received on pipe %s.\n",
+                               (unsigned int)p->hdr.pkt_type, p->name));
+                       break;
+
+               case RPC_RESPONSE: /* No responses here. */
+                       DEBUG(0,("process_complete_pdu: Error. RPC_RESPONSE received from client on pipe %s.\n",
+                               p->name ));
+                       break;
+
+               case RPC_FAULT:
+               case RPC_WORKING: /* CL request - reply to a ping when a call in process. */
+               case RPC_NOCALL: /* CL - server reply to a ping call. */
+               case RPC_REJECT:
+               case RPC_ACK:
+               case RPC_CL_CANCEL:
+               case RPC_FACK:
+               case RPC_CANCEL_ACK:
+                       DEBUG(0,("process_complete_pdu: Error. Connectionless packet type %u received on pipe %s.\n",
+                               (unsigned int)p->hdr.pkt_type, p->name));
+                       break;
+
                case RPC_BIND:
                        /*
                         * We assume that a pipe bind is only in one pdu.
@@ -724,6 +750,14 @@ static void process_complete_pdu(pipes_struct *p)
                                reply = api_pipe_bind_req(p, &rpc_in);
                        }
                        break;
+
+               case RPC_BINDACK:
+               case RPC_BINDNACK:
+                       DEBUG(0,("process_complete_pdu: Error. RPC_BINDACK/RPC_BINDNACK packet type %u received on pipe %s.\n",
+                               (unsigned int)p->hdr.pkt_type, p->name));
+                       break;
+
+
                case RPC_ALTCONT:
                        /*
                         * We assume that a pipe bind is only in one pdu.
@@ -732,6 +766,12 @@ static void process_complete_pdu(pipes_struct *p)
                                reply = api_pipe_alter_context(p, &rpc_in);
                        }
                        break;
+
+               case RPC_ALTCONTRESP:
+                       DEBUG(0,("process_complete_pdu: Error. RPC_ALTCONTRESP on pipe %s: Should only be server -> client.\n",
+                               p->name));
+                       break;
+
                case RPC_AUTH3:
                        /*
                         * The third packet in an NTLMSSP auth exchange.
@@ -740,9 +780,38 @@ static void process_complete_pdu(pipes_struct *p)
                                reply = api_pipe_bind_auth3(p, &rpc_in);
                        }
                        break;
-               case RPC_REQUEST:
-                       reply = process_request_pdu(p, &rpc_in);
+
+               case RPC_SHUTDOWN:
+                       DEBUG(0,("process_complete_pdu: Error. RPC_SHUTDOWN on pipe %s: Should only be server -> client.\n",
+                               p->name));
+                       break;
+
+               case RPC_CO_CANCEL:
+                       /* For now just free all client data and continue processing. */
+                       DEBUG(3,("process_complete_pdu: RPC_ORPHANED. Abandoning rpc call.\n"));
+                       /* As we never do asynchronous RPC serving, we can never cancel a
+                          call (as far as I know). If we ever did we'd have to send a cancel_ack
+                          reply. For now, just free all client data and continue processing. */
+                       reply = True;
                        break;
+#if 0
+                       /* Enable this if we're doing async rpc. */
+                       /* We must check the call-id matches the outstanding callid. */
+                       if(pipe_init_outgoing_data(p)) {
+                               /* Send a cancel_ack PDU reply. */
+                               /* We should probably check the auth-verifier here. */
+                               reply = setup_cancel_ack_reply(p, &rpc_in);
+                       }
+                       break;
+#endif
+
+               case RPC_ORPHANED:
+                       /* We should probably check the auth-verifier here.
+                          For now just free all client data and continue processing. */
+                       DEBUG(3,("process_complete_pdu: RPC_ORPHANED. Abandoning rpc call.\n"));
+                       reply = True;
+                       break;
+
                default:
                        DEBUG(0,("process_complete_pdu: Unknown rpc type = %u received.\n", (unsigned int)p->hdr.pkt_type ));
                        break;
@@ -815,7 +884,13 @@ incoming data size = %u\n", (unsigned int)p->in_data.pdu_received_len, (unsigned
         */
 
        if(p->in_data.pdu_needed_len == 0) {
-               return unmarshall_rpc_header(p);
+               ssize_t rret = unmarshall_rpc_header(p);
+               if (rret == -1 || p->in_data.pdu_needed_len > 0) {
+                       return rret;
+               }
+               /* If rret == 0 and pdu_needed_len == 0 here we have a PDU that consists
+                  of an RPC_HEADER only. This is a RPC_SHUTDOWN, RPC_CO_CANCEL or RPC_ORPHANED
+                  pdu type. Deal with this in process_complete_pdu(). */
        }
 
        /*