Tor 0.4.9.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. */
24static 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 */
31static struct passwd *
32tor_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. */
49static void
50tor_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 **/
69const struct passwd *
70tor_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 */
105const struct passwd *
106tor_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. */
126char *
127get_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:56
static void tor_passwd_free_(struct passwd *pw)
Definition: userdb.c:50
char * get_user_homedir(const char *username)
Definition: userdb.c:127
static struct passwd * passwd_cached
Definition: userdb.c:24
const struct passwd * tor_getpwnam(const char *username)
Definition: userdb.c:70
const struct passwd * tor_getpwuid(uid_t uid)
Definition: userdb.c:106
static struct passwd * tor_passwd_dup(const struct passwd *pw)
Definition: userdb.c:32
Header for userdb.c.
Macros to manage assertions, fatal and non-fatal.
#define tor_assert(expr)
Definition: util_bug.h:103