/// <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 } }
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; }
/// <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 } }