Skip to content

Commit

Permalink
Add option allowing to connect only the user owning the running session
Browse files Browse the repository at this point in the history
Checks, whether the user who is trying to authenticate is already logged
into the running session in order to allow or reject the connection.
This is expected to be used with 'plain' security type in combination
with 'PlainUsers=*' option allowing everyone to connect to the session.
  • Loading branch information
grulja committed Jul 29, 2024
1 parent c407586 commit cc02819
Show file tree
Hide file tree
Showing 5 changed files with 99 additions and 0 deletions.
4 changes: 4 additions & 0 deletions common/rfb/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,10 @@ if (NETTLE_FOUND)
${NETTLE_LIBRARY_DIRS} ${GMP_LIBRARY_DIRS})
endif()

if (LIBSYSTEMD_FOUND)
target_link_libraries(rfb ${LIBSYSTEMD_LIBRARIES})
endif()

if(UNIX)
libtool_create_control_file(rfb)
endif()
8 changes: 8 additions & 0 deletions common/rfb/ServerCore.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -99,3 +99,11 @@ rfb::BoolParameter rfb::Server::queryConnect
("QueryConnect",
"Prompt the local user to accept or reject incoming connections.",
false);
#ifdef HAVE_LIBSYSTEMD
rfb::BoolParameter rfb::Server::approveLoggedUserOnly
("ApproveLoggedUserOnly",
"Approve only the user who is currently logged into the session."
"This is expected to be combined with 'plain' security type and with "
"'PlainUsers=*' option allowing everyone to connect to the session.",
false);
#endif
3 changes: 3 additions & 0 deletions common/rfb/ServerCore.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,9 @@ namespace rfb {
static BoolParameter sendCutText;
static BoolParameter acceptSetDesktopSize;
static BoolParameter queryConnect;
#ifdef HAVE_LIBSYSTEMD
static BoolParameter approveLoggedUserOnly;
#endif

};

Expand Down
77 changes: 77 additions & 0 deletions common/rfb/VNCServerST.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@
#include <stdlib.h>

#include <network/Socket.h>
#include <pwd.h>

#include <rfb/ComparingUpdateTracker.h>
#include <rfb/Exception.h>
Expand All @@ -69,6 +70,9 @@
#include <rfb/util.h>
#include <rfb/ledStates.h>

#ifdef HAVE_LIBSYSTEMD
# include <systemd/sd-login.h>
#endif

using namespace rfb;

Expand Down Expand Up @@ -661,6 +665,69 @@ void VNCServerST::handleTimeout(Timer* t)
}
}

#ifdef HAVE_LIBSYSTEMD
bool VNCServerST::checkUserLogged(const char* userName)
{
bool ret = false;
bool noUserSession = true;
int res;
char **sessions;

res = sd_get_sessions(&sessions);
if (res < 0) {
slog.debug("logind: failed to get sessions");
return false;
}

if (sessions != nullptr && sessions[0] != nullptr) {
for (int i = 0; sessions[i]; i++) {
uid_t uid;
char *clazz;

res = sd_session_get_uid(sessions[i], &uid);
if (res < 0) {
slog.debug("logind: failed to determine user id of session");
break;
}

res = sd_session_get_class(sessions[i], &clazz);
if (res < 0) {
slog.debug("logind: failed to determine session class");
break;
}

if (uid != 0 && strcmp(clazz, "user") == 0) {
noUserSession = false;
}
free(clazz);

struct passwd *pw = getpwnam(userName);
if (!pw) {
slog.debug("logind: user not found");
break;
}

if (uid == pw->pw_uid) {
ret = true;
break;
}
}
}

if (sessions) {
for (int i = 0; sessions[i]; i ++) {
free(sessions[i]);
}

free (sessions);
}

// If we didn't find a matching user, we can still allow the user
// to log in if there is no user session yet.
return !ret ? noUserSession : ret;
}
#endif

void VNCServerST::queryConnection(VNCSConnectionST* client,
const char* userName)
{
Expand All @@ -680,6 +747,16 @@ void VNCServerST::queryConnection(VNCSConnectionST* client,
return;
}

#ifdef HAVE_LIBSYSTEMD
// - Only owner of the session can be approved
if (rfb::Server::approveLoggedUserOnly &&
!checkUserLogged(userName)) {
approveConnection(client->getSock(), false,
"The user is not owner of the running session");
return;
}
#endif

// - Are we configured to do queries?
if (!rfb::Server::queryConnect &&
!client->getSock()->requiresQuery()) {
Expand Down
7 changes: 7 additions & 0 deletions common/rfb/VNCServerST.h
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,13 @@ namespace rfb {
// - Check how many of the clients are authenticated.
int authClientCount();

#ifdef HAVE_LIBSYSTEMD
// - Check whether user is logged into a session
// Returns true if user is already logged or there is no
// user session at all.
bool checkUserLogged(const char* userName);
#endif

bool needRenderedCursor();
void startFrameClock();
void stopFrameClock();
Expand Down

0 comments on commit cc02819

Please sign in to comment.