Skip to content

Commit

Permalink
Merge pull request #1737 from 62832/fix-1195
Browse files Browse the repository at this point in the history
Allow for alternative user config locations, deprecate `~/.vnc` in favour of XDG Base Directory Specification paths
  • Loading branch information
samhed authored May 7, 2024
2 parents 6d19e96 + 337c136 commit 3db859e
Show file tree
Hide file tree
Showing 30 changed files with 380 additions and 167 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,6 @@ CMakeCache.txt
Makefile
Makefile.in
config.h
cmake_install.cmake
cmake_uninstall.cmake
install_manifest.txt
52 changes: 39 additions & 13 deletions common/os/os.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -24,27 +24,30 @@
#include <os/os.h>

#include <assert.h>
#include <sys/types.h>
#include <sys/stat.h>

#ifndef WIN32
#include <pwd.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
#else
#include <windows.h>
#include <wininet.h> /* MinGW needs it */
#include <shlobj.h>
#define stat _stat
#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];
static char dir[PATH_MAX], legacy[PATH_MAX];
struct stat st;

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

snprintf(dir, sizeof(dir), "%s/.vnc", homedir);
xdgdir = getenv(xdg_env);
if (xdgdir != NULL && xdgdir[0] == '/')
snprintf(dir, sizeof(dir), "%s/tigervnc", xdgdir);
else
snprintf(dir, sizeof(dir), "%s/%s/tigervnc", homedir, xdg_def);

return dir;
snprintf(legacy, sizeof(legacy), "%s/.vnc", homedir);
#else
(void) xdg_def;
(void) xdg_env;

if (userDir)
ret = SHGetSpecialFolderPath(NULL, dir, CSIDL_PROFILE, FALSE);
else
Expand All @@ -81,22 +91,38 @@ static const char* gethomedir(bool userDir)
if (userDir)
return dir;

if (strlen(dir) + strlen("\\vnc") >= sizeof(dir))
ret = SHGetSpecialFolderPath(NULL, legacy, CSIDL_APPDATA, FALSE);

if (ret == FALSE)
return NULL;

strcat(dir, "\\vnc");
if (strlen(dir) + strlen("\\TigerVNC") >= sizeof(dir))
return NULL;
if (strlen(legacy) + strlen("\\vnc") >= sizeof(legacy))
return NULL;

return dir;
strcat(dir, "\\TigerVNC");
strcat(legacy, "\\vnc");
#endif
return (stat(dir, &st) != 0 && stat(legacy, &st) == 0) ? legacy : dir;
}

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::getvncdatadir()
{
return getvncdir(false, "XDG_DATA_HOME", ".local/share");
}

const char* os::getvncstatedir()
{
return getvncdir(false, "XDG_STATE_HOME", ".local/state");
}
34 changes: 28 additions & 6 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.
* If HOME environment variable is set then it is used.
* Otherwise home directory is obtained via getpwuid function.
* Get VNC config directory. On Unix-like systems, this is either:
* - $XDG_CONFIG_HOME/tigervnc
* - $HOME/.config/tigervnc
* On Windows, this is simply %APPDATA%/TigerVNC/.
*
* Returns NULL on failure.
*/
const char* getuserhomedir();
const char* getvncconfigdir();

/*
* Get VNC data directory used for X.509 known hosts.
* On Unix-like systems, this is either:
* - $XDG_DATA_HOME/tigervnc
* - $HOME/.local/share/tigervnc
* On Windows, this is simply %APPDATA%/TigerVNC/.
*
* Returns NULL on failure.
*/
const char* getvncdatadir();

/*
* 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%/TigerVNC/.
*
* Returns NULL on failure.
*/
const char* getvncstatedir();

}

Expand Down
27 changes: 13 additions & 14 deletions common/rfb/CSecurityTLS.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -58,28 +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 +307,7 @@ void CSecurityTLS::checkSession()
int err;
bool hostname_match;

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

Expand Down Expand Up @@ -385,14 +384,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 "
hostsDir = os::getvncdatadir();
if (hostsDir == NULL) {
throw AuthFailureException("Could not obtain VNC data directory "
"path for known hosts storage");
}

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

