Tor  0.4.7.0-alpha-dev
userdb.c
Go to the documentation of this file.
1 /* Copyright (c) 2003-2004, Roger Dingledine
2  * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
3  * Copyright (c) 2007-2021, The Tor Project, Inc. */
4 /* See LICENSE for licensing information */
5 
6 /**
7  * \file userdb.c
8  *
9  * \brief Access the POSIX user database.
10  **/
11 
12 #include "lib/fs/userdb.h"
13 
14 #ifndef _WIN32
15 #include "lib/malloc/malloc.h"
16 #include "lib/log/log.h"
17 #include "lib/log/util_bug.h"
18 
19 #include <pwd.h>
20 #include <stddef.h>
21 #include <string.h>
22 
23 /** Cached struct from the last getpwname() call we did successfully. */
24 static struct passwd *passwd_cached = NULL;
25 
26 /** Helper: copy a struct passwd object.
27  *
28  * We only copy the fields pw_uid, pw_gid, pw_name, pw_dir. Tor doesn't use
29  * any others, and I don't want to run into incompatibilities.
30  */
31 static struct passwd *
32 tor_passwd_dup(const struct passwd *pw)
33 {
34  struct passwd *new_pw = tor_malloc_zero(sizeof(struct passwd));
35  if (pw->pw_name)
36  new_pw->pw_name = tor_strdup(pw->pw_name);
37  if (pw->pw_dir)
38  new_pw->pw_dir = tor_strdup(pw->pw_dir);
39  new_pw->pw_uid = pw->pw_uid;
40  new_pw->pw_gid = pw->pw_gid;
41 
42  return new_pw;
43 }
44 
45 #define tor_passwd_free(pw) \
46  FREE_AND_NULL(struct passwd, tor_passwd_free_, (pw))
47 
48 /** Helper: free one of our cached 'struct passwd' values. */
49 static void
50 tor_passwd_free_(struct passwd *pw)
51 {
52  if (!pw)
53  return;
54 
55  tor_free(pw->pw_name);
56  tor_free(pw->pw_dir);
57  tor_free(pw);
58 }
59 
60 /** Wrapper around getpwnam() that caches result. Used so that we don't need
61  * to give the sandbox access to /etc/passwd.
62  *
63  * The following fields alone will definitely be copied in the output: pw_uid,
64  * pw_gid, pw_name, pw_dir. Other fields are not present in cached values.
65  *
66  * When called with a NULL argument, this function clears storage associated
67  * with static variables it uses.
68  **/
69 const struct passwd *
70 tor_getpwnam(const char *username)
71 {
72  struct passwd *pw;
73 
74  if (username == NULL) {
75  tor_passwd_free(passwd_cached);
76  passwd_cached = NULL;
77  return NULL;
78  }
79 
80  if ((pw = getpwnam(username))) {
81  tor_passwd_free(passwd_cached);
83  log_info(LD_GENERAL, "Caching new entry %s for %s",
84  passwd_cached->pw_name, username);
85  return pw;
86  }
87 
88  /* Lookup failed */
89  if (! passwd_cached || ! passwd_cached->pw_name)
90  return NULL;
91 
92  if (! strcmp(username, passwd_cached->pw_name))
93  return passwd_cached; // LCOV_EXCL_LINE - would need to make getpwnam flaky
94 
95  return NULL;
96 }
97 
98 /** Wrapper around getpwnam() that can use cached result from
99  * tor_getpwnam(). Used so that we don't need to give the sandbox access to
100  * /etc/passwd.
101  *
102  * The following fields alone will definitely be copied in the output: pw_uid,
103  * pw_gid, pw_name, pw_dir. Other fields are not present in cached values.
104  */
105 const struct passwd *
106 tor_getpwuid(uid_t uid)
107 {
108  struct passwd *pw;
109 
110  if ((pw = getpwuid(uid))) {
111  return pw;
112  }
113 
114  /* Lookup failed */
115  if (! passwd_cached)
116  return NULL;
117 
118  if (uid == passwd_cached->pw_uid)
119  return passwd_cached; // LCOV_EXCL_LINE - would need to make getpwnam flaky
120 
121  return NULL;
122 }
123 
124 /** Allocate and return a string containing the home directory for the
125  * user <b>username</b>. Only works on posix-like systems. */
126 char *
127 get_user_homedir(const char *username)
128 {
129  const struct passwd *pw;
130  tor_assert(username);
131 
132  if (!(pw = tor_getpwnam(username))) {
133  log_err(LD_CONFIG,"User \"%s\" not found.", username);
134  return NULL;
135  }
136  return tor_strdup(pw->pw_dir);
137 }
138 #endif /* !defined(_WIN32) */
Headers for log.c.
#define LD_GENERAL
Definition: log.h:62
#define LD_CONFIG
Definition: log.h:68
Headers for util_malloc.c.
#define tor_free(p)
Definition: malloc.h:52
const struct passwd * tor_getpwuid(uid_t uid)
Definition: userdb.c:106
static void tor_passwd_free_(struct passwd *pw)
Definition: userdb.c:50
static struct passwd * passwd_cached
Definition: userdb.c:24
const struct passwd * tor_getpwnam(const char *username)
Definition: userdb.c:70
static struct passwd * tor_passwd_dup(const struct passwd *pw)
Definition: userdb.c:32
char * get_user_homedir(const char *username)
Definition: userdb.c:127
Header for userdb.c.
Macros to manage assertions, fatal and non-fatal.
#define tor_assert(expr)
Definition: util_bug.h:102