/// <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);
        }
Exemplo n.º 2
0
        /// <summary>
        /// Connect and bind to a RPCE remote host.
        /// </summary>
        /// <param name="protocolSequence">
        /// A protocol sequence.<para/>
        /// Support ncacn_ip_tcp and ncacn_np only.
        /// </param>
        /// <param name="networkAddress">
        /// A network address of RPCE remote host.
        /// </param>
        /// <param name="endpoint">
        /// An endpoint that its format and content
        /// are associated with the protocol sequence.
        /// </param>
        /// <param name="transportCredential">
        /// If connect by SMB/SMB2, it's the security credential
        /// used by underlayer transport (SMB/SMB2).
        /// If connect by TCP, this parameter is ignored.
        /// </param>
        /// <param name="interfaceId">
        /// A Guid of interface_id that is binding to.
        /// </param>
        /// <param name="interfaceMajorVersion">
        /// interface_major_ver that is binding to.
        /// </param>
        /// <param name="interfaceMinorVersion">
        /// interface_minor_ver that is binding to.
        /// </param>
        /// <param name="securityContext">
        /// A security provider. If setting to null, indicate the default authentication type NTLM is selected.
        /// </param>
        /// <param name="connectSecurityContext">
        /// A security provider for connect authentication. If setting to null, indicate the default authentication type NTLM is selected.
        /// </param>
        /// <param name="authenticationLevel">
        /// An authentication level.
        /// </param>
        /// <param name="supportsHeaderSign">
        /// Indicates whether client supports header sign or not.
        /// </param>
        /// <param name="timeout">
        /// Timeout period.
        /// </param>
        /// <exception cref="ArgumentNullException">
        /// Thrown when protSeq, networkAddr or endpoint is null.
        /// </exception>
        /// <exception cref="InvalidOperationException">
        /// Thrown when receive error from server.
        /// </exception>
        public virtual void Bind(
            string protocolSequence,
            string networkAddress,
            string endpoint,
            AccountCredential transportCredential,
            Guid interfaceId,
            ushort interfaceMajorVersion,
            ushort interfaceMinorVersion,
            ClientSecurityContext securityContext,
            ClientSecurityContext connectSecurityContext,
            RpceAuthenticationLevel authenticationLevel,
            bool supportsHeaderSign,
            TimeSpan timeout)
        {
            if (protocolSequence == null)
            {
                throw new ArgumentNullException("protocolSequence");
            }
            if (networkAddress == null)
            {
                throw new ArgumentNullException("networkAddress");
            }
            if (endpoint == null)
            {
                throw new ArgumentNullException("endpoint");
            }

            // RPC over named-pipe does not support asynchronous call in this library.
            // http://msdn.microsoft.com/en-us/library/windows/desktop/aa373551(v=vs.85).aspx
            rpceClient.Context.IsAsynchronous = (string.Compare(protocolSequence, RpceUtility.RPC_OVER_NAMED_PIPE_PROTOCOL_SEQUENCE, true) != 0);

            rpceClient.Connect(protocolSequence, networkAddress, endpoint, transportCredential, timeout,
                               connectSecurityContext == null ? SecurityPackageType.Ntlm : connectSecurityContext.PackageType);

            rpceClient.SetAuthInfo(securityContext, authenticationLevel, rpceClient.Context.AuthenticationContextId);

            RpceCoBindPdu bindPdu = rpceClient.CreateCoBindPdu(
                //read from context, donot hardcode.
                rpceClient.Context.RpcVersionMinor,         // default is rpc vers 5.0
                supportsHeaderSign ? RpceCoPfcFlags.PFC_SUPPORT_HEADER_SIGN : RpceCoPfcFlags.None,
                rpceClient.ComputeNextCallId(),             // call id, default is 1
                rpceClient.Context.MaxTransmitFragmentSize, // max xmit frag
                rpceClient.Context.MaxReceiveFragmentSize,  // max recv frag
                rpceClient.Context.AssociateGroupId,        // assoc group id, default 0
                interfaceId,
                interfaceMajorVersion,
                interfaceMinorVersion,
                rpceClient.Context.NdrVersion,                                                                       // default is NDR
                (rpceClient.Context.BindTimeFeatureNegotiationBitmask != RpceBindTimeFeatureNegotiationBitmask.None) // default is None
                    ? (RpceBindTimeFeatureNegotiationBitmask?)rpceClient.Context.BindTimeFeatureNegotiationBitmask
                    : null);

            FragmentAndSendPdu(bindPdu);

            RpcePdu receivedPdu = ReceiveAndReassemblePdu(timeout);

            if (receivedPdu is RpceCoBindAckPdu)
            {
                if (rpceClient.Context.NdrVersion == RpceNdrVersion.None)
                {
                    throw new InvalidOperationException("Neither NDR nor NDR64 is supported.");
                }
            }
            else
            {
                RpceCoBindNakPdu bindNakPdu = receivedPdu as RpceCoBindNakPdu;
                if (bindNakPdu != null)
                {
                    throw new InvalidOperationException(bindNakPdu.provider_reject_reason.ToString());
                }
                else
                {
                    throw new InvalidOperationException(
                              string.Format("Unexpected packet type received - {0}.",
                                            receivedPdu.GetType().Name));
                }
            }

            while (rpceClient.Context.SecurityContext != null &&
                   rpceClient.Context.SecurityContext.NeedContinueProcessing)
            {
                RpceCoAlterContextPdu alterContextPdu = rpceClient.CreateCoAlterContextPdu();
                FragmentAndSendPdu(alterContextPdu);
                receivedPdu = ReceiveAndReassemblePdu(timeout);

                RpceCoFaultPdu faultPdu = receivedPdu as RpceCoFaultPdu;
                if (faultPdu != null)
                {
                    throw new InvalidOperationException(faultPdu.status.ToString());
                }

                if (!(receivedPdu is RpceCoAlterContextRespPdu))
                {
                    throw new InvalidOperationException("Expect alter_context_pdu, but received others.");
                }
            }

            if (rpceClient.Context.SecurityContext != null &&
                rpceClient.Context.SecurityContext.Token != null &&
                rpceClient.Context.SecurityContext.Token.Length != 0)
            {
                RpceCoAuth3Pdu auth3Pdu = rpceClient.CreateCoAuth3Pdu();
                FragmentAndSendPdu(auth3Pdu);
                // no expected response from server
                rpceClient.Context.OutstandingCalls.Remove(auth3Pdu.call_id);
            }

            if (rpceClient.Context.IsAsynchronous)
            {
                // Start the receiving thread to receive the response from server.
                cancellationToken = new CancellationTokenSource();
                receiveTask       = new Task(EventLoop, cancellationToken.Token); //new Thread(new ThreadStart(EventLoop));
                //receiveThread.IsBackground = true;
                receiveTask.Start();
            }
        }
Exemplo n.º 3
0
        /// <summary>
        /// update context on receiving RPCE CO Bind PDU.
        /// </summary>
        /// <param name="bindPdu">Bind PDU to receive.</param>
        internal void UpdateContextOnReceivingBindPdu(RpceCoBindPdu bindPdu)
        {
            this.MaxTransmitFragmentSize = bindPdu.max_xmit_frag;
            this.MaxReceiveFragmentSize  = bindPdu.max_recv_frag;

            if (bindPdu.assoc_group_id != 0)
            {
                this.AssociateGroupId = bindPdu.assoc_group_id;
            }
            else
            {
                if (this.associateGroupIdList.Count == 0)
                {
                    this.AssociateGroupId = bindPdu.assoc_group_id + 1;
                }
                else
                {
                    this.associateGroupIdList.Sort();
                    this.AssociateGroupId = this.associateGroupIdList[this.associateGroupIdList.Count - 1] + 1;
                }
            }

            associateGroupIdList.Add(this.AssociateGroupId);

            if (bindPdu.p_context_elem.p_cont_elem != null &&
                bindPdu.p_context_elem.p_cont_elem.Length > 0)
            {
                this.InterfaceId
                    = bindPdu.p_context_elem.p_cont_elem[0].abstract_syntax.if_uuid;
                this.InterfaceMajorVersion
                    = bindPdu.p_context_elem.p_cont_elem[0].abstract_syntax.if_vers_major;
                this.InterfaceMinorVersion
                    = bindPdu.p_context_elem.p_cont_elem[0].abstract_syntax.if_vers_minor;

                this.NdrVersion = RpceNdrVersion.None;
                this.PresentationContextsTable.Clear();
                for (int i = 0; i < bindPdu.p_context_elem.p_cont_elem.Length; i++)
                {
                    p_cont_elem_t p_cont_elem = bindPdu.p_context_elem.p_cont_elem[i];

                    if (p_cont_elem.transfer_syntaxes == null)
                    {
                        continue;
                    }
                    for (int j = 0; j < p_cont_elem.transfer_syntaxes.Length; j++)
                    {
                        p_syntax_id_t transfer_syntax = p_cont_elem.transfer_syntaxes[j];

                        if (transfer_syntax.if_uuid == RpceUtility.NDR_INTERFACE_UUID
                            &&
                            transfer_syntax.if_vers_major == RpceUtility.NDR_INTERFACE_MAJOR_VERSION
                            &&
                            transfer_syntax.if_vers_minor == RpceUtility.NDR_INTERFACE_MINOR_VERSION)
                        {
                            this.NdrVersion |= RpceNdrVersion.NDR;
                            this.PresentationContextsTable.Add(p_cont_elem.p_cont_id, RpceNdrVersion.NDR);
                        }
                        else if (transfer_syntax.if_uuid == RpceUtility.NDR64_INTERFACE_UUID
                                 &&
                                 transfer_syntax.if_vers_major == RpceUtility.NDR64_INTERFACE_MAJOR_VERSION
                                 &&
                                 transfer_syntax.if_vers_minor == RpceUtility.NDR64_INTERFACE_MINOR_VERSION)
                        {
                            this.NdrVersion |= RpceNdrVersion.NDR64;
                            this.PresentationContextsTable.Add(p_cont_elem.p_cont_id, RpceNdrVersion.NDR64);
                        }
                        else
                        {
                            byte[] uuid = transfer_syntax.if_uuid.ToByteArray();
                            if (ArrayUtility.CompareArrays(
                                    ArrayUtility.SubArray(
                                        uuid,
                                        0,
                                        RpceUtility.BIND_TIME_FEATURE_NEGOTIATION_BITMASK_PREFIX_LENGTH),
                                    ArrayUtility.SubArray(
                                        RpceUtility.BIND_TIME_FEATURE_NEGOTIATION_BITMASK_GUID_BYTES,
                                        0,
                                        RpceUtility.BIND_TIME_FEATURE_NEGOTIATION_BITMASK_PREFIX_LENGTH))
                                &&
                                transfer_syntax.if_vers_major == 1
                                &&
                                transfer_syntax.if_vers_minor == 0)
                            {
                                this.BindTimeFeatureNegotiationBitmask = (RpceBindTimeFeatureNegotiationBitmask)
                                                                         uuid[RpceUtility.BIND_TIME_FEATURE_NEGOTIATION_BITMASK_PREFIX_LENGTH];
                            }
                        }
                    }
                }
            }
        }