err = gnutls_verify_stored_pubkey(dbPath.c_str(), NULL,
client->getServerName(), NULL,
Expand Down
2 changes: 1 addition & 1 deletion contrib/packages/rpm/el7/SOURCES/10-libvnc.conf
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,5 @@
# Identifier "Screen0
# DefaultDepth 16
# Option "SecurityTypes" "VncAuth"
# Option "PasswordFile" "/root/.vnc/passwd"
# Option "PasswordFile" "/root/.config/tigervnc/passwd"
#EndSection
2 changes: 1 addition & 1 deletion contrib/packages/rpm/el8/SOURCES/10-libvnc.conf
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,5 @@
# Identifier "Screen0
# DefaultDepth 16
# Option "SecurityTypes" "VncAuth"
# Option "PasswordFile" "/root/.vnc/passwd"
# Option "PasswordFile" "/root/.config/tigervnc/passwd"
#EndSection
2 changes: 1 addition & 1 deletion contrib/packages/rpm/el9/SOURCES/10-libvnc.conf
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,5 @@
# Identifier "Screen0
# DefaultDepth 16
# Option "SecurityTypes" "VncAuth"
# Option "PasswordFile" "/root/.vnc/passwd"
# Option "PasswordFile" "/root/.config/tigervnc/passwd"
#EndSection
4 changes: 4 additions & 0 deletions java/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
*.class
*.jar
.idea/
timestamp
9 changes: 4 additions & 5 deletions java/com/tigervnc/rfb/CSecurityTLS.java
Original file line number Diff line number Diff line change
Expand Up @@ -89,13 +89,13 @@ public CSecurityTLS(boolean _anon)
public static String getDefaultCA() {
if (UserPreferences.get("viewer", "x509ca") != null)
return UserPreferences.get("viewer", "x509ca");
return FileUtils.getVncHomeDir()+"x509_ca.pem";
return FileUtils.getVncConfigDir()+"x509_ca.pem";
}

public static String getDefaultCRL() {
if (UserPreferences.get("viewer", "x509crl") != null)
return UserPreferences.get("viewer", "x509crl");
return FileUtils.getVncHomeDir()+"x509_crl.pem";
return FileUtils.getVncConfigDir()+"x509_crl.pem";
}

public static void setDefaults()
Expand Down Expand Up @@ -277,12 +277,12 @@ public void checkServerTrusted(X509Certificate[] chain, String authType)
"do you want to continue?"))
throw new AuthFailureException("server certificate has expired");
}
File vncDir = new File(FileUtils.getVncHomeDir());
File vncDir = new File(FileUtils.getVncDataDir());
if (!vncDir.exists()) {
try {
vncDir.mkdir();
} catch(SecurityException e) {
throw new AuthFailureException("Could not obtain VNC home directory "+
throw new AuthFailureException("Could not obtain VNC data directory "+
"path for known hosts storage");
}
}
Expand Down Expand Up @@ -356,7 +356,6 @@ public void checkServerTrusted(X509Certificate[] chain, String authType)
private void store_pubkey(File dbPath, String serverName, String pk)
{
ArrayList<String> lines = new ArrayList<String>();
File vncDir = new File(FileUtils.getVncHomeDir());
try {
if (dbPath.exists()) {
FileReader db = new FileReader(dbPath);
Expand Down
48 changes: 38 additions & 10 deletions java/com/tigervnc/vncviewer/FileUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,11 @@

import com.tigervnc.rfb.LogWriter;

import java.io.File;

public class FileUtils {

public static final String getHomeDir() {
public static String getHomeDir() {
String homeDir = null;
try {
String os = System.getProperty("os.name");
Expand Down Expand Up @@ -56,21 +58,47 @@ public static final String getHomeDir() {
vlog.error("Cannot access os.name system property:"+e.getMessage());
}

String separator = null;
try {
separator = Character.toString(java.io.File.separatorChar);
} catch(java.security.AccessControlException e) {
vlog.error("Cannot access file.separator system property:"+e.getMessage());
return homeDir + getFileSeparator();
}

public static String getVncDir(String xdgEnv, String xdgDefault) {
File legacyDir = new File(getHomeDir() + ".vnc" + getFileSeparator());
String os = System.getProperty("os.name");

if (os.startsWith("Windows")) {
File newDir = new File(System.getenv("APPDATA") + getFileSeparator() + "TigerVNC" + getFileSeparator());
if (!newDir.exists()) {
newDir.mkdirs();
}
File[] existingFiles = legacyDir.listFiles();
if (existingFiles != null) {
for (File file : existingFiles) {
file.renameTo(new File(newDir.getPath() + file.getName()));
}
legacyDir.delete();
}
return newDir.getPath();
} else {
if (legacyDir.exists()) {
vlog.info("WARNING: ~/.vnc is deprecated, please consult 'man vncviewer' for paths to migrate to.");
return legacyDir.getPath();
}
String xdgBaseDir = System.getenv(xdgEnv);
return (xdgBaseDir != null && xdgBaseDir.startsWith("/"))
? xdgBaseDir + getFileSeparator() + "tigervnc" + getFileSeparator()
: getHomeDir() + xdgDefault + getFileSeparator() + "tigervnc" + getFileSeparator();
}
}

return homeDir + getFileSeparator();
public static String getVncConfigDir() {
return getVncDir("XDG_CONFIG_HOME", ".config");
}

public static final String getVncHomeDir() {
return getHomeDir()+".vnc"+getFileSeparator();
public static String getVncDataDir() {
return getVncDir("XDG_DATA_HOME", ".local" + getFileSeparator() + "share");
}

public static final String getFileSeparator() {
public static String getFileSeparator() {
String separator = null;
try {
separator = Character.toString(java.io.File.separatorChar);
Expand Down
18 changes: 1 addition & 17 deletions java/com/tigervnc/vncviewer/Parameters.java
Original file line number Diff line number Diff line change
Expand Up @@ -325,13 +325,6 @@ public static void saveViewerParameters(String filename, String servername) {
if (filename == null || filename.isEmpty()) {
saveToReg(servername);
return;
/*
String homeDir = FileUtils.getVncHomeDir();
if (homeDir == null)
throw new Exception("Failed to read configuration file, "+
"can't obtain home directory path.");
filepath = homeDir.concat("default.tigervnc");
*/
} else {
filepath = filename;
}
Expand Down Expand Up @@ -385,16 +378,7 @@ public static String loadViewerParameters(String filename) throws Exception {

String filepath;
if (filename == null) {

return loadFromReg();

/*
String homeDir = FileUtils.getVncHomeDir();
if (homeDir == null)
throw new Exception("Failed to read configuration file, "+
"can't obtain home directory path.");
filepath = homeDir.concat("default.tigervnc");
*/
return loadFromReg();
} else {
filepath = filename;
}
Expand Down
Loading

0 comments on commit 3db859e

Please sign in to comment.