Skip to content

Commit 527d21b

Browse files
Jesse-Bakkermatt335672
authored andcommitted
Add support for RFB protocol version 3.7 and 3.8
(cherry picked from commit 69cb532)
1 parent 2b22636 commit 527d21b

File tree

1 file changed

+103
-29
lines changed

1 file changed

+103
-29
lines changed

vnc/vnc.c

Lines changed: 103 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1654,10 +1654,15 @@ lib_mod_connect(struct vnc *v)
16541654
char cursor_mask[32 * (32 / 8)];
16551655
char con_port[256];
16561656
char text[256];
1657+
char *version_str;
1658+
char j;
16571659
struct stream *s;
16581660
struct stream *pixel_format;
16591661
int error;
16601662
int i;
1663+
int sec_lvl = 0;
1664+
int version;
1665+
int n_sec_lvls;
16611666
int check_sec_result;
16621667
int socket_mode;
16631668

@@ -1748,61 +1753,131 @@ lib_mod_connect(struct vnc *v)
17481753
error = trans_force_read_s(v->trans, s, 12);
17491754
if (error == 0)
17501755
{
1751-
s->p = s->data;
1752-
out_uint8a(s, "RFB 003.003\n", 12);
1753-
s_mark_end(s);
1754-
error = trans_force_write_s(v->trans, s);
1756+
in_uint8p(s, version_str, 12);
1757+
if (g_strncmp(version_str, "RFB 003.00", 10) != 0)
1758+
{
1759+
version_str[11] = '\0';
1760+
LOG(LOG_LEVEL_ERROR, "Invalid server version string %s", version_str);
1761+
error = 1;
1762+
}
1763+
}
1764+
if (error == 0)
1765+
{
1766+
version = version_str[10] - '0';
1767+
if (version != 3 && version != 7 && version != 8)
1768+
{
1769+
LOG(LOG_LEVEL_ERROR, "Unsupported VNC version 3.%d", version);
1770+
error = 1;
1771+
}
17551772
}
1756-
1757-
/* sec type */
17581773
if (error == 0)
17591774
{
17601775
init_stream(s, 8192);
1761-
error = trans_force_read_s(v->trans, s, 4);
1776+
out_uint8p(s, version_str, 12);
1777+
s_mark_end(s);
1778+
error = trans_force_write_s(v->trans, s);
17621779
}
17631780

1781+
/* sec type */
17641782
if (error == 0)
17651783
{
1766-
in_uint32_be(s, i);
1767-
g_sprintf(text, "VNC security level is %d (1 = none, 2 = standard)", i);
1768-
v->server_msg(v, text, 0);
1769-
1770-
if (i == 1) /* none */
1784+
if (version == 3)
17711785
{
1772-
check_sec_result = 0;
1786+
// The server chooses the security type
1787+
error = trans_force_read_s(v->trans, s, 4);
1788+
if (error == 0)
1789+
{
1790+
in_uint32_be(s, sec_lvl);
1791+
}
17731792
}
1774-
else if (i == 2) /* dec the password and the server random */
1793+
else if (version >= 7)
17751794
{
1776-
init_stream(s, 8192);
1777-
error = trans_force_read_s(v->trans, s, 16);
1778-
1795+
// The client chooses the security type
1796+
error = trans_force_read_s(v->trans, s, 1);
17791797
if (error == 0)
17801798
{
1781-
init_stream(s, 8192);
1782-
if (guid_is_set(&v->guid))
1799+
in_uint8(s, n_sec_lvls);
1800+
if (n_sec_lvls > 0)
17831801
{
1784-
char guid_str[GUID_STR_SIZE];
1785-
guid_to_str(&v->guid, guid_str);
1786-
rfbHashEncryptBytes(s->data, guid_str);
1802+
error = trans_force_read_s(v->trans, s, n_sec_lvls);
17871803
}
17881804
else
17891805
{
1790-
rfbEncryptBytes(s->data, v->password);
1806+
// Read size of reason
1807+
error = trans_force_read_s(v->trans, s, 4);
1808+
if (error == 0)
1809+
{
1810+
in_uint32_be(s, i);
1811+
error = trans_force_read_s(v->trans, s, i);
1812+
in_uint8a(s, text, i);
1813+
text[i] = '\0';
1814+
LOG(LOG_LEVEL_ERROR, "Connection closed by server with reason: %s", text);
1815+
error = 1;
1816+
}
17911817
}
1792-
s->p += 16;
1818+
}
1819+
if (error == 0)
1820+
{
1821+
for (; n_sec_lvls > 0; --n_sec_lvls)
1822+
{
1823+
in_uint8(s, j);
1824+
// Choose the highest security level that we support
1825+
if (j > sec_lvl && j <= 2)
1826+
{
1827+
sec_lvl = j;
1828+
}
1829+
}
1830+
init_stream(s, 8192);
1831+
out_uint8(s, sec_lvl);
17931832
s_mark_end(s);
1833+
17941834
error = trans_force_write_s(v->trans, s);
1795-
check_sec_result = 1; // not needed
17961835
}
17971836
}
1798-
else if (i == 0)
1837+
}
1838+
1839+
if (error == 0)
1840+
{
1841+
g_sprintf(text, "VNC security level is %d (1 = none, 2 = standard)", sec_lvl);
1842+
v->server_msg(v, text, 0);
1843+
1844+
if (sec_lvl == 1) /* none */
1845+
{
1846+
if (version >= 8)
1847+
{
1848+
check_sec_result = 1;
1849+
}
1850+
else
1851+
{
1852+
check_sec_result = 0;
1853+
}
1854+
}
1855+
else if (sec_lvl == 2) /* dec the password and the server random */
1856+
{
1857+
init_stream(s, 8192);
1858+
if (guid_is_set(&v->guid))
1859+
{
1860+
char guid_str[GUID_STR_SIZE];
1861+
guid_to_str(&v->guid, guid_str);
1862+
rfbHashEncryptBytes(s->data, guid_str);
1863+
}
1864+
else
1865+
{
1866+
rfbEncryptBytes(s->data, v->password);
1867+
}
1868+
s->p += 16;
1869+
s_mark_end(s);
1870+
error = trans_force_write_s(v->trans, s);
1871+
check_sec_result = 1; // not needed
1872+
}
1873+
else if (sec_lvl == 0)
17991874
{
18001875
LOG(LOG_LEVEL_ERROR, "VNC Server will disconnect");
18011876
error = 1;
18021877
}
18031878
else
18041879
{
1805-
LOG(LOG_LEVEL_ERROR, "VNC unsupported security level %d", i);
1880+
LOG(LOG_LEVEL_ERROR, "VNC unsupported security level %d", sec_lvl);
18061881
error = 1;
18071882
}
18081883
}
@@ -1839,8 +1914,7 @@ lib_mod_connect(struct vnc *v)
18391914
{
18401915
v->server_msg(v, "VNC sending share flag", 0);
18411916
init_stream(s, 8192);
1842-
s->data[0] = 1;
1843-
s->p++;
1917+
out_uint8(s, 1);
18441918
s_mark_end(s);
18451919
error = trans_force_write_s(v->trans, s); /* share flag */
18461920
}

0 commit comments

Comments
 (0)