/// <summary>
        /// Calling this method to be notified when a new RPC connection is coming.
        /// </summary>
        /// <param name="ifMatchFunc">Matching function.</param>
        /// <param name="timeout">Timeout of expecting a connection.</param>
        /// <param name="sessionContext">The sessionContext of binded connection.</param>
        /// <returns>If bind succeeded, return true; otherwise, false.</returns>
        private bool InternalExpectBind(
            RpcIfMatchFunc ifMatchFunc,
            TimeSpan timeout,
            ref RpceServerSessionContext sessionContext)
        {
            RpcePdu       receivedPdu = ReceiveAndReassemblePdu(timeout, ref sessionContext);
            RpceCoBindPdu bindPdu     = receivedPdu as RpceCoBindPdu;

            if (bindPdu == null)
            {
                throw new InvalidOperationException("Expect bind_pdu, but received others.");
            }

            RpcIf rpcIf = new RpcIf(sessionContext.InterfaceId, sessionContext.InterfaceMajorVersion, sessionContext.InterfaceMinorVersion);

            if (!ifMatchFunc(rpcIf))
            {
                // Interface doesn't match, response BindNak
                RpceCoBindNakPdu bindNakPdu =
                    rpceServer.CreateCoBindNakPdu(sessionContext, p_reject_reason_t.REASON_NOT_SPECIFIED, null);
                FragmentAndSendPdu(sessionContext, bindNakPdu);
                return(false);
            }

            RpceCoBindAckPdu bindAckPdu = rpceServer.CreateCoBindAckPdu(sessionContext);

            FragmentAndSendPdu(sessionContext, bindAckPdu);

            while (sessionContext.SecurityContext != null && sessionContext.SecurityContextNeedContinueProcessing)
            {
                receivedPdu = ReceiveAndReassemblePdu(timeout, ref sessionContext);
                RpceCoAlterContextPdu alterContextPdu = receivedPdu as RpceCoAlterContextPdu;
                RpceCoAuth3Pdu        auth3Pdu        = receivedPdu as RpceCoAuth3Pdu;

                if (alterContextPdu != null)
                {
                    RpceCoAlterContextRespPdu alterContextRespPdu =
                        rpceServer.CreateCoAlterContextRespPdu(sessionContext);

                    FragmentAndSendPdu(sessionContext, alterContextRespPdu);
                }
                else if (auth3Pdu != null)
                {
                    //Do nothing
                }
            }

            return(true);
        }
Exemple #2
0
        /// <summary>
        /// update context on sending RPCE CO BindAck PDU.
        /// </summary>
        /// <param name="bindAckPdu">BindAck PDU to send.</param>
        internal void UpdateContextOnSendingBindAckPdu(RpceCoBindAckPdu bindAckPdu)
        {
            this.MaxTransmitFragmentSize = bindAckPdu.max_xmit_frag;
            this.MaxReceiveFragmentSize  = bindAckPdu.max_recv_frag;
            this.AssociateGroupId        = bindAckPdu.assoc_group_id;
            if (bindAckPdu.sec_addr.port_spec != null)
            {
                this.SecondaryAddress
                    = Encoding.ASCII.GetString(bindAckPdu.sec_addr.port_spec);
            }

            if (bindAckPdu.p_result_list.p_results != null)
            {
                this.NdrVersion = RpceNdrVersion.None;
                for (int i = 0; i < bindAckPdu.p_result_list.p_results.Length; i++)
                {
                    p_result_t p_result = bindAckPdu.p_result_list.p_results[i];

                    if (p_result.result == p_cont_def_result_t.acceptance)
                    {
                        if (p_result.transfer_syntax.if_uuid == RpceUtility.NDR_INTERFACE_UUID
                            &&
                            p_result.transfer_syntax.if_vers_major == RpceUtility.NDR_INTERFACE_MAJOR_VERSION
                            &&
                            p_result.transfer_syntax.if_vers_minor == RpceUtility.NDR_INTERFACE_MINOR_VERSION)
                        {
                            this.NdrVersion |= RpceNdrVersion.NDR;
                        }
                        else if (p_result.transfer_syntax.if_uuid == RpceUtility.NDR64_INTERFACE_UUID
                                 &&
                                 p_result.transfer_syntax.if_vers_major == RpceUtility.NDR64_INTERFACE_MAJOR_VERSION
                                 &&
                                 p_result.transfer_syntax.if_vers_minor == RpceUtility.NDR64_INTERFACE_MINOR_VERSION)
                        {
                            this.NdrVersion |= RpceNdrVersion.NDR64;
                        }
                    }
                    else if (p_result.result == p_cont_def_result_t.negotiate_ack)
                    {
                        byte[] bitmask = BitConverter.GetBytes((ushort)p_result.reason);
                        this.BindTimeFeatureNegotiationBitmask = (RpceBindTimeFeatureNegotiationBitmask)bitmask[0];
                        if ((this.BindTimeFeatureNegotiationBitmask
                             & RpceBindTimeFeatureNegotiationBitmask.KeepConnectionOnOrphanSupported_Resp)
                            != 0)
                        {
                            this.BindTimeFeatureNegotiationBitmask
                                |= RpceBindTimeFeatureNegotiationBitmask.KeepConnectionOnOrphanSupported;
                        }
                    }
                }

                foreach (KeyValuePair <ushort, RpceNdrVersion> item in this.PresentationContextsTable)
                {
                    if ((this.NdrVersion & item.Value) == item.Value)
                    {
                        this.ContextIdentifier = item.Key;
                        break;
                    }
                }
            }
        }
