Example #1
0
        /// <summary>
        /// Bind the RPC transport to an interface.
        /// </summary>
        /// <param name="interface_id">The interface ID to bind to.</param>
        /// <param name="interface_version">The interface version to bind to.</param>
        /// <param name="transfer_syntax_id">The transfer syntax to use.</param>
        /// <param name="transfer_syntax_version">The transfer syntax version to use.</param>
        public void Bind(Guid interface_id, Version interface_version, Guid transfer_syntax_id, Version transfer_syntax_version)
        {
            if (transfer_syntax_id != Ndr.NdrNativeUtils.DCE_TransferSyntax || transfer_syntax_version != new Version(2, 0))
            {
                throw new ArgumentException("Only supports DCE transfer syntax");
            }

            PDUBind bind_pdu = new PDUBind(MaxXmitFrag, MaxRecvFrag);

            bind_pdu.Elements.Add(new ContextElement(interface_id, interface_version, transfer_syntax_id, transfer_syntax_version));
            var recv_pdu = SendReceivePDU(bind_pdu);

            if (recv_pdu is PDUBindAck bind_ack)
            {
                if (bind_ack.ResultList.Count != 1 || bind_ack.ResultList[0].Result != PresentationResultType.Acceptance)
                {
                    throw new RpcTransportException($"Bind to {interface_id}:{interface_version} was rejected.");
                }

                _max_recv_fragment = bind_ack.MaxRecvFrag;
                _max_send_fragment = bind_ack.MaxXmitFrag;
            }
            else
            {
                throw new RpcTransportException("Unexpected PDU from server.");
            }
        }
        private void BindNoAuth()
        {
            PDUBind bind_pdu = new PDUBind(_max_send_fragment, _max_recv_fragment, 0, false);

            bind_pdu.Elements.Add(new ContextElement(_interface_id, _interface_version, _transfer_syntax_id, _transfer_syntax_version));
            var recv_pdu = SendReceivePDU(++CallId, bind_pdu, new byte[0], true, _current_security_context).Item1;

            if (recv_pdu is PDUBindAck bind_ack)
            {
                if (bind_ack.ResultList.Count != 1 || bind_ack.ResultList[0].Result != PresentationResultType.Acceptance)
                {
                    throw new RpcTransportException($"Bind to {_interface_id}:{_interface_version} was rejected.");
                }

                _max_recv_fragment = bind_ack.MaxRecvFrag;
                _max_send_fragment = bind_ack.MaxXmitFrag;
                _assoc_group_id    = bind_ack.AssocGroupId;
            }
            else if (recv_pdu is PDUBindNack bind_nack)
            {
                throw new RpcTransportException($"Bind NACK returned with rejection reason {bind_nack.RejectionReason}");
            }
            else
            {
                throw new RpcTransportException($"Unexpected {recv_pdu.PDUType} PDU from server.");
            }
        }
        private void BindAuth(bool alter_context, RpcTransportSecurityContext security_context)
        {
            // 8 should be more than enough legs to complete authentication.
            int max_legs = security_context.MaxAuthLegs;
            int call_id  = ++CallId;
            int count    = 0;

            while (count++ < max_legs)
            {
                PDUBind bind_pdu = new PDUBind(_max_send_fragment, _max_recv_fragment, 0, alter_context);

                bind_pdu.Elements.Add(new ContextElement(_interface_id, _interface_version, _transfer_syntax_id, _transfer_syntax_version));
                if (!_bind_time_features.HasValue)
                {
                    _bind_time_features = BindTimeFeatureNegotiation.None;
                    bind_pdu.Elements.Add(new ContextElement(_interface_id, _interface_version,
                                                             BindTimeFeatureNegotiation.SecurityContextMultiplexingSupported));
                }

                var recv = SendReceivePDU(call_id, bind_pdu, security_context.AuthContext.Token.ToArray(), true, security_context);
                if (recv.Item1 is PDUBindAck bind_ack)
                {
                    if (bind_ack.ResultList.Count < 1 || bind_ack.ResultList[0].Result != PresentationResultType.Acceptance)
                    {
                        throw new RpcTransportException($"Bind to {_interface_id}:{_interface_version} was rejected.");
                    }

                    if (bind_ack.ResultList.Count == 2)
                    {
                        _bind_time_features = bind_ack.ResultList[1].BindTimeFeature;
                    }

                    if (!alter_context)
                    {
                        // Only capture values from the BindAck.
                        _max_recv_fragment = bind_ack.MaxRecvFrag;
                        _max_send_fragment = bind_ack.MaxXmitFrag;
                        _assoc_group_id    = bind_ack.AssocGroupId;
                        alter_context      = true;
                    }

                    if (recv.Item2.Data == null || recv.Item2.Data.Length == 0)
                    {
                        // No auth, assume success.
                        break;
                    }

                    security_context.AuthContext.Continue(new AuthenticationToken(recv.Item2.Data));
                    if (security_context.AuthContext.Done)
                    {
                        byte[] token = security_context.AuthContext.Token.ToArray();
                        if (token.Length == 0)
                        {
                            break;
                        }
                        // If we still have an NTLM token to complete then send as an Auth3 PDU.
                        if (security_context.TransportSecurity.AuthenticationType == RpcAuthenticationType.WinNT)
                        {
                            SendReceivePDU(call_id, new PDUAuth3(), token, false, security_context);
                            break;
                        }
                    }
                }
                else if (recv.Item1 is PDUBindNack bind_nack)
                {
                    throw new RpcTransportException($"Bind NACK returned with rejection reason {bind_nack.RejectionReason}");
                }
                else
                {
                    throw new RpcTransportException($"Unexpected {recv.Item1.PDUType} PDU from server.");
                }
            }

            if (!security_context.AuthContext.Done)
            {
                throw new RpcTransportException("Failed to complete the client authentication.");
            }
            security_context.SetNegotiatedAuthType();
        }
