Entry in the .Xauthority file.
예제 #1
0
        /// <summary>
        /// Find an entry which is most matched to the display number and the connection type.
        /// </summary>
        /// <param name="xauthFile">path to the .Xauthority file</param>
        /// <param name="display">display number</param>
        /// <returns>best-matched entry if it was found. otherwise null.</returns>
        public XauthorityEntry FindBest(string xauthFile, int display)
        {
            // from Xauth.h
            const ushort FamilyWild = 65535;

            string hostName = Dns.GetHostEntry("").HostName;    // get fully qualified hostname

            XauthorityEntry candidate = null;

            foreach (var entry in ReadEntries(xauthFile))
            {
                if (entry.Number != display)
                {
                    continue;
                }
                if (entry.Family == FamilyWild)
                {
                    candidate = entry;
                }
                if (entry.Address == hostName)
                {
                    return(entry);   // best
                }
            }
            return(candidate);
        }
        /// <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
            }
        }
예제 #3
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
            }
        }
        /// <summary>
        /// Setup the connection manager according to the parameters.
        /// </summary>
        /// <param name="param">parameters</param>
        /// <exception cref="X11UtilException"></exception>
        /// <exception cref="X11SocketException"></exception>
        public void Setup(X11ForwardingParams param)
        {
            if (_setupDone) {
                return;
            }

            _param = param.Clone();

            _spoofedAuthProtocolName = DEFAULT_AUTH_NAME;
            _spoofedAuthCookie = GenerateCookie();

            if (param.UseCygwinUnixDomainSocket) {
                _protocolEventManager.Trace("[X11] Use Cygwin's domain socket");
                _socketFactory = () => new X11CygwinDomainSocket(param.X11UnixFolder);
            }
            else {
                _protocolEventManager.Trace("[X11] Use TCP socket");
                _socketFactory = () => new X11TcpSocket();
            }

            XauthorityEntry xauthEntry;
            if (param.NeedAuth) {
                string xauthFile = FindXauthorityFile(param);
                if (xauthFile == null) {
                    throw new X11UtilException(Strings.GetString("XauthorityFileNotFound"));
                }
                var parser = new XauthorityParser();
                xauthEntry = parser.FindBest(xauthFile, param.Display);
                if (xauthEntry == null) {
                    throw new X11UtilException(Strings.GetString("SuitableAuthorizationInformationNotFound"));
                }
            }
            else {
                xauthEntry = new XauthorityEntry(0, "", param.Display, "", new byte[0]);
            }

            var cookieInfo = GetUntrustedAccessCookie(_socketFactory, param.Display, xauthEntry);
            if (cookieInfo == null) {
                // no SECURITY extension
                _protocolEventManager.Trace("[X11] \"Trusted\" access will be used.");
                _xAuthProtocolName = xauthEntry.Name;
                _xAuthCookie = xauthEntry.Data;
                _authEntry = xauthEntry;
                _authId = null;
                _setupDone = true;
                return;
            }

            _protocolEventManager.Trace("[X11] \"Untrusted\" access will be used.");
            _xAuthProtocolName = DEFAULT_AUTH_NAME;
            _xAuthCookie = cookieInfo.Item2;
            _authEntry = xauthEntry;
            _authId = cookieInfo.Item1;
            _setupDone = true;
            // TODO:
            // the authorization cookie should be deleted from the X server when
            // the forwarding channel is closed.
        }
예제 #5
0
        /// <summary>
        /// Setup the connection manager according to the parameters.
        /// </summary>
        /// <param name="param">parameters</param>
        /// <exception cref="X11UtilException"></exception>
        /// <exception cref="X11SocketException"></exception>
        public void Setup(X11ForwardingParams param)
        {
            if (_setupDone)
            {
                return;
            }

            _param = param.Clone();

            _spoofedAuthProtocolName = DEFAULT_AUTH_NAME;
            _spoofedAuthCookie       = GenerateCookie();

            if (param.UseCygwinUnixDomainSocket)
            {
                _protocolEventManager.Trace("[X11] Use Cygwin's domain socket");
                _socketFactory = () => new X11CygwinDomainSocket(param.X11UnixFolder);
            }
            else
            {
                _protocolEventManager.Trace("[X11] Use TCP socket");
                _socketFactory = () => new X11TcpSocket();
            }

            XauthorityEntry xauthEntry;

            if (param.NeedAuth)
            {
                string xauthFile = FindXauthorityFile(param);
                if (xauthFile == null)
                {
                    throw new X11UtilException(Strings.GetString("XauthorityFileNotFound"));
                }
                var parser = new XauthorityParser();
                xauthEntry = parser.FindBest(xauthFile, param.Display);
                if (xauthEntry == null)
                {
                    throw new X11UtilException(Strings.GetString("SuitableAuthorizationInformationNotFound"));
                }
            }
            else
            {
                xauthEntry = new XauthorityEntry(0, "", param.Display, "", new byte[0]);
            }

            var cookieInfo = GetUntrustedAccessCookie(_socketFactory, param.Display, xauthEntry);

            if (cookieInfo == null)
            {
                // no SECURITY extension
                _protocolEventManager.Trace("[X11] \"Trusted\" access will be used.");
                _xAuthProtocolName = xauthEntry.Name;
                _xAuthCookie       = xauthEntry.Data;
                _authEntry         = xauthEntry;
                _authId            = null;
                _setupDone         = true;
                return;
            }

            _protocolEventManager.Trace("[X11] \"Untrusted\" access will be used.");
            _xAuthProtocolName = DEFAULT_AUTH_NAME;
            _xAuthCookie       = cookieInfo.Item2;
            _authEntry         = xauthEntry;
            _authId            = cookieInfo.Item1;
            _setupDone         = true;
            // TODO:
            // the authorization cookie should be deleted from the X server when
            // the forwarding channel is closed.
        }