Data reader for the X protocol message
        /// <summary>
        /// Obtain a new cookie from the X server for the "Untrusted" access.
        /// </summary>
        /// <remarks>
        /// This method will be called in the setup procedure of this manager.
        /// </remarks>
        /// <param name="socketFactory"></param>
        /// <param name="display">display number</param>
        /// <param name="entry"></param>
        /// <returns>tuple of { authorization-id, authorization-data } if the untrusted access is available. otherwise null.</returns>
        private Tuple<uint, byte[]> GetUntrustedAccessCookie(Func<IX11Socket> socketFactory, int display, XauthorityEntry entry)
        {
            using (IX11Socket socket = socketFactory()) {
                socket.Connect(display);

                const bool BIGENDIAN = true;

                byte[] recv = new byte[100];
                var xmsg = new XProtocolMessage(BIGENDIAN);
                var reader = new XDataReader(BIGENDIAN);

                // Note: if USE_UNTRUSTED_ACCESS was disabled, this method only checks the connectability to the X server.

                // initiation
                {
                    byte[] authName = Encoding.ASCII.GetBytes(entry.Name);
                    xmsg.Clear()
                        .AppendByte(0x42)   // MSB first
                        .AppendByte(0)  // unused
                        .AppendUInt16(11)   // protocol-major-version
                        .AppendUInt16(0)    // protocol-minor-version
                        .AppendUInt16((ushort)authName.Length) // length of authorization-protocol-name
                        .AppendUInt16((ushort)entry.Data.Length)    // length of authorization-protocol-data
                        .AppendUInt16(0)    // unused
                        .AppendBytes(authName)  // authorization-protocol-name
                        .AppendPaddingBytesOf(authName)
                        .AppendBytes(entry.Data)    // authorization-protocol-data
                        .AppendPaddingBytesOf(entry.Data);
                    if (!socket.Send(xmsg.AsDataFragment(), SEND_TIMEOUT)) {
                        throw new X11UtilException(Strings.GetString("FailedToSendMessageToXServer"));
                    }

                    if (!socket.ReceiveBytes(recv, 0, 8, RESPONSE_TIMEOUT)) {
                        throw new X11UtilException(Strings.GetString("XServerDoesntRespond"));
                    }

                    if (recv[0] != 1 /*Success*/) {
                        throw new X11UtilException(Strings.GetString("X11AuthorizationFailed"));
                    }
                    int extraDataLen = reader.ReadUInt16(recv, 6) * 4;
                    byte[] extraData = new byte[extraDataLen];
                    if (!socket.ReceiveBytes(extraData, 0, extraDataLen, RESPONSE_TIMEOUT)) {
                        throw new X11UtilException(Strings.GetString("XServerDoesntRespond"));
                    }
                }

            #if USE_UNTRUSTED_ACCESS

                // QueryExtension
                {
                    byte[] extName = Encoding.ASCII.GetBytes("SECURITY");
                    xmsg.Clear()
                        .AppendByte(98)   // opcode
                        .AppendByte(0)  // unused
                        .AppendUInt16((ushort)(2 + (extName.Length + 3) / 4))   // request-length
                        .AppendUInt16((ushort)extName.Length)    // length of name
                        .AppendUInt16(0)    // unused
                        .AppendBytes(extName)  // name
                        .AppendPaddingBytesOf(extName);
                    if (!socket.Send(xmsg.AsDataFragment(), SEND_TIMEOUT)) {
                        throw new X11UtilException(Strings.GetString("FailedToSendMessageToXServer"));
                    }

                    if (!socket.ReceiveBytes(recv, 0, 32, RESPONSE_TIMEOUT)) {
                        throw new X11UtilException(Strings.GetString("XServerDoesntRespond"));
                    }
                    if (recv[0] != 1 /*Reply*/ || recv[8] != 1 /*present*/) {
                        // no SECURITY extension
                        _protocolEventManager.Trace("[X11] X server doesn't have the SECURITY extension.");
                        return null;
                    }
                }
                byte secOpcode = recv[9];   // major-opcode of the SECURITY extension

                // SecurityQueryVersion
                {
                    xmsg.Clear()
                        .AppendByte(secOpcode)   // major-opcode
                        .AppendByte(0)  // minor-opcode
                        .AppendUInt16(2)   // request-length
                        .AppendUInt16(1)    // client-major-version
                        .AppendUInt16(0);   // client-minor-version
                    if (!socket.Send(xmsg.AsDataFragment(), SEND_TIMEOUT)) {
                        throw new X11UtilException(Strings.GetString("FailedToSendMessageToXServer"));
                    }

                    if (!socket.ReceiveBytes(recv, 0, 32, RESPONSE_TIMEOUT)) {
                        throw new X11UtilException(Strings.GetString("XServerDoesntRespond"));
                    }
                }

                // SecurityGenerateAuthorization
                {
                    byte[] authName = Encoding.ASCII.GetBytes(DEFAULT_AUTH_NAME);
                    byte[] authData = new byte[0];

                    uint[] valueList = new uint[] {
                        // timeout
                        0,  // no timeout
                        // trust-level
                        1,  // SecurityClientUntrusted
                    };

                    xmsg.Clear()
                        .AppendByte(secOpcode)   // major-opcode
                        .AppendByte(1)  // minor-opcode
                        .AppendUInt16((ushort)(3 + (authName.Length + 3) / 4 + (authData.Length + 3) / 4 + valueList.Length))
                        .AppendUInt16((ushort)authName.Length)
                        .AppendUInt16((ushort)authData.Length)
                        .AppendUInt32(3)    // value-mask : timeout + trust-level
                        .AppendBytes(authName)
                        .AppendPaddingBytesOf(authName)
                        .AppendBytes(authData)
                        .AppendPaddingBytesOf(authData)
                        .AppendUInt32(valueList[0])
                        .AppendUInt32(valueList[1]);
                    if (!socket.Send(xmsg.AsDataFragment(), SEND_TIMEOUT)) {
                        throw new X11UtilException(Strings.GetString("FailedToSendMessageToXServer"));
                    }

                    if (!socket.ReceiveBytes(recv, 0, 32, RESPONSE_TIMEOUT)) {
                        throw new X11UtilException(Strings.GetString("XServerDoesntRespond"));
                    }

                    if (recv[0] != 1 /*Reply*/) {
                        return null;
                    }

                    uint authId = reader.ReadUInt32(recv, 8);

                    int extraDataLength = (int)reader.ReadUInt32(recv, 4) * 4;
                    if (extraDataLength < 0 || extraDataLength > 1024) {
                        // something wrong...
                        return null;
                    }
                    int datLength = (int)reader.ReadUInt16(recv, 12);
                    if (datLength < 0 || datLength > extraDataLength) {
                        // something wrong...
                        return null;
                    }
                    byte[] extraData = new byte[extraDataLength];
                    if (!socket.ReceiveBytes(extraData, 0, extraDataLength, RESPONSE_TIMEOUT)) {
                        throw new X11UtilException(Strings.GetString("XServerDoesntRespond"));
                    }

                    byte[] generatedAuthData = reader.ReadBytes(extraData, 0, datLength);

                    return Tuple.Create(authId, generatedAuthData);
                }

            #else   // USE_UNTRUSTED_ACCESS

                // no untrusted access
                return null;

            #endif  // USE_UNTRUSTED_ACCESS
            }
        }
