jaulib v1.5.0
Jau Support Library (C++, Java, ..)
Loading...
Searching...
No Matches
user_info.cpp
Go to the documentation of this file.
1/**
2 * Author: Sven Gothel <sgothel@jausoft.com>
3 * Copyright (c) 2024 Gothel Software e.K.
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining
6 * a copy of this software and associated documentation files (the
7 * "Software"), to deal in the Software without restriction, including
8 * without limitation the rights to use, copy, modify, merge, publish,
9 * distribute, sublicense, and/or sell copies of the Software, and to
10 * permit persons to whom the Software is furnished to do so, subject to
11 * the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be
14 * included in all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 */
24#include <jau/string_util.hpp>
25#if !defined(_WIN32)
26
27 #include "jau/debug.hpp"
28 #include "jau/os/user_info.hpp"
29
30 extern "C" {
31 #include <unistd.h>
32 #include <grp.h>
33 #include <pwd.h>
34 #include <sys/types.h>
35 }
36
37 using namespace jau;
38 using namespace jau::os;
39
40 bool UserInfo::get_groups(std::vector<id_t>& list) noexcept {
41 // jau::fprintf_td(stderr, "%s: uid %" PRIu32 ", euid %" PRIu32 ", gid %" PRIu32 ", egid %" PRIu32 "\n",
42 // title.c_str(), ::getuid(), ::geteuid(), ::getgid(), ::getegid());
43 list.clear();
44 ::gid_t gid_list[64];
45 int count = ::getgroups(sizeof(gid_list)/sizeof(*gid_list), gid_list);
46 if( 0 > count ) {
47 jau_DBG_PRINT("getgroups() failed");
48 return false;
49 } else {
50 for(int i=0; i<count; ++i) {
51 list.push_back((id_t)gid_list[i]);
52 }
53 jau_DBG_PRINT("getgroups(): %s", jau::to_string(list).c_str());
54 return true;
55 }
56 }
57
58 bool UserInfo::set_groups(const std::vector<id_t>& list) noexcept {
59 std::vector<::gid_t> n_list;
60 n_list.reserve(list.size()+1);
61 for(const id_t& gid : list) {
62 n_list.push_back( (::gid_t)gid );
63 }
64 if( 0 > ::setgroups(n_list.size(), n_list.data()) ) {
65 jau_ERR_PRINT("setgroups failed");
66 return false;
67 }
68 return true;
69 }
70
71 bool UserInfo::set_effective_gid(id_t group_id) noexcept {
72 ::gid_t n_group_id = (::gid_t) group_id;
73 if( 0 != ::setegid(n_group_id) ) {
74 jau_ERR_PRINT("setegid(%" PRIu64 ") failed", group_id);
75 return false;
76 }
77 return true;
78 }
79
80 bool UserInfo::set_effective_uid(id_t user_id) noexcept {
81 ::uid_t n_user_id = (::uid_t)user_id;
82 if( 0 != ::seteuid(n_user_id) ) {
83 jau_ERR_PRINT("seteuid(%" PRIu64 ") failed", user_id);
84 return false;
85 }
86 return true;
87 }
88
89 static bool UserInfo_get_env_uid(::uid_t &res_uid, const bool try_sudo) noexcept {
90 char *env_str = nullptr;
91 ::uid_t env_val = 0;
92 if ( try_sudo ) {
93 env_str = ::getenv("SUDO_UID");
94 if ( nullptr != env_str ) {
95 const auto [consumed, complete] = jau::fromIntString(env_val, env_str, strlen(env_str));
96 if ( complete ) {
97 res_uid = env_val;
98 return true;
99 }
100 }
101 }
102 env_str = ::getenv("UID");
103 if ( nullptr != env_str ) {
104 const auto [consumed, complete] = jau::fromIntString(env_val, env_str, strlen(env_str));
105 if ( complete ) {
106 res_uid = env_val;
107 return true;
108 }
109 }
110 return false;
111 }
112 bool UserInfo::get_env_uid(id_t &res_uid, const bool try_sudo) noexcept {
113 ::uid_t n_res_uid = 0;
114 if ( UserInfo_get_env_uid(n_res_uid, try_sudo) ) {
115 res_uid = (id_t)n_res_uid;
116 return true;
117 }
118 return false;
119 }
120
121 bool UserInfo::get_env_username(std::string &username, const bool try_sudo) noexcept {
122 char *env_str = nullptr;
123 if ( try_sudo ) {
124 env_str = ::getenv("SUDO_USER");
125 if ( nullptr != env_str ) {
126 username = std::string(env_str);
127 return true;
128 }
129 }
130 env_str = ::getenv("USER");
131 if ( nullptr != env_str ) {
132 username = std::string(env_str);
133 return true;
134 }
135 return false;
136 }
137
138 bool UserInfo::get_creds(id_t &res_uid, id_t &res_gid, std::string &username, std::string &homedir, std::string &shell) noexcept {
139 ::uid_t n_res_uid = (::uid_t)res_uid;
140 const bool is_root = 0 == n_res_uid;
141 struct passwd pwd;
142 char buffer[1024];
143
144 if ( !is_root || UserInfo_get_env_uid(n_res_uid, is_root) ) {
145 struct passwd *pwd_res = nullptr;
146 if ( 0 != ::getpwuid_r(n_res_uid, &pwd, buffer, sizeof(buffer), &pwd_res) || nullptr == pwd_res ) {
147 jau_DBG_PRINT("getpwuid(%" PRIu32 ") failed", n_res_uid);
148 return false;
149 }
150 jau_DBG_PRINT("getpwuid(%" PRIu32 "): name '%s', uid %" PRIu32 ", gid %" PRIu32 "\n", n_res_uid, pwd_res->pw_name, pwd_res->pw_uid, pwd_res->pw_gid);
151 res_uid = (id_t)n_res_uid;
152 res_gid = (id_t)(::gid_t)(pwd_res->pw_gid);
153 username = std::string(pwd_res->pw_name);
154 homedir = std::string(pwd_res->pw_dir);
155 shell = std::string(pwd_res->pw_shell);
156 return true;
157 } else {
158 std::string tmp_username;
159 if ( get_env_username(tmp_username, is_root) ) {
160 struct passwd *pwd_res = nullptr;
161 if ( 0 != ::getpwnam_r(tmp_username.c_str(), &pwd, buffer, sizeof(buffer), &pwd_res) || nullptr == pwd_res ) {
162 jau_DBG_PRINT("getpwnam(%s) failed\n", tmp_username.c_str());
163 return false;
164 }
165 jau_DBG_PRINT("getpwnam(%s): name '%s', uid %" PRIu32 ", gid %" PRIu32 "\n", tmp_username.c_str(), pwd_res->pw_name, pwd_res->pw_uid, pwd_res->pw_gid);
166 res_uid = (id_t)n_res_uid;
167 res_gid = (id_t)(::gid_t)(pwd_res->pw_gid);
168 username = std::string(pwd_res->pw_name);
169 homedir = std::string(pwd_res->pw_dir);
170 shell = std::string(pwd_res->pw_shell);
171 return true;
172 }
173 }
174 return false;
175 }
176
177 bool UserInfo::get_creds(const std::string &username_lookup, id_t &res_uid, id_t &res_gid, std::string &username, std::string &homedir, std::string &shell) noexcept {
178 struct passwd pwd;
179 char buffer[1024];
180 struct passwd *pwd_res = nullptr;
181 if ( 0 != ::getpwnam_r(username_lookup.c_str(), &pwd, buffer, sizeof(buffer), &pwd_res) || nullptr == pwd_res ) {
182 jau_DBG_PRINT("getpwnam(%s) failed\n", username_lookup.c_str());
183 return false;
184 }
185 jau_DBG_PRINT("getpwnam(%s): name '%s', uid %" PRIu32 ", gid %" PRIu32 "\n", username_lookup.c_str(), pwd_res->pw_name, pwd_res->pw_uid, pwd_res->pw_gid);
186 res_uid = (id_t)(::uid_t)(pwd_res->pw_uid);
187 res_gid = (id_t)(::gid_t)(pwd_res->pw_gid);
188 username = std::string(pwd_res->pw_name);
189 homedir = std::string(pwd_res->pw_dir);
190 shell = std::string(pwd_res->pw_shell);
191 return true;
192 }
193
195 m_uid = (id_t)::getuid();
196 m_valid = get_creds(m_uid, m_gid, m_username, m_homedir, m_shell);
197 if ( m_valid ) {
198 get_groups(m_gid_list);
199 }
200 }
202 m_uid = uid;
203 m_valid = get_creds(m_uid, m_gid, m_username, m_homedir, m_shell);
204 if ( m_valid ) {
205 get_groups(m_gid_list);
206 }
207 }
208
209 UserInfo::UserInfo(const std::string &username) noexcept {
210 m_valid = get_creds(username, m_uid, m_gid, m_username, m_homedir, m_shell);
211 if ( m_valid ) {
212 get_groups(m_gid_list);
213 }
214 }
215
216#endif // !_WIN32
id_t uid() const noexcept
Definition user_info.hpp:78
const std::string & username() const noexcept
Definition user_info.hpp:80
UserInfo() noexcept
Create instance of the user executing this application.
#define jau_DBG_PRINT(fmt,...)
Use for environment-variable environment::DEBUG conditional debug messages, prefix '[elapsed_time] De...
Definition debug.hpp:100
#define jau_ERR_PRINT(...)
Use for unconditional error messages, prefix '[elapsed_time] Error @ FILE:LINE FUNC: '.
Definition debug.hpp:150
std::string_view to_string(const endian_t v) noexcept
Return std::string representation of the given endian.
constexpr SizeBoolPair fromIntString(value_type &result, std::string_view str, uint32_t radix=10, const char separator=0) noexcept
Converts a given integer string representation to the given result reference, compatible with ::strto...
Author: Sven Gothel sgothel@jausoft.com Copyright (c) 2024 Gothel Software e.K.
__pack(...): Produces MSVC, clang and gcc compatible lead-in and -out macros.
Definition backtrace.hpp:32
static bool UserInfo_get_env_uid(::uid_t &res_uid, const bool try_sudo) noexcept
Definition user_info.cpp:89