Exemplo n.º 4
0
        /// <summary>
        /// update context on receiving PDU.
        /// </summary>
        /// <param name="pdu">PDU to receive.</param>
        /// <exception cref="ArgumentNullException">Thrown when pdu is null.</exception>
        internal void UpdateContextOnReceivingPdu(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)
            {
                //TDI:
                //TD said PFC_SUPPORT_HEADER_SIGN is meanful in Bind and AltContext.
                //But when using Kerberos, AltContext doesn't have this flag,
                //if server or client read this flag according to AltContext, Sign/Encrypt will fail.
                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;
            this.CurrentCallId = coPdu.call_id;
            if (coPdu.PTYPE != RpcePacketType.Response && coPdu.PTYPE != RpcePacketType.Auth3)
            {
                this.outstandingCalls.Add(coPdu.call_id);
            }

            switch (coPdu.PTYPE)
            {
            case RpcePacketType.Bind:
                RpceCoBindPdu bindPdu = coPdu as RpceCoBindPdu;
                if (bindPdu != null)
                {
                    UpdateContextOnReceivingBindPdu(bindPdu);
                }
                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.Auth3:
            case RpcePacketType.AlterContext:
            case RpcePacketType.CoCancel:
            case RpcePacketType.Orphaned:
            default:
                //default situation should do nothing.
                //This is just update the context, if we cannot recognize the PDU, ignore it.
                break;
            }

            this.SecurityContextNeedContinueProcessing = coPdu.securityContextNeedContinueProcessing;
        }