Esempio n. 2
0
        private void ProcessSetupMessage()
        {
            if (_messageBuffer.Length < 12)
            {
                return;
            }

            var  magic = _messageBuffer[0];
            bool byteOrder;

            if (magic == 0x42)
            {
                // MSB first
                byteOrder = true;   // big-endian
            }
            else if (magic == 0x6c)
            {
                // LSB first
                byteOrder = false;  // little-endian
            }
            else
            {
                _state = Status.HasError;
                return;
            }

            XDataReader reader = new XDataReader(byteOrder);

            ushort majorVersion = reader.ReadUInt16(_messageBuffer.RawBuffer, _messageBuffer.RawBufferOffset + 2);
            ushort minorVersion = reader.ReadUInt16(_messageBuffer.RawBuffer, _messageBuffer.RawBufferOffset + 4);

            int nameLen    = reader.ReadUInt16(_messageBuffer.RawBuffer, _messageBuffer.RawBufferOffset + 6);
            int namePadLen = (4 - (nameLen % 4)) % 4;

            int dataLen    = reader.ReadUInt16(_messageBuffer.RawBuffer, _messageBuffer.RawBufferOffset + 8);
            int dataPadLen = (4 - (dataLen % 4)) % 4;

            int messageLen = 12 + nameLen + namePadLen + dataLen + dataPadLen;

            if (_messageBuffer.Length < messageLen)
            {
                return;
            }

            // setup message has been received

            if (nameLen != _spoofedAuthProtocolName.Length ||
                !CompareBytes(_messageBuffer, 12, _spoofedAuthProtocolName))
            {
                // authorization protocol name doesn't match
                _state = Status.HasError;
                return;
            }

            if (dataLen != _spoofedAuthCookie.Length ||
                !CompareBytes(_messageBuffer, 12 + nameLen + namePadLen, _spoofedAuthCookie))
            {
                // authorization protocol data doesn't match
                _state = Status.HasError;
                return;
            }

            // start the receiving thread
            _x11Sock.StartReceivingThread(OnDataFromXServer, OnXSocketClosed);

            // send the modified setup message to the X server
            XProtocolMessage xmsg = new XProtocolMessage(byteOrder);

            xmsg.Clear()
            .AppendByte(byteOrder ? (byte)0x42 : (byte)0x6c)
            .AppendByte(0)
            .AppendUInt16(majorVersion)
            .AppendUInt16(minorVersion)
            .AppendUInt16((ushort)_authProtocolName.Length)
            .AppendUInt16((ushort)_authCookie.Length)
            .AppendUInt16(0)
            .AppendBytes(_authProtocolName)
            .AppendPaddingBytesOf(_authProtocolName)
            .AppendBytes(_authCookie)
            .AppendPaddingBytesOf(_authCookie);

            if (!_x11Sock.Send(xmsg.AsDataFragment(), SEND_TIMEOUT))
            {
                _state = Status.HasError;
                return;
            }

            // delete original setup message
            _messageBuffer.RemoveHead(messageLen);
            // send remaining bytes
            if (_messageBuffer.Length > 0)
            {
                if (!_x11Sock.Send(_messageBuffer.AsDataFragment(), SEND_TIMEOUT))
                {
                    _state = Status.HasError;
                    return;
                }
            }

            _state = Status.Established;
        }
        private void ProcessSetupMessage()
        {
            if (_messageBuffer.Length < 12) {
                return;
            }

            var magic = _messageBuffer[0];
            bool byteOrder;
            if (magic == 0x42) {
                // MSB first
                byteOrder = true;   // big-endian
            }
            else if (magic == 0x6c) {
                // LSB first
                byteOrder = false;  // little-endian
            }
            else {
                _state = Status.HasError;
                return;
            }

            XDataReader reader = new XDataReader(byteOrder);

            ushort majorVersion = reader.ReadUInt16(_messageBuffer.RawBuffer, _messageBuffer.RawBufferOffset + 2);
            ushort minorVersion = reader.ReadUInt16(_messageBuffer.RawBuffer, _messageBuffer.RawBufferOffset + 4);

            int nameLen = reader.ReadUInt16(_messageBuffer.RawBuffer, _messageBuffer.RawBufferOffset + 6);
            int namePadLen = (4 - (nameLen % 4)) % 4;

            int dataLen = reader.ReadUInt16(_messageBuffer.RawBuffer, _messageBuffer.RawBufferOffset + 8);
            int dataPadLen = (4 - (dataLen % 4)) % 4;

            int messageLen = 12 + nameLen + namePadLen + dataLen + dataPadLen;

            if (_messageBuffer.Length < messageLen) {
                return;
            }

            // setup message has been received

            if (nameLen != _spoofedAuthProtocolName.Length
                || !CompareBytes(_messageBuffer, 12, _spoofedAuthProtocolName)) {
                // authorization protocol name doesn't match
                _state = Status.HasError;
                return;
            }

            if (dataLen != _spoofedAuthCookie.Length
                || !CompareBytes(_messageBuffer, 12 + nameLen + namePadLen, _spoofedAuthCookie)) {
                // authorization protocol data doesn't match
                _state = Status.HasError;
                return;
            }

            // start the receiving thread
            _x11Sock.StartReceivingThread(OnDataFromXServer, OnXSocketClosed);

            // send the modified setup message to the X server
            XProtocolMessage xmsg = new XProtocolMessage(byteOrder);
            xmsg.Clear()
                .AppendByte(byteOrder ? (byte)0x42 : (byte)0x6c)
                .AppendByte(0)
                .AppendUInt16(majorVersion)
                .AppendUInt16(minorVersion)
                .AppendUInt16((ushort)_authProtocolName.Length)
                .AppendUInt16((ushort)_authCookie.Length)
                .AppendUInt16(0)
                .AppendBytes(_authProtocolName)
                .AppendPaddingBytesOf(_authProtocolName)
                .AppendBytes(_authCookie)
                .AppendPaddingBytesOf(_authCookie);

            if (!_x11Sock.Send(xmsg.AsDataFragment(), SEND_TIMEOUT)) {
                _state = Status.HasError;
                return;
            }

            // delete original setup message
            _messageBuffer.RemoveHead(messageLen);
            // send remaining bytes
            if (_messageBuffer.Length > 0) {
                if (!_x11Sock.Send(_messageBuffer.AsDataFragment(), SEND_TIMEOUT)) {
                    _state = Status.HasError;
                    return;
                }
            }

            _state = Status.Established;
        }