Exemple #3
0
        /// <summary>
        /// update context on sending PDU.
        /// </summary>
        /// <param name="pdu">PDU to send.</param>
        internal void UpdateContextOnSendingPdu(RpcePdu pdu)
        {
            RpceCoPdu coPdu = pdu as RpceCoPdu;

            if (coPdu == null)
            {
                return;
            }

            this.RpcVersionMajor = coPdu.rpc_vers;
            this.RpcVersionMinor = coPdu.rpc_vers_minor;
            if (coPdu.PTYPE == RpcePacketType.Bind ||
                coPdu.PTYPE == RpcePacketType.BindAck ||
                coPdu.PTYPE == RpcePacketType.AlterContext ||
                coPdu.PTYPE == RpcePacketType.AlterContextResp)
            {
                this.SupportsHeaderSign
                    = (coPdu.pfc_flags & RpceCoPfcFlags.PFC_SUPPORT_HEADER_SIGN)
                      == RpceCoPfcFlags.PFC_SUPPORT_HEADER_SIGN;
            }

            this.SupportsConcurrentMultiplexing
                = (coPdu.pfc_flags & RpceCoPfcFlags.PFC_CONC_MPX)
                  == RpceCoPfcFlags.PFC_CONC_MPX;
            this.PackedDataRepresentationFormat = coPdu.packed_drep.dataRepFormat;

            if (coPdu.PTYPE != RpcePacketType.Request)
            {
                this.outstandingCalls.Remove(coPdu.call_id);
            }

            switch (coPdu.PTYPE)
            {
            case RpcePacketType.BindAck:
                RpceCoBindAckPdu bindAckPdu = coPdu as RpceCoBindAckPdu;
                if (bindAckPdu != null)
                {
                    UpdateContextOnSendingBindAckPdu(bindAckPdu);
                }
                break;

            case RpcePacketType.Request:
                RpceCoRequestPdu requestPdu = coPdu as RpceCoRequestPdu;
                if (requestPdu != null)
                {
                    this.ContextIdentifier = requestPdu.p_cont_id;
                }
                break;

            case RpcePacketType.Response:
                RpceCoResponsePdu responsePdu = coPdu as RpceCoResponsePdu;
                if (responsePdu != null)
                {
                    this.ContextIdentifier = responsePdu.p_cont_id;
                }
                break;

            case RpcePacketType.BindNak:
            case RpcePacketType.AlterContextResp:
            case RpcePacketType.Fault:
            case RpcePacketType.Shutdown:
            default:
                //default situation should do nothing.
                //This is just update the context, if we cannot recognize the PDU, ignore it.
                break;
            }
        }
