Direct-BT v3.3.0-1-gc2d430c
Direct-BT - Direct Bluetooth Programming.
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#if !defined(_WIN32)
25
26 #include "jau/debug.hpp"
27 #include "jau/os/user_info.hpp"
28
29 extern "C" {
30 #include <unistd.h>
31 #include <grp.h>
32 #include <pwd.h>
33 #include <sys/types.h>
34 }
35
36 using namespace jau;
37 using namespace jau::os;
38
39 bool UserInfo::get_groups(std::vector<id_t>& list) noexcept {
40 // jau::fprintf_td(stderr, "%s: uid %" PRIu32 ", euid %" PRIu32 ", gid %" PRIu32 ", egid %" PRIu32 "\n",
41 // title.c_str(), ::getuid(), ::geteuid(), ::getgid(), ::getegid());
42 list.clear();
43 ::gid_t gid_list[64];
44 int count = ::getgroups(sizeof(gid_list)/sizeof(*gid_list), gid_list);
45 if( 0 > count ) {
46 DBG_PRINT("getgroups() failed");
47 return false;
48 } else {
49 for(int i=0; i<count; ++i) {
50 list.push_back((id_t)gid_list[i]);
51 }
52 DBG_PRINT("getgroups(): %s", jau::to_string(list).c_str());
53 return true;
54 }
55 }
56
57 bool UserInfo::set_groups(const std::vector<id_t>& list) noexcept {
58 std::vector<::gid_t> n_list;
59 n_list.reserve(list.size()+1);
60 for(const id_t& gid : list) {
61 n_list.push_back( (::gid_t)gid );
62 }
63 if( 0 > ::setgroups(n_list.size(), n_list.data()) ) {
64 ERR_PRINT("setgroups failed");
65 return false;
66 }
67 return true;
68 }
69
70 bool UserInfo::set_effective_gid(id_t group_id) noexcept {
71 ::gid_t n_group_id = (::gid_t) group_id;
72 if( 0 != ::setegid(n_group_id) ) {
73 ERR_PRINT("setegid(%" PRIu64 ") failed", group_id);
74 return false;
75 }
76 return true;
77 }
78
79 bool UserInfo::set_effective_uid(id_t user_id) noexcept {
80 ::uid_t n_user_id = (::uid_t)user_id;
81 if( 0 != ::seteuid(n_user_id) ) {
82 ERR_PRINT("seteuid(%" PRIu64 ") failed", user_id);
83 return false;
84 }
85 return true;
86 }
87
88 static bool UserInfo_get_env_uid(::uid_t& res_uid, const bool try_sudo) noexcept {
89 char *env_str = nullptr;
90 long long env_val = 0;
91 if( try_sudo ) {
92 env_str = ::getenv("SUDO_UID");
93 if( nullptr != env_str ) {
94 if( jau::to_integer(env_val, env_str, strlen(env_str)) ) {
95 res_uid = (::uid_t) env_val;
96 return true;
97 }
98 }
99 }
100 env_str = ::getenv("UID");
101 if( nullptr != env_str ) {
102 if( jau::to_integer(env_val, env_str, strlen(env_str)) ) {
103 res_uid = (::uid_t) env_val;
104 return true;
105 }
106 }
107 return false;
108 }
109 bool UserInfo::get_env_uid(id_t& res_uid, const bool try_sudo) noexcept {
110 ::uid_t n_res_uid = 0;
111 if( UserInfo_get_env_uid(n_res_uid, try_sudo) ) {
112 res_uid = (id_t)n_res_uid;
113 return true;
114 }
115 return false;
116 }
117
118 bool UserInfo::get_env_username(std::string& username, const bool try_sudo) noexcept {
119 char *env_str = nullptr;
120 if( try_sudo ) {
121 env_str = ::getenv("SUDO_USER");
122 if( nullptr != env_str ) {
123 username = std::string(env_str);
124 return true;
125 }
126 }
127 env_str = ::getenv("USER");
128 if( nullptr != env_str ) {
129 username = std::string(env_str);
130 return true;
131 }
132 return false;
133 }
134
135 bool UserInfo::get_creds(id_t& res_uid, id_t& res_gid, std::string& username, std::string& homedir, std::string& shell) noexcept {
136 ::uid_t n_res_uid = (::uid_t)res_uid;
137 const bool is_root = 0 == n_res_uid;
138 struct passwd pwd;
139 char buffer[1024];
140
141 if( !is_root || UserInfo_get_env_uid(n_res_uid, is_root) ) {
142 struct passwd* pwd_res = nullptr;
143 if( 0 != ::getpwuid_r(n_res_uid, &pwd, buffer, sizeof(buffer), &pwd_res) || nullptr == pwd_res ) {
144 DBG_PRINT("getpwuid(%" PRIu32 ") failed", n_res_uid);
145 return false;
146 }
147 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);
148 res_uid = (id_t)n_res_uid;
149 res_gid = (id_t)(::gid_t)( pwd_res->pw_gid );
150 username = std::string(pwd_res->pw_name);
151 homedir = std::string(pwd_res->pw_dir);
152 shell = std::string(pwd_res->pw_shell);
153 return true;
154 } else {
155 std::string tmp_username;
156 if( get_env_username(tmp_username, is_root) ) {
157 struct passwd* pwd_res = nullptr;
158 if( 0 != ::getpwnam_r(tmp_username.c_str(), &pwd, buffer, sizeof(buffer), &pwd_res) || nullptr == pwd_res ) {
159 DBG_PRINT("getpwnam(%s) failed\n", tmp_username.c_str());
160 return false;
161 }
162 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);
163 res_uid = (id_t)n_res_uid;
164 res_gid = (id_t)(::gid_t)( pwd_res->pw_gid );
165 username = std::string(pwd_res->pw_name);
166 homedir = std::string(pwd_res->pw_dir);
167 shell = std::string(pwd_res->pw_shell);
168 return true;
169 }
170 }
171 return false;
172 }
173
174 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 {
175 struct passwd pwd;
176 char buffer[1024];
177 struct passwd* pwd_res = nullptr;
178 if( 0 != ::getpwnam_r(username_lookup.c_str(), &pwd, buffer, sizeof(buffer), &pwd_res) || nullptr == pwd_res ) {
179 DBG_PRINT("getpwnam(%s) failed\n", username_lookup.c_str());
180 return false;
181 }
182 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);
183 res_uid = (id_t)(::uid_t)( pwd_res->pw_uid );
184 res_gid = (id_t)(::gid_t)( pwd_res->pw_gid );
185 username = std::string(pwd_res->pw_name);
186 homedir = std::string(pwd_res->pw_dir);
187 shell = std::string(pwd_res->pw_shell);
188 return true;
189 }
190
191 UserInfo::UserInfo() noexcept {
192 m_uid = (id_t)::getuid();
193 m_valid = get_creds(m_uid, m_gid, m_username, m_homedir, m_shell);
194 if( m_valid ) {
195 get_groups(m_gid_list);
196 }
197 }
198 UserInfo::UserInfo(id_t uid) noexcept {
199 m_uid = uid;
200 m_valid = get_creds(m_uid, m_gid, m_username, m_homedir, m_shell);
201 if( m_valid ) {
202 get_groups(m_gid_list);
203 }
204 }
205
206 UserInfo::UserInfo(const std::string& username) noexcept {
207 m_valid = get_creds(username, m_uid, m_gid, m_username, m_homedir, m_shell);
208 if( m_valid ) {
209 get_groups(m_gid_list);
210 }
211 }
212
213#endif // !_WIN32
UserInfo() noexcept
Create instance of the user executing this application.
Definition: user_info.cpp:191
#define ERR_PRINT(...)
Use for unconditional error messages, prefix '[elapsed_time] Error @ FILE:LINE FUNC: '.
Definition: debug.hpp:109
#define DBG_PRINT(...)
Use for environment-variable environment::DEBUG conditional debug messages, prefix '[elapsed_time] De...
Definition: debug.hpp:52
static bool set_effective_uid(::uid_t user_id)
Definition: file_util.cpp:1936
std::string to_string(const endian_t v) noexcept
Return std::string representation of the given endian.
bool to_integer(long long &result, const std::string &str, const char limiter='\0', const char *limiter_pos=nullptr)
Author: Sven Gothel sgothel@jausoft.com Copyright (c) 2024 Gothel Software e.K.
Definition: dyn_linker.hpp:37
__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:88