Esempio n. 4
0
        /// <summary>
        /// Obtain a new cookie from the X server for the "Untrusted" access.
        /// </summary>
        /// <remarks>
        /// This method will be called in the setup procedure of this manager.
        /// </remarks>
        /// <param name="socketFactory"></param>
        /// <param name="display">display number</param>
        /// <param name="entry"></param>
        /// <returns>tuple of { authorization-id, authorization-data } if the untrusted access is available. otherwise null.</returns>
        private Tuple <uint, byte[]> GetUntrustedAccessCookie(Func <IX11Socket> socketFactory, int display, XauthorityEntry entry)
        {
            using (IX11Socket socket = socketFactory()) {
                socket.Connect(display);

                const bool BIGENDIAN = true;

                byte[] recv   = new byte[100];
                var    xmsg   = new XProtocolMessage(BIGENDIAN);
                var    reader = new XDataReader(BIGENDIAN);

                // Note: if USE_UNTRUSTED_ACCESS was disabled, this method only checks the connectability to the X server.

                // initiation
                {
                    byte[] authName = Encoding.ASCII.GetBytes(entry.Name);
                    xmsg.Clear()
                    .AppendByte(0x42)                        // MSB first
                    .AppendByte(0)                           // unused
                    .AppendUInt16(11)                        // protocol-major-version
                    .AppendUInt16(0)                         // protocol-minor-version
                    .AppendUInt16((ushort)authName.Length)   // length of authorization-protocol-name
                    .AppendUInt16((ushort)entry.Data.Length) // length of authorization-protocol-data
                    .AppendUInt16(0)                         // unused
                    .AppendBytes(authName)                   // authorization-protocol-name
                    .AppendPaddingBytesOf(authName)
                    .AppendBytes(entry.Data)                 // authorization-protocol-data
                    .AppendPaddingBytesOf(entry.Data);
                    if (!socket.Send(xmsg.AsDataFragment(), SEND_TIMEOUT))
                    {
                        throw new X11UtilException(Strings.GetString("FailedToSendMessageToXServer"));
                    }

                    if (!socket.ReceiveBytes(recv, 0, 8, RESPONSE_TIMEOUT))
                    {
                        throw new X11UtilException(Strings.GetString("XServerDoesntRespond"));
                    }

                    if (recv[0] != 1 /*Success*/)
                    {
                        throw new X11UtilException(Strings.GetString("X11AuthorizationFailed"));
                    }
                    int    extraDataLen = reader.ReadUInt16(recv, 6) * 4;
                    byte[] extraData    = new byte[extraDataLen];
                    if (!socket.ReceiveBytes(extraData, 0, extraDataLen, RESPONSE_TIMEOUT))
                    {
                        throw new X11UtilException(Strings.GetString("XServerDoesntRespond"));
                    }
                }

#if USE_UNTRUSTED_ACCESS
                // QueryExtension
                {
                    byte[] extName = Encoding.ASCII.GetBytes("SECURITY");
                    xmsg.Clear()
                    .AppendByte(98)                                       // opcode
                    .AppendByte(0)                                        // unused
                    .AppendUInt16((ushort)(2 + (extName.Length + 3) / 4)) // request-length
                    .AppendUInt16((ushort)extName.Length)                 // length of name
                    .AppendUInt16(0)                                      // unused
                    .AppendBytes(extName)                                 // name
                    .AppendPaddingBytesOf(extName);
                    if (!socket.Send(xmsg.AsDataFragment(), SEND_TIMEOUT))
                    {
                        throw new X11UtilException(Strings.GetString("FailedToSendMessageToXServer"));
                    }

                    if (!socket.ReceiveBytes(recv, 0, 32, RESPONSE_TIMEOUT))
                    {
                        throw new X11UtilException(Strings.GetString("XServerDoesntRespond"));
                    }
                    if (recv[0] != 1 /*Reply*/ || recv[8] != 1 /*present*/)
                    {
                        // no SECURITY extension
                        _protocolEventManager.Trace("[X11] X server doesn't have the SECURITY extension.");
                        return(null);
                    }
                }
                byte secOpcode = recv[9];   // major-opcode of the SECURITY extension

                // SecurityQueryVersion
                {
                    xmsg.Clear()
                    .AppendByte(secOpcode) // major-opcode
                    .AppendByte(0)         // minor-opcode
                    .AppendUInt16(2)       // request-length
                    .AppendUInt16(1)       // client-major-version
                    .AppendUInt16(0);      // client-minor-version
                    if (!socket.Send(xmsg.AsDataFragment(), SEND_TIMEOUT))
                    {
                        throw new X11UtilException(Strings.GetString("FailedToSendMessageToXServer"));
                    }

                    if (!socket.ReceiveBytes(recv, 0, 32, RESPONSE_TIMEOUT))
                    {
                        throw new X11UtilException(Strings.GetString("XServerDoesntRespond"));
                    }
                }

                // SecurityGenerateAuthorization
                {
                    byte[] authName = Encoding.ASCII.GetBytes(DEFAULT_AUTH_NAME);
                    byte[] authData = new byte[0];

                    uint[] valueList = new uint[] {
                        // timeout
                        0,  // no timeout
                        // trust-level
                        1,  // SecurityClientUntrusted
                    };

                    xmsg.Clear()
                    .AppendByte(secOpcode) // major-opcode
                    .AppendByte(1)         // minor-opcode
                    .AppendUInt16((ushort)(3 + (authName.Length + 3) / 4 + (authData.Length + 3) / 4 + valueList.Length))
                    .AppendUInt16((ushort)authName.Length)
                    .AppendUInt16((ushort)authData.Length)
                    .AppendUInt32(3)        // value-mask : timeout + trust-level
                    .AppendBytes(authName)
                    .AppendPaddingBytesOf(authName)
                    .AppendBytes(authData)
                    .AppendPaddingBytesOf(authData)
                    .AppendUInt32(valueList[0])
                    .AppendUInt32(valueList[1]);
                    if (!socket.Send(xmsg.AsDataFragment(), SEND_TIMEOUT))
                    {
                        throw new X11UtilException(Strings.GetString("FailedToSendMessageToXServer"));
                    }

                    if (!socket.ReceiveBytes(recv, 0, 32, RESPONSE_TIMEOUT))
                    {
                        throw new X11UtilException(Strings.GetString("XServerDoesntRespond"));
                    }

                    if (recv[0] != 1 /*Reply*/)
                    {
                        return(null);
                    }

                    uint authId = reader.ReadUInt32(recv, 8);

                    int extraDataLength = (int)reader.ReadUInt32(recv, 4) * 4;
                    if (extraDataLength < 0 || extraDataLength > 1024)
                    {
                        // something wrong...
                        return(null);
                    }
                    int datLength = (int)reader.ReadUInt16(recv, 12);
                    if (datLength < 0 || datLength > extraDataLength)
                    {
                        // something wrong...
                        return(null);
                    }
                    byte[] extraData = new byte[extraDataLength];
                    if (!socket.ReceiveBytes(extraData, 0, extraDataLength, RESPONSE_TIMEOUT))
                    {
                        throw new X11UtilException(Strings.GetString("XServerDoesntRespond"));
                    }

                    byte[] generatedAuthData = reader.ReadBytes(extraData, 0, datLength);

                    return(Tuple.Create(authId, generatedAuthData));
                }
#else   // USE_UNTRUSTED_ACCESS
                // no untrusted access
                return(null);
#endif  // USE_UNTRUSTED_ACCESS
            }
        }