Exemplo n.º 5
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);
        }
        /// <summary>
        /// Create an RpceCoBindPdu.
        /// </summary>
        /// <param name="rpcVersionMinor">
        /// RPC version minor.
        /// </param>
        /// <param name="pfcFlags">
        /// PFC_*** flags.
        /// </param>
        /// <param name="callId">
        /// Call Id.
        /// </param>
        /// <param name="maxTransmitFragmentSize">
        /// Max transmit fragment size, in bytes.
        /// </param>
        /// <param name="maxReceiveFragmentSize">
        /// Max receive fragment size, in bytes.
        /// </param>
        /// <param name="associateGroupId">
        /// Associated group id.
        /// </param>
        /// <param name="interfaceId">
        /// A Guid of interface_id that is binding to.
        /// </param>
        /// <param name="interfaceMajorVersion">
        /// interface_major_ver that is binding to.
        /// </param>
        /// <param name="interfaceMinorVersion">
        /// interface_minor_ver that is binding to.
        /// </param>
        /// <param name="ndrVersion">
        /// NDR version to be used to marshal/un-marshal stub.
        /// </param>
        /// <param name="bindTimeFeatureNegotiationBitmask">
        /// BindTimeFeatureNegotiationBitmask to sent. 
        /// Set the value to null if client donot support the feature.
        /// </param>
        /// <returns>
        /// Created RpceCoBindPdu, it's ok to be sent out if there's 
        /// no modification to any field of the PDU.
        /// </returns>
        public RpceCoBindPdu CreateCoBindPdu(
            byte rpcVersionMinor,
            RpceCoPfcFlags pfcFlags,
            uint callId,
            ushort maxTransmitFragmentSize,
            ushort maxReceiveFragmentSize,
            uint associateGroupId,
            Guid interfaceId,
            ushort interfaceMajorVersion,
            ushort interfaceMinorVersion,
            RpceNdrVersion ndrVersion,
            RpceBindTimeFeatureNegotiationBitmask? bindTimeFeatureNegotiationBitmask)
        {
            RpceCoBindPdu bindPdu = new RpceCoBindPdu(context);

            bindPdu.rpc_vers = 5;
            bindPdu.rpc_vers_minor = rpcVersionMinor;
            bindPdu.PTYPE = RpcePacketType.Bind;
            bindPdu.pfc_flags = pfcFlags
                | RpceCoPfcFlags.PFC_FIRST_FRAG
                | RpceCoPfcFlags.PFC_LAST_FRAG;
            bindPdu.packed_drep.dataRepFormat = RpceDataRepresentationFormat.IEEE_LittleEndian_ASCII;
            bindPdu.packed_drep.reserved = 0;
            bindPdu.call_id = callId;

            bindPdu.max_xmit_frag = maxTransmitFragmentSize;
            bindPdu.max_recv_frag = maxReceiveFragmentSize;
            bindPdu.assoc_group_id = associateGroupId;

            List<p_cont_elem_t> p_cont_elem_list = new List<p_cont_elem_t>();
            if ((ndrVersion & RpceNdrVersion.NDR) == RpceNdrVersion.NDR)
            {
                p_cont_elem_t p_cont_elem;
                p_cont_elem.p_cont_id = (ushort)(p_cont_elem_list.Count);
                p_cont_elem.n_transfer_syn = 1;
                p_cont_elem.reserved = 0;
                p_cont_elem.abstract_syntax.if_uuid = interfaceId;
                p_cont_elem.abstract_syntax.if_vers_major = interfaceMajorVersion;
                p_cont_elem.abstract_syntax.if_vers_minor = interfaceMinorVersion;
                p_cont_elem.transfer_syntaxes = new p_syntax_id_t[1];
                p_cont_elem.transfer_syntaxes[0].if_uuid
                    = RpceUtility.NDR_INTERFACE_UUID;
                p_cont_elem.transfer_syntaxes[0].if_vers_major
                    = RpceUtility.NDR_INTERFACE_MAJOR_VERSION;
                p_cont_elem.transfer_syntaxes[0].if_vers_minor
                    = RpceUtility.NDR_INTERFACE_MINOR_VERSION;
                p_cont_elem_list.Add(p_cont_elem);
            }
            if ((ndrVersion & RpceNdrVersion.NDR64) == RpceNdrVersion.NDR64)
            {
                p_cont_elem_t p_cont_elem;
                p_cont_elem.p_cont_id = (ushort)(p_cont_elem_list.Count);
                p_cont_elem.n_transfer_syn = 1;
                p_cont_elem.reserved = 0;
                p_cont_elem.abstract_syntax.if_uuid = interfaceId;
                p_cont_elem.abstract_syntax.if_vers_major = interfaceMajorVersion;
                p_cont_elem.abstract_syntax.if_vers_minor = interfaceMinorVersion;
                p_cont_elem.transfer_syntaxes = new p_syntax_id_t[1];
                p_cont_elem.transfer_syntaxes[0].if_uuid
                    = RpceUtility.NDR64_INTERFACE_UUID;
                p_cont_elem.transfer_syntaxes[0].if_vers_major
                    = RpceUtility.NDR64_INTERFACE_MAJOR_VERSION;
                p_cont_elem.transfer_syntaxes[0].if_vers_minor
                    = RpceUtility.NDR64_INTERFACE_MINOR_VERSION;
                p_cont_elem_list.Add(p_cont_elem);
            }
            if (bindTimeFeatureNegotiationBitmask != null)
            {
                p_cont_elem_t p_cont_elem;
                p_cont_elem.p_cont_id = (ushort)(p_cont_elem_list.Count);
                p_cont_elem.n_transfer_syn = 1;
                p_cont_elem.reserved = 0;
                p_cont_elem.abstract_syntax.if_uuid = interfaceId;
                p_cont_elem.abstract_syntax.if_vers_major = interfaceMajorVersion;
                p_cont_elem.abstract_syntax.if_vers_minor = interfaceMinorVersion;
                p_cont_elem.transfer_syntaxes = new p_syntax_id_t[1];
                byte[] guidBytes = new byte[RpceUtility.GUID_SIZE]; // length of a Guid
                Buffer.BlockCopy(
                    RpceUtility.BIND_TIME_FEATURE_NEGOTIATION_BITMASK_GUID_BYTES,
                    0,
                    guidBytes,
                    0,
                    RpceUtility.GUID_SIZE);
                guidBytes[RpceUtility.BIND_TIME_FEATURE_NEGOTIATION_BITMASK_PREFIX_LENGTH]
                    = (byte)bindTimeFeatureNegotiationBitmask.Value;
                p_cont_elem.transfer_syntaxes[0].if_uuid = new Guid(guidBytes);
                p_cont_elem.transfer_syntaxes[0].if_vers_major = 1;
                p_cont_elem.transfer_syntaxes[0].if_vers_minor = 0;
                p_cont_elem_list.Add(p_cont_elem);
            }
            bindPdu.p_context_elem.n_context_elem = (byte)p_cont_elem_list.Count;
            bindPdu.p_context_elem.reserved = 0;
            bindPdu.p_context_elem.reserved2 = 0;
            bindPdu.p_context_elem.p_cont_elem = p_cont_elem_list.ToArray();

            bindPdu.AppendAuthenticationVerifier();
            bindPdu.SetLength();

            return bindPdu;
        }
        /// <summary>
        /// update context on sending RPCE CO Bind PDU
        /// </summary>
        /// <param name="bindPdu">Bind PDU</param>
        private void UpdateContextOnSendingBindPdu(RpceCoBindPdu bindPdu)
        {
            context.MaxTransmitFragmentSize = bindPdu.max_xmit_frag;
            context.MaxReceiveFragmentSize = bindPdu.max_recv_frag;
            context.AssociateGroupId = bindPdu.assoc_group_id;
            if (bindPdu.p_context_elem.p_cont_elem != null &&
                bindPdu.p_context_elem.p_cont_elem.Length > 0)
            {
                context.InterfaceId
                    = bindPdu.p_context_elem.p_cont_elem[0].abstract_syntax.if_uuid;
                context.InterfaceMajorVersion
                    = bindPdu.p_context_elem.p_cont_elem[0].abstract_syntax.if_vers_major;
                context.InterfaceMinorVersion
                    = bindPdu.p_context_elem.p_cont_elem[0].abstract_syntax.if_vers_minor;

                context.NdrVersion = RpceNdrVersion.None;
                context.PresentationContextsTable.Clear();
                for (int i = 0; i < bindPdu.p_context_elem.p_cont_elem.Length; i++)
                {
                    if (bindPdu.p_context_elem.p_cont_elem[i].transfer_syntaxes == null)
                    {
                        continue;
                    }
                    for (int j = 0;
                        j < bindPdu.p_context_elem.p_cont_elem[i].transfer_syntaxes.Length;
                        j++)
                    {
                        if (bindPdu.p_context_elem.p_cont_elem[i].transfer_syntaxes[j].if_uuid
                                == RpceUtility.NDR_INTERFACE_UUID
                            &&
                            bindPdu.p_context_elem.p_cont_elem[i].transfer_syntaxes[j].if_vers_major
                                == RpceUtility.NDR_INTERFACE_MAJOR_VERSION
                            &&
                            bindPdu.p_context_elem.p_cont_elem[i].transfer_syntaxes[j].if_vers_minor
                                == RpceUtility.NDR_INTERFACE_MINOR_VERSION)
                        {
                            context.NdrVersion |= RpceNdrVersion.NDR;
                            context.PresentationContextsTable.Add(
                                bindPdu.p_context_elem.p_cont_elem[i].p_cont_id,
                                RpceNdrVersion.NDR);
                        }
                        else if (bindPdu.p_context_elem.p_cont_elem[i].transfer_syntaxes[j].if_uuid
                                == RpceUtility.NDR64_INTERFACE_UUID
                            &&
                            bindPdu.p_context_elem.p_cont_elem[i].transfer_syntaxes[j].if_vers_major
                                == RpceUtility.NDR64_INTERFACE_MAJOR_VERSION
                            &&
                            bindPdu.p_context_elem.p_cont_elem[i].transfer_syntaxes[j].if_vers_minor
                                == RpceUtility.NDR64_INTERFACE_MINOR_VERSION)
                        {
                            context.NdrVersion |= RpceNdrVersion.NDR64;
                            context.PresentationContextsTable.Add(
                                bindPdu.p_context_elem.p_cont_elem[i].p_cont_id,
                                RpceNdrVersion.NDR64);
                        }
                        else
                        {
                            byte[] uuid
                                = bindPdu.p_context_elem.p_cont_elem[i].transfer_syntaxes[j].if_uuid.ToByteArray();
                            if (ArrayUtility.CompareArrays(
                                    ArrayUtility.SubArray(
                                        uuid,
                                        0,
                                        RpceUtility.BIND_TIME_FEATURE_NEGOTIATION_BITMASK_PREFIX_LENGTH),
                                    ArrayUtility.SubArray(
                                        RpceUtility.BIND_TIME_FEATURE_NEGOTIATION_BITMASK_GUID_BYTES,
                                        0,
                                        RpceUtility.BIND_TIME_FEATURE_NEGOTIATION_BITMASK_PREFIX_LENGTH))
                                &&
                                bindPdu.p_context_elem.p_cont_elem[i].transfer_syntaxes[j].if_vers_major == 1
                                &&
                                bindPdu.p_context_elem.p_cont_elem[i].transfer_syntaxes[j].if_vers_minor == 0)
                            {
                                context.BindTimeFeatureNegotiationBitmask = (RpceBindTimeFeatureNegotiationBitmask)
                                    uuid[RpceUtility.BIND_TIME_FEATURE_NEGOTIATION_BITMASK_PREFIX_LENGTH];
                            }
                        }

                    }
                }
            }
        }