์ด๊ฒ์ RDP ํ๋กํ ์ฝ ์์
์ ์ํ ์คํ ์์ค ํ๋ก๊ทธ๋จ ํ
์คํธ์ ๊ดํ ์ผ๋ จ์ ๊ธฐ์ฌ ์ค ๋ ๋ฒ์งธ ๋ฆฌ๋ทฐ์
๋๋ค. ์ฌ๊ธฐ์๋ rdesktop ํด๋ผ์ด์ธํธ์ xrdp ์๋ฒ๋ฅผ ์ดํด๋ณด๊ฒ ์ต๋๋ค.
์ค๋ฅ๋ฅผ ์๋ณํ๋ ๋๊ตฌ๋ก ์ฌ์ฉ๋จ
์ด ๊ธฐ์ฌ์๋ ๋์๊ฒ ํฅ๋ฏธ๋ก์ ๋ ์ค๋ฅ๋ง ์ ์๋์ด ์์ต๋๋ค. ๋ค๋ง, ํ๋ก์ ํธ ๊ท๋ชจ๊ฐ ์์์ ์ค์๊ฐ ๊ฑฐ์ ์์์ต๋๋ค :).
์ฃผ์. FreeRDP ํ๋ก์ ํธ ๊ฒ์ฆ์ ๊ดํ ์ด์ ๊ธฐ์ฌ๋ฅผ ์ฐพ์ ์ ์์ต๋๋ค.
๋ฐ์คํฌํ
์ด ํด๋ผ์ด์ธํธ๋ ๋งค์ฐ ์ธ๊ธฐ๊ฐ ๋์ต๋๋ค. ๊ธฐ๋ณธ์ ์ผ๋ก ReactOS์์ ์ฌ์ฉ๋๋ฉฐ ์ด์ ๋ํ ํ์ฌ ๊ทธ๋ํฝ ํ๋ฐํธ ์๋๋ ์ฐพ์ ์ ์์ต๋๋ค. ๊ทธ๋ฌ๋ ๊ทธ๋ ๊ฝค ๋์ด๊ฐ ๋ง์ต๋๋ค. ๊ทธ์ ์ฒซ ๋ฒ์งธ ๋ฆด๋ฆฌ์ค๋ 4๋ 2001์ 17์ผ์ ์ด๋ฃจ์ด์ก์ต๋๋ค. ์ด ๊ธ์ ์ฐ๋ ๋น์ ๊ทธ๋ XNUMX์ธ์์ต๋๋ค.
์์ ์ธ๊ธํ๋ฏ์ด ํ๋ก์ ํธ๋ ๋งค์ฐ ์์ต๋๋ค. ์ฝ 30์ค์ ์ฝ๋๊ฐ ํฌํจ๋์ด ์๋๋ฐ, ์ค๋ ์ธ์์ ๊ณ ๋ คํ๋ฉด ์กฐ๊ธ ์ด์ํฉ๋๋ค. ๋น๊ต๋ฅผ ์ํด FreeRDP์๋ 320๋ง ์ค์ด ํฌํจ๋์ด ์์ต๋๋ค. Cloc ํ๋ก๊ทธ๋จ์ ์ถ๋ ฅ์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
์ ๊ทผํ ์ ์๋ ์ฝ๋
int
main(int argc, char *argv[])
{
....
return handle_disconnect_reason(deactivated, ext_disc_reason);
if (g_redirect_username)
xfree(g_redirect_username);
xfree(g_username);
}
์ค๋ฅ๋ ํจ์์์ ์ฆ์ ๋ฐ์ํฉ๋๋ค. ๋ณธ๊ด: ์ฐ์ฐ์ ๋ค์ ์ค๋ ์ฝ๋๋ฅผ ๋ณผ ์ ์์ต๋๋ค. return โ ์ด ์กฐ๊ฐ์ ๋ฉ๋ชจ๋ฆฌ ์ ๋ฆฌ๋ฅผ ์ํํฉ๋๋ค. ๊ทธ๋ฌ๋ ์ค๋ฅ๋ ์ํ์ ์ผ์ผํค์ง ์์ต๋๋ค. ํ ๋น๋ ๋ชจ๋ ๋ฉ๋ชจ๋ฆฌ๋ ํ๋ก๊ทธ๋จ์ด ์ข ๋ฃ๋ ํ ์ด์ ์ฒด์ ์ ์ํด ์ง์์ง๋๋ค.
์ค๋ฅ ์ฒ๋ฆฌ ์์
RD_BOOL
subprocess(char *const argv[], str_handle_lines_t linehandler, void *data)
{
int n = 1;
char output[256];
....
while (n > 0)
{
n = read(fd[0], output, 255);
output[n] = ' '; // <=
str_handle_lines(output, &rest, linehandler, data);
}
....
}
์ด ๊ฒฝ์ฐ ์ฝ๋ ์กฐ๊ฐ์ ํ์ผ์ด ๋๋ ๋๊น์ง ํ์ผ์์ ๋ฒํผ๋ก ์ฝ์ด์ต๋๋ค. ๊ทธ๋ฌ๋ ์ฌ๊ธฐ์๋ ์ค๋ฅ ์ฒ๋ฆฌ๊ฐ ์์ต๋๋ค. ๋ฌธ์ ๊ฐ ๋ฐ์ํ๋ฉด ์ฝ๊ธฐ -1์ ๋ฐํํ๊ณ ๋ฐฐ์ด์ด ์ค๋ฒ๋ฐ๋ฉ๋๋ค. ์ถ๋ ฅ.
char ์ ํ์์ EOF ์ฌ์ฉ
int
ctrl_send_command(const char *cmd, const char *arg)
{
char result[CTRL_RESULT_SIZE], c, *escaped;
....
while ((c = fgetc(fp)) != EOF && index < CTRL_RESULT_SIZE && c != 'n')
{
result[index] = c;
index++;
}
....
}
์ฌ๊ธฐ์๋ ํ์ผ ๋์ ๋๋ฌํ๋ ์๋ชป๋ ์ฒ๋ฆฌ๋ฅผ ๋ณผ ์ ์์ต๋๋ค. fgetc ์ฝ๋๊ฐ 0xFF์ธ ๋ฌธ์๋ฅผ ๋ฐํํ๋ฉด ํ์ผ์ ๋์ผ๋ก ํด์๋ฉ๋๋ค(EOF).
EOF ์ด๋ ์์์ด๋ฉฐ ์ผ๋ฐ์ ์ผ๋ก -1๋ก ์ ์๋ฉ๋๋ค. ์๋ฅผ ๋ค์ด, CP1251 ์ธ์ฝ๋ฉ์์ ๋ฌ์์ ์ํ๋ฒณ์ ๋ง์ง๋ง ๋ฌธ์๋ ์ฝ๋ 0xFF๋ฅผ ๊ฐ์ง๋ฉฐ, ๋ค์๊ณผ ๊ฐ์ ๋ณ์์ ๋ํด ์ด์ผ๊ธฐํ ๊ฒฝ์ฐ ์ซ์ -1์ ํด๋นํฉ๋๋ค. ์ด๋ฅ ์ ์ฐจ. 0xFF ๊ธฐํธ๋ ๋ค์๊ณผ ๊ฐ์ต๋๋ค. EOF (-1)์ ํ์ผ์ ๋์ผ๋ก ํด์๋ฉ๋๋ค. ์ด๋ฌํ ์ค๋ฅ๋ฅผ ๋ฐฉ์งํ๊ธฐ ์ํด ํจ์์ ๊ฒฐ๊ณผ๋ ๋ค์๊ณผ ๊ฐ์ต๋๋ค. fgetc ๋ค์๊ณผ ๊ฐ์ ๋ณ์์ ์ ์ฅํด์ผ ํฉ๋๋ค. INT.
์คํ
์กฐ๊ฐ 1
RD_NTSTATUS
disk_set_information(....)
{
time_t write_time, change_time, access_time, mod_time;
....
if (write_time || change_time)
mod_time = MIN(write_time, change_time);
else
mod_time = write_time ? write_time : change_time; // <=
....
}
์๋ง๋ ์ด ์ฝ๋์ ์์ฑ์๊ฐ ์๋ชปํ์ ์๋ ์์ต๋๋ค. || ะธ && ์ํ. ๊ฐ์ ๋ํด ๊ฐ๋ฅํ ์ต์ ์ ๊ณ ๋ คํด ๋ณด๊ฒ ์ต๋๋ค. ์ฐ๊ธฐ_์๊ฐ ะธ ๋ณ๊ฒฝ_์๊ฐ:
- ๋ ๋ณ์ ๋ชจ๋ 0๊ณผ ๊ฐ์ต๋๋ค. ์ด ๊ฒฝ์ฐ ๋ถ๊ธฐ๋ก ์ข ๋ฃ๋ฉ๋๋ค. ๊ทธ๋ ์ง ์์ผ๋ฉด: ๋ณ์ mod_time ํ์ ์กฐ๊ฑด์ ๊ด๊ณ์์ด ํญ์ 0์ด ๋ฉ๋๋ค.
- ๋ณ์ ์ค ํ๋๊ฐ 0์ ๋๋ค. mod_time (๋ค๋ฅธ ๋ณ์์ ์์๊ฐ ์๋ ๊ฐ์ด ์๋ ๊ฒฝ์ฐ) 0๊ณผ ๊ฐ์ต๋๋ค. ์๋ํ๋ฉด MIN ๋ ์ต์ ์ค ๋ ์์ ์ต์ ์ ์ ํํฉ๋๋ค.
- ๋ ๋ณ์ ๋ชจ๋ 0์ด ์๋๋๋ค. ์ต์๊ฐ์ ์ ํํ์ธ์.
์กฐ๊ฑด์ ๋ค์๊ณผ ๊ฐ์ด ๊ต์ฒดํ ๋ write_time && ๋ณ๊ฒฝ_์๊ฐ ๋์์ด ์ฌ๋ฐ๋ฅด๊ฒ ๋ณด์ผ ๊ฒ์ ๋๋ค:
- ํ๋ ๋๋ ๋ ๋ณ์ ๋ชจ๋ 0์ด ์๋๋๋ค. XNUMX์ด ์๋ ๊ฐ์ ์ ํํฉ๋๋ค.
- ๋ ๋ณ์ ๋ชจ๋ 0์ด ์๋๋๋ค. ์ต์๊ฐ์ ์ ํํ์ธ์.
์กฐ๊ฐ 2
static RD_NTSTATUS
disk_device_control(RD_NTHANDLE handle, uint32 request, STREAM in,
STREAM out)
{
....
if (((request >> 16) != 20) || ((request >> 16) != 9))
return RD_STATUS_INVALID_PARAMETER;
....
}
์ฌ๊ธฐ ์ด์์๋ ํท๊ฐ๋ฆฌ๋๊ฑฐ ๊ฐ๋๋ฐ || ะธ &&๋๋ == ะธ !=: ๋ณ์๋ 20๊ณผ 9์ ๊ฐ์ ๋์์ ๊ฐ์ง ์ ์์ต๋๋ค.
๋ฌด์ ํ ๋ผ์ธ ๋ณต์ฌ
RD_NTSTATUS
disk_query_directory(....)
{
....
char *dirname, fullpath[PATH_MAX];
....
/* Get information for directory entry */
sprintf(fullpath, "%s/%s", dirname, pdirent->d_name);
....
}
ํจ์ ์ ์ฒด๋ฅผ ์ดํด๋ณด๋ฉด ์ด ์ฝ๋๊ฐ ๋ฌธ์ ๋ฅผ ์ผ์ผํค์ง ์๋๋ค๋ ๊ฒ์ด ๋ถ๋ช ํด์ง๋๋ค. ๊ทธ๋ฌ๋ ๋ฏธ๋์๋ ์ด๋ฌํ ๋ฌธ์ ๊ฐ ๋ฐ์ํ ์ ์์ต๋๋ค. ๋ถ์ฃผ์ํ๊ฒ ๋ณ๊ฒฝํ๋ฉด ๋ฒํผ ์ค๋ฒํ๋ก๊ฐ ๋ฐ์ํฉ๋๋ค. ์คํ๋ฆฐํธ ์ด๋ค ๊ฒ์๋ ์ ํ์ด ์์ผ๋ฏ๋ก ๊ฒฝ๋ก๋ฅผ ์ฐ๊ฒฐํ ๋ ๋ฐฐ์ด์ ๊ฒฝ๊ณ๋ฅผ ๋์ด๊ฐ ์ ์์ต๋๋ค. ์ด ํธ์ถ์ ํ์ธํ๋ ๊ฒ์ด ์ข์ต๋๋ค. snprintf(์ ์ฒด ๊ฒฝ๋ก, PATH_MAX, ....).
์ค๋ณต ์กฐ๊ฑด
static void
inRepos(STREAM in, unsigned int read)
{
SERVER_DWORD add = 4 - read % 4;
if (add < 4 && add > 0)
{
....
}
}
ะัะพะฒะตัะบะฐ ์ถ๊ฐ > 0 ์ฌ๊ธฐ์๋ ํ์ํ์ง ์์ต๋๋ค. ๋ณ์๋ ํญ์ XNUMX๋ณด๋ค ํด ๊ฒ์ ๋๋ค. % 4 ์ฝ์ ๋๋์ ์ ๋๋จธ์ง ๋ถ๋ถ์ ๋ฐํํ์ง๋ง ๊ฒฐ์ฝ 4์ ๊ฐ์ ์๋ ์์ต๋๋ค.
xrdp
- xrdp - ํ๋กํ ์ฝ ๊ตฌํ. Apache 2.0 ๋ผ์ด์ผ์ค์ ๋ฐ๋ผ ๋ฐฐํฌ๋ฉ๋๋ค.
- xorgxrdp - xrdp์ ํจ๊ป ์ฌ์ฉํ๊ธฐ ์ํ Xorg ๋๋ผ์ด๋ฒ ์ธํธ์ ๋๋ค. ๋ผ์ด์ผ์ค - X11(MIT์ ์ ์ฌํ์ง๋ง ๊ด๊ณ ์ ์ฌ์ฉ์ด ๊ธ์ง๋จ)
ํ๋ก์ ํธ ๊ฐ๋ฐ์ rdesktop ๋ฐ FreeRDP์ ๊ฒฐ๊ณผ๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ํฉ๋๋ค. ์ฒ์์๋ ๊ทธ๋ํฝ ์์ ์ ์ํด ๋ณ๋์ VNC ์๋ฒ๋ RDP๋ฅผ ์ง์ํ๋ ํน์ X11 ์๋ฒ(X11rdp)๋ฅผ ์ฌ์ฉํด์ผ ํ์ง๋ง xorgxrdp์ ์ถํ์ผ๋ก ๊ทธ ํ์์ฑ์ด ์ฌ๋ผ์ก์ต๋๋ค.
์ด ๊ธฐ์ฌ์์๋ xorgxrdp๋ฅผ ๋ค๋ฃจ์ง ์์ต๋๋ค.
xrdp ํ๋ก์ ํธ๋ ์ด์ ํ๋ก์ ํธ์ ๋ง์ฐฌ๊ฐ์ง๋ก ๋งค์ฐ ์์ผ๋ฉฐ ์ฝ 80๋ง ์ค์ ํฌํจํฉ๋๋ค.
๋ ๋ง์ ์คํ
static int
rfx_encode_format_rgb(const char *rgb_data, int width, int height,
int stride_bytes, int pixel_format,
uint8 *r_buf, uint8 *g_buf, uint8 *b_buf)
{
....
switch (pixel_format)
{
case RFX_FORMAT_BGRA:
....
while (x < 64)
{
*lr_buf++ = r;
*lg_buf++ = g;
*lb_buf++ = r; // <=
x++;
}
....
}
....
}
์ด ์ฝ๋๋ RemoteFX์ฉ jpeg2000 ์ฝ๋ฑ์ ๊ตฌํํ๋ librfxcodec ๋ผ์ด๋ธ๋ฌ๋ฆฌ์์ ๊ฐ์ ธ์จ ๊ฒ์ ๋๋ค. ์ฌ๊ธฐ์๋ ๋ถ๋ช ํ ๊ทธ๋ํฝ ๋ฐ์ดํฐ ์ฑ๋์ด ํผํฉ๋์ด ์์ต๋๋ค. "ํ๋์"๋์ "๋นจ๊ฐ์"์ด ๊ธฐ๋ก๋ฉ๋๋ค. ์ด ์ค๋ฅ๋ ๋ณต์ฌ-๋ถ์ฌ๋ฃ๊ธฐ ๊ฒฐ๊ณผ๋ก ๋ํ๋ ๊ฐ๋ฅ์ฑ์ด ๋์ต๋๋ค.
๋น์ทํ ๊ธฐ๋ฅ์์ ๊ฐ์ ๋ฌธ์ ๊ฐ ๋ฐ์ํ์ต๋๋ค rfx_encode_format_argb, ๋ถ์๊ธฐ๋ ๋ํ ์ฐ๋ฆฌ์๊ฒ ๋ค์๊ณผ ๊ฐ์ด ๋งํ์ต๋๋ค.
while (x < 64)
{
*la_buf++ = a;
*lr_buf++ = r;
*lg_buf++ = g;
*lb_buf++ = r;
x++;
}
๋ฐฐ์ด ์ ์ธ
// evdev-map.c
int xfree86_to_evdev[137-8+1] = {
....
};
// genkeymap.c
extern int xfree86_to_evdev[137-8];
int main(int argc, char **argv)
{
....
for (i = 8; i <= 137; i++) /* Keycodes */
{
if (is_evdev)
e.keycode = xfree86_to_evdev[i-8];
....
}
....
}
์ด ๋ ํ์ผ์ ๋ฐฐ์ด ์ ์ธ๊ณผ ์ ์๋ ํธํ๋์ง ์์ต๋๋ค. ํฌ๊ธฐ๋ 1์ฉ ๋ค๋ฆ ๋๋ค. ๊ทธ๋ฌ๋ ์ค๋ฅ๋ ๋ฐ์ํ์ง ์์ต๋๋ค. ์ฌ๋ฐ๋ฅธ ํฌ๊ธฐ๋ evdev-map.c ํ์ผ์ ์ง์ ๋์ด ์์ผ๋ฏ๋ก ๋ฒ์๋ฅผ ๋ฒ์ด๋๋ ์ผ์ด ์์ต๋๋ค. ๋ฐ๋ผ์ ์ด๊ฒ์ ์ฝ๊ฒ ๊ณ ์น ์ ์๋ ๋ฒ๊ทธ์ผ ๋ฟ์ ๋๋ค.
์๋ชป๋ ๋น๊ต
// common/parse.h
#if defined(B_ENDIAN) || defined(NEED_ALIGN)
#define in_uint16_le(s, v) do
....
#else
#define in_uint16_le(s, v) do
{
(v) = *((unsigned short*)((s)->p));
(s)->p += 2;
} while (0)
#endif
int
xrdp_caps_process_confirm_active(struct xrdp_rdp *self, struct stream *s)
{
int cap_len;
....
in_uint16_le(s, cap_len);
....
if ((cap_len < 0) || (cap_len > 1024 * 1024))
{
....
}
....
}
ํจ์๋ ์ ํ ๋ณ์๋ฅผ ์ฝ์ต๋๋ค. ์๋ช ๋์ง ์์ ์งง์ ๋ค์๊ณผ ๊ฐ์ ๋ณ์์ INT. ๋ถํธ ์๋ ๋ณ์๋ฅผ ์ฝ๊ณ ๊ทธ ๊ฒฐ๊ณผ๋ฅผ ๋ ํฐ ๋ณ์์ ํ ๋นํ๋ฏ๋ก ์ฌ๊ธฐ์๋ ๊ฒ์ฌ๊ฐ ํ์ํ์ง ์์ต๋๋ค. ๋ฐ๋ผ์ ๋ณ์๋ ์์ ๊ฐ์ ๊ฐ์ง ์ ์์ต๋๋ค.
๋ถํ์ํ ์ ๊ฒ
int EXPORT_CC
libxrdp_send_pointer(struct xrdp_session *session, int cache_idx,
char *data, char *mask, int x, int y, int bpp)
{
....
if ((bpp == 15) && (bpp != 16) && (bpp != 24) && (bpp != 32))
{
g_writeln("libxrdp_send_pointer: error");
return 1;
}
....
}
๋ถํ๋ฑ ๊ฒ์ฌ๋ ์ฒ์์ ์ด๋ฏธ ๋น๊ต๊ฐ ์์๊ธฐ ๋๋ฌธ์ ์ฌ๊ธฐ์๋ ์๋ฏธ๊ฐ ์์ต๋๋ค. ์ด๋ ์คํ์ผ ๊ฐ๋ฅ์ฑ์ด ๋์ผ๋ฉฐ ๊ฐ๋ฐ์๊ฐ ์ฐ์ฐ์๋ฅผ ์ฌ์ฉํ๋ ค๊ณ ํ์ต๋๋ค. || ์๋ชป๋ ์ธ์๋ฅผ ํํฐ๋งํฉ๋๋ค.
๊ฒฐ๋ก
๊ฐ์ฌ ๊ณผ์ ์์ ์ฌ๊ฐํ ์ค๋ฅ๋ ๋ฐ๊ฒฌ๋์ง ์์์ง๋ง ๋ง์ ๋จ์ ์ด ๋ฐ๊ฒฌ๋์์ต๋๋ค. ๊ทธ๋ฌ๋ ์ด๋ฌํ ๋์์ธ์ ๋น๋ก ๋ฒ์๋ ์์ง๋ง ๋ง์ ์์คํ
์์ ์ฌ์ฉ๋ฉ๋๋ค. ์๊ท๋ชจ ํ๋ก์ ํธ๋ผ๊ณ ๋ฐ๋์ ์ค๋ฅ๊ฐ ๋ง์ ๊ฒ์ ์๋๋ฏ๋ก ์๊ท๋ชจ ํ๋ก์ ํธ์์๋ง ๋ถ์๊ธฐ์ ์ฑ๋ฅ์ ํ๋จํด์๋ ์ ๋ฉ๋๋ค. ์ด์ ๋ํ ์์ธํ ๋ด์ฉ์ "
๋น์ฌ์์ PVS-Studio ํ๊ฐํ์ ๋ค์ด๋ก๋ํ ์ ์์ต๋๋ค.
์ด ๊ธฐ์ฌ๋ฅผ ์์ด๊ถ ์ฒญ์ค๊ณผ ๊ณต์ ํ๋ ค๋ฉด Sergey Larin ๋ฒ์ญ ๋งํฌ๋ฅผ ์ฌ์ฉํ์ญ์์ค.
์ถ์ฒ : habr.com