Explorar el Código

Add a pair of wrapper functions: tor_getpwnam() and tor_getpwuid()

We'll use these to deal with being unable to access the user DB
after we install the sandbox, to fix bug 11946.
Nick Mathewson hace 10 años
padre
commit
e12af2adb0
Se han modificado 3 ficheros con 91 adiciones y 0 borrados
  1. 83 0
      src/common/compat.c
  2. 5 0
      src/common/compat.h
  3. 3 0
      src/or/main.c

+ 83 - 0
src/common/compat.c

@@ -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.
  */

+ 5 - 0
src/common/compat.h

@@ -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);
 

+ 3 - 0
src/or/main.c

@@ -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 */