Exemple #4
0
        public static RpceCoPdu DecodeCoPdu(
            RpceContext context,
            byte[] pduBytes)
        {
            if (context == null)
            {
                throw new ArgumentNullException("context");
            }

            if (pduBytes == null)
            {
                throw new ArgumentNullException("pduBytes");
            }

            RpceCoPdu pdu;

            //#2 byte is PTYPE
            RpcePacketType packageType = (RpcePacketType)pduBytes[2];
            //#3 byte is PFC_*** flags
            RpceCoPfcFlags pfcFlags = (RpceCoPfcFlags)pduBytes[3];

            RpceCoPfcFlags pfcFlagsNoFragment = RpceCoPfcFlags.PFC_FIRST_FRAG | RpceCoPfcFlags.PFC_LAST_FRAG;

            if (((pfcFlags & pfcFlagsNoFragment) != pfcFlagsNoFragment) &&
                (packageType == RpcePacketType.Bind ||
                 packageType == RpcePacketType.BindAck ||
                 packageType == RpcePacketType.AlterContext ||
                 packageType == RpcePacketType.AlterContextResp ||
                 packageType == RpcePacketType.Auth3))
            {
                //If it's a fragment and PTYPE is bind/bind_ack/alter_context/alter_context_resp
                //Windows RPC support version 5.0 only.
                //Bind fragment requires RPC ver 5.1.
                //We don't support it.
                throw new NotSupportedException("bind/bind_ack/alt_context/alt_context_resp/auth3 PDU fragment are not supported.");
            }
            else
            {
                switch (packageType)
                {
                case RpcePacketType.Bind:
                    pdu = new RpceCoBindPdu(context, pduBytes);
                    break;

                case RpcePacketType.BindAck:
                    pdu = new RpceCoBindAckPdu(context, pduBytes);
                    break;

                case RpcePacketType.BindNak:
                    pdu = new RpceCoBindNakPdu(context, pduBytes);
                    break;

                case RpcePacketType.AlterContext:
                    pdu = new RpceCoAlterContextPdu(context, pduBytes);
                    break;

                case RpcePacketType.AlterContextResp:
                    pdu = new RpceCoAlterContextRespPdu(context, pduBytes);
                    break;

                case RpcePacketType.Auth3:
                    pdu = new RpceCoAuth3Pdu(context, pduBytes);
                    break;

                case RpcePacketType.Request:
                    pdu = new RpceCoRequestPdu(context, pduBytes);
                    break;

                case RpcePacketType.Response:
                    pdu = new RpceCoResponsePdu(context, pduBytes);
                    break;

                case RpcePacketType.Fault:
                    pdu = new RpceCoFaultPdu(context, pduBytes);
                    break;

                case RpcePacketType.CoCancel:
                    pdu = new RpceCoCancelPdu(context, pduBytes);
                    break;

                case RpcePacketType.Orphaned:
                    pdu = new RpceCoOrphanedPdu(context, pduBytes);
                    break;

                case RpcePacketType.Shutdown:
                    pdu = new RpceCoShutdownPdu(context, pduBytes);
                    break;

                default:
                    throw new InvalidOperationException(
                              string.Format("Receive invalid packet - {0}.", packageType));
                }
            }

            return(pdu);
        }
        public RpceCoBindAckPdu CreateCoBindAckPdu(
            RpceServerSessionContext sessionContext)
        {
            if (sessionContext == null)
            {
                throw new ArgumentNullException("sessionContext");
            }

            RpceCoBindAckPdu bindAckPdu = new RpceCoBindAckPdu(sessionContext);

            float serverRpcVersion
                = (float)sessionContext.ServerContext.RpcVersionMajor
                + (float)sessionContext.ServerContext.RpcVersionMinor / 10.0f;
            float proposedRpcVersion
                = (float)sessionContext.RpcVersionMajor
                + (float)sessionContext.RpcVersionMinor / 10.0f;
            float rpcVersion = Math.Min(serverRpcVersion, proposedRpcVersion);

            bindAckPdu.rpc_vers = (byte)Math.Truncate(rpcVersion);
            bindAckPdu.rpc_vers_minor = (byte)((rpcVersion - Math.Truncate(rpcVersion)) * 10.0f);
            bindAckPdu.PTYPE = RpcePacketType.BindAck;
            bindAckPdu.pfc_flags = RpceUtility.GeneratePfcFlags(sessionContext, RpcePacketType.BindAck);
            bindAckPdu.packed_drep.dataRepFormat = sessionContext.PackedDataRepresentationFormat;
            bindAckPdu.packed_drep.reserved = 0;
            bindAckPdu.call_id = sessionContext.CurrentCallId;

            bindAckPdu.max_xmit_frag = sessionContext.MaxTransmitFragmentSize;
            bindAckPdu.max_recv_frag = sessionContext.MaxReceiveFragmentSize;
            bindAckPdu.assoc_group_id = sessionContext.AssociateGroupId;
            if (sessionContext.SecondaryAddress == null)
            {
                bindAckPdu.sec_addr.port_spec = new byte[0];
            }
            else
            {
                bindAckPdu.sec_addr.port_spec = Encoding.ASCII.GetBytes(sessionContext.SecondaryAddress);
            }
            bindAckPdu.sec_addr.length = (ushort)bindAckPdu.sec_addr.port_spec.Length;

            int sizeOfSecAddr = bindAckPdu.sec_addr.length + Marshal.SizeOf(bindAckPdu.sec_addr.length);
            bindAckPdu.pad2 = new byte[RpceUtility.Align(sizeOfSecAddr, 4) - sizeOfSecAddr];

            RpceNdrVersion ndrVersion = sessionContext.ServerContext.NdrVersion;
            List<p_result_t> presentationResultList = new List<p_result_t>();
            for (int i = 0; i < sessionContext.PresentationContextsTable.Count; i++)
            {
                p_result_t pResult = new p_result_t();
                RpceNdrVersion proposedNdrVersion = sessionContext.PresentationContextsTable.Values[i];
                if ((proposedNdrVersion & ndrVersion) != 0)
                {
                    pResult.result = p_cont_def_result_t.acceptance;
                    // donot accept any more NDR version.
                    ndrVersion = RpceNdrVersion.None;
                }
                else
                {
                    pResult.result = p_cont_def_result_t.provider_rejection;
                }
                pResult.reason = p_provider_reason_t.reason_not_specified;
                if (proposedNdrVersion == RpceNdrVersion.NDR)
                {
                    pResult.transfer_syntax.if_uuid = RpceUtility.NDR_INTERFACE_UUID;
                    pResult.transfer_syntax.if_vers_major = RpceUtility.NDR_INTERFACE_MAJOR_VERSION;
                    pResult.transfer_syntax.if_vers_minor = RpceUtility.NDR_INTERFACE_MINOR_VERSION;
                }
                else if (proposedNdrVersion == RpceNdrVersion.NDR64)
                {
                    pResult.transfer_syntax.if_uuid = RpceUtility.NDR64_INTERFACE_UUID;
                    pResult.transfer_syntax.if_vers_major = RpceUtility.NDR64_INTERFACE_MAJOR_VERSION;
                    pResult.transfer_syntax.if_vers_minor = RpceUtility.NDR64_INTERFACE_MINOR_VERSION;
                }
                presentationResultList.Add(pResult);
            }
            if (sessionContext.BindTimeFeatureNegotiationBitmask != RpceBindTimeFeatureNegotiationBitmask.None)
            {
                RpceBindTimeFeatureNegotiationBitmask bindTimeFeatureNegotiationBitmask
                    = sessionContext.BindTimeFeatureNegotiationBitmask;
                if ((bindTimeFeatureNegotiationBitmask
                    & RpceBindTimeFeatureNegotiationBitmask.KeepConnectionOnOrphanSupported)
                    != 0)
                {
                    bindTimeFeatureNegotiationBitmask
                        |= RpceBindTimeFeatureNegotiationBitmask.KeepConnectionOnOrphanSupported_Resp;
                }
                bindTimeFeatureNegotiationBitmask
                    &= (sessionContext.ServerContext.SupportsSecurityContextMultiplexing
                        ? RpceBindTimeFeatureNegotiationBitmask.SecurityContextMultiplexingSupported
                        : RpceBindTimeFeatureNegotiationBitmask.None)
                        |
                       (sessionContext.ServerContext.SupportsKeepConnectionOnOrphan
                        ? RpceBindTimeFeatureNegotiationBitmask.KeepConnectionOnOrphanSupported_Resp
                        : RpceBindTimeFeatureNegotiationBitmask.None);

                p_result_t pResult = new p_result_t();
                pResult.result = p_cont_def_result_t.negotiate_ack;
                pResult.reason = (p_provider_reason_t)bindTimeFeatureNegotiationBitmask;
                presentationResultList.Add(pResult);
            }

            bindAckPdu.p_result_list.n_results = (byte)presentationResultList.Count;
            bindAckPdu.p_result_list.p_results = presentationResultList.ToArray();

            bindAckPdu.AppendAuthenticationVerifier();
            bindAckPdu.SetLength();

            return bindAckPdu;
        }
        /// <summary>
        /// update context on receiving RPCE CO BindAck PDU
        /// </summary>
        /// <param name="bindAckPdu">BindAck PDU</param>
        private void UpdateContextOnReceivingBindAckPdu(RpceCoBindAckPdu bindAckPdu)
        {
            context.MaxTransmitFragmentSize = bindAckPdu.max_xmit_frag;
            context.MaxReceiveFragmentSize = bindAckPdu.max_recv_frag;
            context.AssociateGroupId = bindAckPdu.assoc_group_id;
            if (bindAckPdu.sec_addr.port_spec != null)
            {
                context.SecondaryAddress
                    = Encoding.ASCII.GetString(bindAckPdu.sec_addr.port_spec);
            }

            if (bindAckPdu.p_result_list.p_results != null)
            {
                context.NdrVersion = RpceNdrVersion.None;
                for (int i = 0; i < bindAckPdu.p_result_list.p_results.Length; i++)
                {
                    if (bindAckPdu.p_result_list.p_results[i].result
                        == p_cont_def_result_t.acceptance)
                    {
                        if (bindAckPdu.p_result_list.p_results[i].transfer_syntax.if_uuid
                                == RpceUtility.NDR_INTERFACE_UUID
                            &&
                            bindAckPdu.p_result_list.p_results[i].transfer_syntax.if_vers_major
                                == RpceUtility.NDR_INTERFACE_MAJOR_VERSION
                            &&
                            bindAckPdu.p_result_list.p_results[i].transfer_syntax.if_vers_minor
                                == RpceUtility.NDR_INTERFACE_MINOR_VERSION)
                        {
                            context.NdrVersion |= RpceNdrVersion.NDR;
                        }
                        else if (bindAckPdu.p_result_list.p_results[i].transfer_syntax.if_uuid
                                == RpceUtility.NDR64_INTERFACE_UUID
                            &&
                            bindAckPdu.p_result_list.p_results[i].transfer_syntax.if_vers_major
                                == RpceUtility.NDR64_INTERFACE_MAJOR_VERSION
                            &&
                            bindAckPdu.p_result_list.p_results[i].transfer_syntax.if_vers_minor
                                == RpceUtility.NDR64_INTERFACE_MINOR_VERSION)
                        {
                            context.NdrVersion |= RpceNdrVersion.NDR64;
                        }
                    }
                    else if (bindAckPdu.p_result_list.p_results[i].result
                        == p_cont_def_result_t.negotiate_ack)
                    {
                        byte[] bitmask = BitConverter.GetBytes(
                            (ushort)bindAckPdu.p_result_list.p_results[i].reason);
                        context.BindTimeFeatureNegotiationBitmask
                            = (RpceBindTimeFeatureNegotiationBitmask)bitmask[0];
                    }
                }
                foreach (KeyValuePair<ushort, RpceNdrVersion> item in
                    context.PresentationContextsTable)
                {
                    if ((context.NdrVersion & item.Value) == item.Value)
                    {
                        context.ContextIdentifier = item.Key;
                        break;
                    }
                }
            }
        }