Example #4
0
        private void BindAuth(Guid interface_id, Version interface_version, Guid transfer_syntax_id, Version transfer_syntax_version)
        {
            // 8 should be more than enough legs to complete authentication.
            int  max_legs      = _transport_security.AuthenticationType == RpcAuthenticationType.WinNT ? 3 : 8;
            int  call_id       = ++CallId;
            int  count         = 0;
            bool alter_context = false;

            while (count++ < max_legs)
            {
                PDUBind bind_pdu = new PDUBind(_max_send_fragment, _max_recv_fragment, alter_context);

                bind_pdu.Elements.Add(new ContextElement(interface_id, interface_version, transfer_syntax_id, transfer_syntax_version));

                var recv = SendReceivePDU(call_id, bind_pdu, _auth_context.Token.ToArray(), true);
                if (recv.Item1 is PDUBindAck bind_ack)
                {
                    if (bind_ack.ResultList.Count != 1 || bind_ack.ResultList[0].Result != PresentationResultType.Acceptance)
                    {
                        throw new RpcTransportException($"Bind to {interface_id}:{interface_version} was rejected.");
                    }

                    if (!alter_context)
                    {
                        // Only capture values from the BindAck.
                        _max_recv_fragment = bind_ack.MaxRecvFrag;
                        _max_send_fragment = bind_ack.MaxXmitFrag;
                        alter_context      = true;
                    }

                    if (recv.Item2.Data == null || recv.Item2.Data.Length == 0)
                    {
                        // No auth, assume success.
                        break;
                    }

                    _auth_context.Continue(new AuthenticationToken(recv.Item2.Data));
                    if (_auth_context.Done)
                    {
                        byte[] token = _auth_context.Token.ToArray();
                        if (token.Length == 0)
                        {
                            break;
                        }
                        // If we still have an NTLM token to complete then send as an Auth3 PDU.
                        if (_transport_security.AuthenticationType == RpcAuthenticationType.WinNT)
                        {
                            SendReceivePDU(call_id, new PDUAuth3(), _auth_context.Token.ToArray(), false);
                            break;
                        }
                    }
                }
                else if (recv.Item1 is PDUBindNack bind_nack)
                {
                    throw new RpcTransportException($"Bind NACK returned with rejection reason {bind_nack.RejectionReason}");
                }
                else
                {
                    throw new RpcTransportException($"Unexpected {recv.Item1.PDUType} PDU from server.");
                }
            }

            if (!_auth_context.Done)
            {
                throw new RpcTransportException("Failed to complete the client authentication.");
            }

            if (_transport_security.AuthenticationType == RpcAuthenticationType.Negotiate)
            {
                var package_name = _auth_context.PackageName;
                _negotiated_auth_type = AuthenticationPackage.CheckKerberos(package_name)
                    ? RpcAuthenticationType.Kerberos : RpcAuthenticationType.WinNT;
            }
            else
            {
                _negotiated_auth_type = _transport_security.AuthenticationType;
            }
        }