LCOV - code coverage report
Current view: top level - lib/fs - userdb.c (source / functions) Hit Total Coverage
Test: lcov.info Lines: 39 39 100.0 %
Date: 2021-11-24 03:28:48 Functions: 5 5 100.0 %

          Line data    Source code
       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           3 : tor_passwd_dup(const struct passwd *pw)
      33             : {
      34           3 :   struct passwd *new_pw = tor_malloc_zero(sizeof(struct passwd));
      35           3 :   if (pw->pw_name)
      36           3 :     new_pw->pw_name = tor_strdup(pw->pw_name);
      37           3 :   if (pw->pw_dir)
      38           3 :     new_pw->pw_dir = tor_strdup(pw->pw_dir);
      39           3 :   new_pw->pw_uid = pw->pw_uid;
      40           3 :   new_pw->pw_gid = pw->pw_gid;
      41             : 
      42           3 :   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         238 : tor_passwd_free_(struct passwd *pw)
      51             : {
      52         238 :   if (!pw)
      53             :     return;
      54             : 
      55           2 :   tor_free(pw->pw_name);
      56           2 :   tor_free(pw->pw_dir);
      57           2 :   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         240 : tor_getpwnam(const char *username)
      71             : {
      72         240 :   struct passwd *pw;
      73             : 
      74         240 :   if (username == NULL) {
      75         235 :     tor_passwd_free(passwd_cached);
      76         235 :     passwd_cached = NULL;
      77         235 :     return NULL;
      78             :   }
      79             : 
      80           5 :   if ((pw = getpwnam(username))) {
      81           3 :     tor_passwd_free(passwd_cached);
      82           3 :     passwd_cached = tor_passwd_dup(pw);
      83           3 :     log_info(LD_GENERAL, "Caching new entry %s for %s",
      84             :              passwd_cached->pw_name, username);
      85           3 :     return pw;
      86             :   }
      87             : 
      88             :   /* Lookup failed */
      89           2 :   if (! passwd_cached || ! passwd_cached->pw_name)
      90             :     return NULL;
      91             : 
      92           2 :   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           3 : tor_getpwuid(uid_t uid)
     107             : {
     108           3 :   struct passwd *pw;
     109             : 
     110           3 :   if ((pw = getpwuid(uid))) {
     111             :     return pw;
     112             :   }
     113             : 
     114             :   /* Lookup failed */
     115           1 :   if (! passwd_cached)
     116             :     return NULL;
     117             : 
     118           1 :   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           2 : get_user_homedir(const char *username)
     128             : {
     129           2 :   const struct passwd *pw;
     130           2 :   tor_assert(username);
     131             : 
     132           2 :   if (!(pw = tor_getpwnam(username))) {
     133           1 :     log_err(LD_CONFIG,"User \"%s\" not found.", username);
     134           1 :     return NULL;
     135             :   }
     136           1 :   return tor_strdup(pw->pw_dir);
     137             : }
     138             : #endif /* !defined(_WIN32) */

Generated by: LCOV version 1.14