about summary refs log tree commit diff
path: root/surf.c
diff options
context:
space:
mode:
authorDmitry Bogatov <KAction@gnu.org>2016-05-29 11:56:51 +0200
committerQuentin Rameau <quinq@fifth.space>2016-07-05 13:01:56 +0200
commitcee8f0186ce3277add9b6a8ac07588be40f0f080 (patch)
tree237d094d90ca3497343b179e7a4d8c91b8f0e101 /surf.c
parentFix url parsing in load() (diff)
downloadsurf-cee8f0186ce3277add9b6a8ac07588be40f0f080.tar.gz
surf-cee8f0186ce3277add9b6a8ac07588be40f0f080.tar.bz2
surf-cee8f0186ce3277add9b6a8ac07588be40f0f080.zip
Check $HOME and home dir of $USER before getpwuid()->pw_dir
getpwnam(3) recommends to use $HOME instead of getpwuid()->pw_dir,
as it allows users to point programs to a different path.

Using getpwuid() also breaks namespaces-related use cases,
like `unshare -r`.

Patch was submitted by Dmitry Bogatov on the Debian bug tracker:
https://bugs.debian.org/825397

Signed-off-by: Christoph Lohmann <20h@r-36.net>
Diffstat (limited to 'surf.c')
-rw-r--r--surf.c43
1 files changed, 36 insertions, 7 deletions
diff --git a/surf.c b/surf.c
index 3d6cc11..105b28e 100644
--- a/surf.c
+++ b/surf.c
@@ -350,29 +350,58 @@ buildfile(const char *path)
 	return fpath;
 }
 
+static const char*
+get_user_homedir(const char *user) {
+	struct passwd *pw = getpwnam(user);
+	if (!pw) {
+		die("Can't get user `%s' home directory.\n", user);
+	}
+	return pw->pw_dir;
+}
+
+static const char*
+get_current_user_homedir() {
+	const char *homedir;
+	const char *user;
+	struct passwd *pw;
+
+	homedir = getenv("HOME");
+	if (homedir) {
+		return homedir;
+	}
+
+	user = getenv("USER");
+	if (user) {
+		return get_user_homedir(user);
+	}
+
+	pw = getpwuid(getuid());
+	if (!pw) {
+		die("Can't get current user home directory\n");
+	}
+	return pw->pw_dir;
+}
+
 char *
 buildpath(const char *path)
 {
-	struct passwd *pw;
 	char *apath, *name, *p, *fpath;
 
 	if (path[0] == '~') {
+		const char *homedir;
 		if (path[1] == '/' || path[1] == '\0') {
 			p = (char *)&path[1];
-			pw = getpwuid(getuid());
+			homedir = get_current_user_homedir();
 		} else {
 			if ((p = strchr(path, '/')))
 				name = g_strndup(&path[1], --p - path);
 			else
 				name = g_strdup(&path[1]);
 
-			if (!(pw = getpwnam(name))) {
-				die("Can't get user %s home directory: %s.\n",
-				    name, path);
-			}
+			homedir = get_user_homedir(name);
 			g_free(name);
 		}
-		apath = g_build_filename(pw->pw_dir, p, NULL);
+		apath = g_build_filename(homedir, p, NULL);
 	} else {
 		apath = g_strdup(path);
 	}