Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for RFB protocol version 3.7 and 3.8 #2549

Open
wants to merge 2 commits into
base: devel
Choose a base branch
from

Conversation

Jesse-Bakker
Copy link

No description provided.

@matt335672
Copy link
Member

@Jesse-Bakker - thanks for this.

It's been a busy week here, I'll get a proper review to you probably early next week now.

Copy link
Member

@matt335672 matt335672 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @Jesse-Bakker

There's a few comments below. Get back to me on anything I haven't explained well, or you disagree with.

vnc/vnc.c Show resolved Hide resolved
vnc/vnc.c Show resolved Hide resolved
vnc/vnc.c Outdated Show resolved Hide resolved
vnc/vnc.c Outdated Show resolved Hide resolved
vnc/vnc.c Show resolved Hide resolved
Copy link
Member

@matt335672 matt335672 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for that @Jesse-Bakker

A few comments below.

(v[n]) = '\0'; \
(s)->p++; \
} while (0)

/******************************************************************************/
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This isn't copying the string from the input buffer.

when the macro runs:-

  • (v) = (s)->p; sets err_reason to be (s)->p (which points into (s)->data)
  • (v[n]) = '\0'; writes a null into the input buffer
  • (s)->p++ advances one character along the buffer. This isn't useful, but you're not seeing any bad effects as the macro is only used at the end of the input.

I don't think it's good form to overwrite the input buffer in this way - you should be copying the string. Here's a possibility (not tested):-

#define in_str(s, n, v, vlen) do \
    { \
        int copylen = MIN((n), (vlen - 1)); \
        in_uint8a((s), (v), copylen); \
        (v)[copylen] = '\0'; \
        if ((n) > copylen) \
        { \
            in_uint8s((s), (n) - copylen); \
        } \
    } while (0)

Use with :-

char err_reason[128];
. . .
in_str(s, i, err_reason, sizeof(err_reason));

It's a pretty complex macro however.

if (g_strncmp(version_str, "RFB 003.00", 10) != 0)
{
version_str[11] = '\0';
LOG(LOG_LEVEL_ERROR, "Invalid server version string %s", version_str);
error = 1;
}
if (version_str[11] != '\n')
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Need an else if here.

If the previous test succeeds (invalid version string), the newline will be overwritten with a NUL for error reporting, and then this test will trigger too!

if (i <= 1024)
{
error = trans_force_read_s(v->trans, s, i);
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Logic problem here. If this line returns 0, the string is read again at line 1796 below.

Also, i is intrather than unsigned int, so the test against 1024 is not sufficient.

Suggest the following, if in_str() is redefined:-

char err_str[128];  // replaces char *err_str;
. . .
                // The client chooses the security type
                error = trans_force_read_s(v->trans, s, 1);
                if (error == 0)
                {
                    in_uint8(s, n_sec_lvls);
                    if (n_sec_lvls > 0)
                    {
                        error = trans_force_read_s(v->trans, s, n_sec_lvls);
                    }
                    else
                    {
                        // Server has closed the connection
                        error = 1;
                        g_snprintf(err_reason, sizeof(err_reason),
                                  "<reason unavailable>");
                        // Read size of reason
                        if (trans_force_read_s(v->trans, s, 4) == 0)
                        {
                            in_uint32_be(s, i);
                            if (i > 0 && i < sizeof(err_reason) &&
                                trans_force_read_s(v->trans, s, i) == 0)
                            {
                                in_str(s, i, err_reason, sizeof(err_reason));
                            }
                        }
                        LOG(LOG_LEVEL_ERROR, "Connection closed by server : %s",
                            err_reason);
                    }
                }

NB Lines need reformatting to keep width to 80 chars (see https://github.com/neutrinolabs/xrdp/wiki/Coding-Style)

{
in_str(s, err_reason, i);
v->server_msg(v, err_reason, 0);
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we get to this point, the server has disconnected, and yet error is still 0 (it should probably be 2).

Also, i can be negative again.

Suggest something like:-

            if (i != 0)
            {
                if (version < 8)
                {
                    g_snprintf(text, sizeof(text), "VNC password failed");
                }
                else
                {
                    g_snprintf(err_reason, sizeof(err_reason),
                               "<reason unavailable>");
                    if (trans_force_read_s(v->trans, s, 4) == 0)
                    {
                        in_uint32_be(s, i);
                        if (i > 0 && i < sizeof(err_reason) &&
                                trans_force_read_s(v->trans, s, i) == 0)
                        {
                            in_str(s, i, err_reason, sizeof(err_reason));
                        }
                    }
                    g_snprintf(text, sizeof(text), "VNC password failed : %s",
                               err_reason);
                }

                v->server_msg(v, text, 0);
                error = 2;
            }
            else
            {
                v->server_msg(v, "VNC password ok", 0);
            }

@matt335672
Copy link
Member

PS : Don't worry about the code check fails - we're looking at it. See #2567

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants