Skip to content

Commit

Permalink
Begin work on XDGBDS compliance and overrideable configs
Browse files Browse the repository at this point in the history
  • Loading branch information
62832 committed Mar 15, 2024
1 parent 90e9db2 commit 119a5ff
Show file tree
Hide file tree
Showing 9 changed files with 151 additions and 56 deletions.
17 changes: 17 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
*.mo
*.la
*.lo
*.class
*.jar
.deps
.libs

Expand All @@ -10,3 +12,18 @@ CMakeCache.txt
Makefile
Makefile.in
config.h

*.xml
*.man
*.service
cmake_install.cmake
cmake_uninstall.cmake
install_manifest.txt
tests/unit/[a-z]*
!tests/unit/[a-z]*\.

timestamp
vncserver
!unix/vncserver
vncsession
vncsession-start
36 changes: 30 additions & 6 deletions common/os/os.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -32,19 +32,20 @@
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#else
#include <windows.h>
#include <wininet.h> /* MinGW needs it */
#include <shlobj.h>
#endif

static const char* gethomedir(bool userDir)
static const char* getvncdir(bool userDir, const char *xdg_env, const char *xdg_def)
{
static char dir[PATH_MAX];

#ifndef WIN32
char *homedir;
char *homedir, *xdgdir;
uid_t uid;
struct passwd *passwd;
#else
Expand All @@ -66,7 +67,20 @@ static const char* gethomedir(bool userDir)
if (userDir)
return homedir;

// check if (deprecated) legacy path exists and use that if so
snprintf(dir, sizeof(dir), "%s/.vnc", homedir);
struct stat st;

if (stat(dir, &st) == 0)
return dir;

if (xdg_def != NULL) {
xdgdir = getenv(xdg_env);
if (xdgdir != NULL)
snprintf(dir, sizeof(dir), "%s/tigervnc", xdgdir);
else
snprintf(dir, sizeof(dir), "%s/%s/tigervnc", homedir, xdg_def);
}

return dir;
#else
Expand All @@ -90,13 +104,23 @@ static const char* gethomedir(bool userDir)
#endif
}

const char* os::getvnchomedir()
const char* os::getuserhomedir()
{
return gethomedir(false);
return getvncdir(true, NULL, NULL);
}

const char* os::getuserhomedir()
const char* os::getvncconfigdir()
{
return gethomedir(true);
return getvncdir(false, "XDG_CONFIG_HOME", ".config");
}

const char* os::getvncstatedir()
{
return getvncdir(false, "XDG_STATE_HOME", ".local/state");
}

/* deprecated */
const char* os::getvnchomedir()
{
return getvncdir(false, NULL, NULL);
}
30 changes: 26 additions & 4 deletions common/os/os.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,22 +23,44 @@
namespace os {

/*
* Get VNC home directory ($HOME/.vnc or %APPDATA%/vnc/).
* Get user home directory.
* If HOME environment variable is set then it is used.
* Otherwise home directory is obtained via getpwuid function.
*
* Returns NULL on failure.
*/
const char* getvnchomedir();
const char* getuserhomedir();

/*
* Get user home directory.
* Get VNC config directory. On Unix-like systems, this is either:
* - $XDG_CONFIG_HOME/tigervnc
* - $HOME/.config/tigervnc
* On Windows, this is simply %APPDATA%/vnc/.
*
* Returns NULL on failure.
*/
const char* getvncconfigdir();

/*
* Get VNC state (logs) directory. On Unix-like systems, this is either:
* - $XDG_STATE_HOME/tigervnc
* - $HOME/.local/state/tigervnc
* On Windows, this is simply %APPDATA%/vnc/.
*
* Returns NULL on failure.
*/
const char* getvncstatedir();

/*
* Get legacy VNC home directory ($HOME/.vnc on Unix-likes).
* If HOME environment variable is set then it is used.
* Otherwise home directory is obtained via getpwuid function.
*
* Returns NULL on failure.
*
* Deprecated.
*/
const char* getuserhomedir();
const char* getvnchomedir();

}

Expand Down
26 changes: 13 additions & 13 deletions common/rfb/CSecurityTLS.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -58,27 +58,27 @@

using namespace rfb;

static const char* homedirfn(const char* fn);
static const char* configdirfn(const char* fn);

StringParameter CSecurityTLS::X509CA("X509CA", "X509 CA certificate",
homedirfn("x509_ca.pem"),
configdirfn("x509_ca.pem"),
ConfViewer);
StringParameter CSecurityTLS::X509CRL("X509CRL", "X509 CRL file",
homedirfn("x509_crl.pem"),
configdirfn("x509_crl.pem"),
ConfViewer);

static LogWriter vlog("TLS");

static const char* homedirfn(const char* fn)
static const char* configdirfn(const char* fn)
{
static char full_path[PATH_MAX];
const char* homedir;
const char* configdir;

homedir = os::getvnchomedir();
if (homedir == NULL)
configdir = os::getvncconfigdir();
if (configdir == NULL)
return "";

snprintf(full_path, sizeof(full_path), "%s/%s", homedir, fn);
snprintf(full_path, sizeof(full_path), "%s/%s", configdir, fn);

return full_path;
}
Expand Down Expand Up @@ -308,7 +308,7 @@ void CSecurityTLS::checkSession()
int err;
bool hostname_match;

const char *homeDir;
const char *configDir;
gnutls_datum_t info;
size_t len;

Expand Down Expand Up @@ -385,14 +385,14 @@ void CSecurityTLS::checkSession()

/* Certificate has some user overridable problems, so TOFU time */

homeDir = os::getvnchomedir();
if (homeDir == NULL) {
throw AuthFailureException("Could not obtain VNC home directory "
configDir = os::getvncconfigdir();
if (configDir == NULL) {
throw AuthFailureException("Could not obtain VNC config directory "
"path for known hosts storage");
}

std::string dbPath;
dbPath = (std::string)homeDir + "/x509_known_hosts";
dbPath = (std::string)configDir + "/x509_known_hosts";

err = gnutls_verify_stored_pubkey(dbPath.c_str(), NULL,
client->getServerName(), NULL,
Expand Down
10 changes: 5 additions & 5 deletions unix/vncpasswd/vncpasswd.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -156,13 +156,13 @@ int main(int argc, char** argv)
}

if (fname[0] == '\0') {
const char *homeDir = os::getvnchomedir();
if (homeDir == NULL) {
fprintf(stderr, "Can't obtain VNC home directory\n");
const char *configDir = os::getvncconfigdir();
if (configDir == NULL) {
fprintf(stderr, "Can't obtain VNC config directory\n");
exit(1);
}
mkdir(homeDir, 0777);
snprintf(fname, sizeof(fname), "%s/passwd", homeDir);
mkdir(configDir, 0777);
snprintf(fname, sizeof(fname), "%s/passwd", configDir);
}

while (true) {
Expand Down
12 changes: 10 additions & 2 deletions unix/vncserver/vncserver.in
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,15 @@
# your site
#

# Start with legacy ~/.vnc user dir
$vncUserDir = "$ENV{HOME}/.vnc";
if (stat($vncUserDir)) {
warn "~/.vnc is deprecated, please migrate to XDGBDS-compliant paths!";
} else {
# Legacy path doesn't exist, start using new XDG-alike path
$vncUserDir = "$ENV{HOME}/.config/tigervnc";
}

$vncUserConfig = "$vncUserDir/config";

$vncSystemConfigDir = "@CMAKE_INSTALL_FULL_SYSCONFDIR@/tigervnc";
Expand Down Expand Up @@ -111,8 +119,8 @@ $default_opts{pn} = undef;
# Load user-overrideable system defaults
LoadConfig($vncSystemConfigDefaultsFile);

# Then the user's settings
LoadConfig($vncUserConfig);
# Then the user's settings (location overrideable by previous system defaults)
LoadConfig($config{'userconfig'} || $vncUserConfig);

# And then override anything set above if mandatory settings exist.
# WARNING: "Mandatory" is used loosely here! As the man page says,
Expand Down
16 changes: 8 additions & 8 deletions vncviewer/ServerDialog.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -315,12 +315,12 @@ void ServerDialog::loadServerHistory()
return;
#endif

const char* homeDir = os::getvnchomedir();
if (homeDir == NULL)
throw Exception(_("Could not obtain the home directory path"));
const char* stateDir = os::getvncstatedir();
if (stateDir == NULL)
throw Exception(_("Could not obtain the state directory path"));

char filepath[PATH_MAX];
snprintf(filepath, sizeof(filepath), "%s/%s", homeDir, SERVER_HISTORY);
snprintf(filepath, sizeof(filepath), "%s/%s", stateDir, SERVER_HISTORY);

/* Read server history from file */
FILE* f = fopen(filepath, "r");
Expand Down Expand Up @@ -381,12 +381,12 @@ void ServerDialog::saveServerHistory()
return;
#endif

const char* homeDir = os::getvnchomedir();
if (homeDir == NULL)
throw Exception(_("Could not obtain the home directory path"));
const char* stateDir = os::getvncstatedir();
if (stateDir == NULL)
throw Exception(_("Could not obtain the state directory path"));

char filepath[PATH_MAX];
snprintf(filepath, sizeof(filepath), "%s/%s", homeDir, SERVER_HISTORY);
snprintf(filepath, sizeof(filepath), "%s/%s", stateDir, SERVER_HISTORY);

/* Write server history to file */
FILE* f = fopen(filepath, "w+");
Expand Down
16 changes: 8 additions & 8 deletions vncviewer/parameters.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -629,11 +629,11 @@ void saveViewerParameters(const char *filename, const char *servername) {
return;
#endif

const char* homeDir = os::getvnchomedir();
if (homeDir == NULL)
throw Exception(_("Could not obtain the home directory path"));
const char* configDir = os::getvncconfigdir();
if (configDir == NULL)
throw Exception(_("Could not obtain the config directory path"));

snprintf(filepath, sizeof(filepath), "%s/default.tigervnc", homeDir);
snprintf(filepath, sizeof(filepath), "%s/default.tigervnc", configDir);
} else {
snprintf(filepath, sizeof(filepath), "%s", filename);
}
Expand Down Expand Up @@ -733,11 +733,11 @@ char* loadViewerParameters(const char *filename) {
return loadFromReg();
#endif

const char* homeDir = os::getvnchomedir();
if (homeDir == NULL)
throw Exception(_("Could not obtain the home directory path"));
const char* configDir = os::getvncconfigdir();
if (configDir == NULL)
throw Exception(_("Could not obtain the config directory path"));

snprintf(filepath, sizeof(filepath), "%s/default.tigervnc", homeDir);
snprintf(filepath, sizeof(filepath), "%s/default.tigervnc", configDir);
} else {
snprintf(filepath, sizeof(filepath), "%s", filename);
}
Expand Down
44 changes: 34 additions & 10 deletions vncviewer/vncviewer.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -429,17 +429,34 @@ static void init_fltk()
#endif
}

static void mkvnchomedir()
static int mkvncdir(const char *dir)
{
// Create .vnc in the user's home directory if it doesn't already exist
const char* homeDir = os::getvnchomedir();
if (homeDir == NULL) {
vlog.error(_("Could not obtain the home directory path"));
} else {
int result = mkdir(homeDir, 0755);
if (result == -1 && errno != EEXIST)
vlog.error(_("Could not create VNC home directory: %s"), strerror(errno));
int result = mkdir(dir, 0755);
if (result == -1 && errno != EEXIST) {
vlog.error(_("Could not create VNC directory %s: %s"), dir, strerror(errno));
return result;
}
return 0;
}

static void mkdirrecursive(const char *dir)
{
char *path = strdup(dir);
char *p;

for (p = path + 1; *p; p++) {
if (*p == '/') {
*p = '\0';
if (mkvncdir(path) != 0) {
free(path);
return;
}
*p = '/';
}
}

mkvncdir(path);
free(path);
}

static void usage(const char *programName)
Expand Down Expand Up @@ -728,7 +745,14 @@ int main(int argc, char** argv)

migrateDeprecatedOptions();

mkvnchomedir();
#ifndef WIN32
// Check if config and state dirs are both the same legacy ~/.vnc dir
struct stat st;
if (stat(os::getvnchomedir(), &st) == 0)
vlog.info(_("~/.vnc is deprecated, please migrate to XDGBDS-compliant paths!"));
#endif
mkdirrecursive(os::getvncconfigdir());
mkdirrecursive(os::getvncstatedir());

CSecurity::upg = &dlg;
#if defined(HAVE_GNUTLS) || defined(HAVE_NETTLE)
Expand Down

0 comments on commit 119a5ff

Please sign in to comment.