]> git.ipfire.org Git - thirdparty/tor.git/commitdiff
Add a pair of wrapper functions: tor_getpwnam() and tor_getpwuid()
authorNick Mathewson <nickm@torproject.org>
Wed, 14 May 2014 17:50:43 +0000 (13:50 -0400)
committerNick Mathewson <nickm@torproject.org>
Wed, 14 May 2014 17:50:43 +0000 (13:50 -0400)
We'll use these to deal with being unable to access the user DB
after we install the sandbox, to fix bug 11946.

src/common/compat.c
src/common/compat.h
src/or/main.c

index 7a444df1069f8ac22e35c795a2193aee81341d43..9f31cceb0963a2cab32483356e58b26e3c9a0478 100644 (file)
@@ -1702,6 +1702,89 @@ log_credential_status(void)
 }
 #endif
 
+#ifndef _WIN32
+static struct passwd *passwd_cached = NULL;
+
+static struct passwd *
+tor_passwd_dup(const struct passwd *pw)
+{
+  struct passwd *new_pw = tor_malloc_zero(sizeof(struct passwd));
+  if (pw->pw_name)
+    new_pw->pw_name = tor_strdup(pw->pw_name);
+  if (pw->pw_dir)
+    new_pw->pw_dir = tor_strdup(pw->pw_dir);
+  new_pw->pw_uid = pw->pw_uid;
+  new_pw->pw_gid = pw->pw_gid;
+
+  return new_pw;
+}
+
+static void
+tor_passwd_free(struct passwd *pw)
+{
+  if (!pw)
+    return;
+
+  tor_free(pw->pw_name);
+  tor_free(pw->pw_dir);
+  tor_free(pw);
+}
+
+/** Wrapper around getpwnam() that caches result. Used so that we don't need
+ * to give the sandbox access to /etc/passwd. */
+const struct passwd *
+tor_getpwnam(const char *username)
+{
+  struct passwd *pw;
+
+  if (username == NULL) {
+    tor_passwd_free(passwd_cached);
+    passwd_cached = NULL;
+    return NULL;
+  }
+
+  if ((pw = getpwnam(username))) {
+    tor_passwd_free(passwd_cached);
+    passwd_cached = tor_passwd_dup(pw);
+    log_notice(LD_GENERAL, "Caching new entry %s for %s",
+               passwd_cached->pw_name, username);
+    return pw;
+  }
+
+  /* Lookup failed */
+  if (! passwd_cached || ! passwd_cached->pw_name)
+    return NULL;
+
+  if (! strcmp(username, passwd_cached->pw_name))
+    return passwd_cached;
+
+  return NULL;
+}
+
+/** Wrapper around getpwnam() that can use cached result from
+ * tor_getpwnam(). Used so that we don't need to give the sandbox access to
+ * /etc/passwd. */
+const struct passwd *
+tor_getpwuid(uid_t uid)
+{
+  struct passwd *pw;
+
+  if ((pw = getpwuid(uid))) {
+    return pw;
+  }
+
+  /* Lookup failed */
+  if (! passwd_cached)
+    return NULL;
+
+  if (uid == passwd_cached->pw_uid)
+    return passwd_cached;
+
+  return NULL;
+}
+#endif
+
+
 /** Call setuid and setgid to run as <b>user</b> and switch to their
  * primary group.  Return 0 on success.  On failure, log and return -1.
  */
index 314b1aa0014e0713676a3cc3d4dbacbade988765..683c4d0897757d66cf973c34eb3a5a1025d70374 100644 (file)
@@ -633,6 +633,11 @@ int switch_id(const char *user);
 char *get_user_homedir(const char *username);
 #endif
 
+#ifndef _WIN32
+const struct passwd *tor_getpwnam(const char *username);
+const struct passwd *tor_getpwuid(uid_t uid);
+#endif
+
 int get_parent_directory(char *fname);
 char *make_path_absolute(char *fname);
 
index 5532026e392f8867f5f13fcd0f16d8a6754c5b2d..a2c5743cf072c1cbadee5b9efc475799f0fee1b0 100644 (file)
@@ -2548,6 +2548,9 @@ tor_free_all(int postfork)
   free_cell_pool();
   if (!postfork) {
     tor_tls_free_all();
+#ifndef _WIN32
+    tor_getpwnam(NULL);
+#endif
   }
   /* stuff in main.c */