pion
5.0.6
|
00001 // --------------------------------------------------------------------- 00002 // pion: a Boost C++ framework for building lightweight HTTP interfaces 00003 // --------------------------------------------------------------------- 00004 // Copyright (C) 2007-2014 Splunk Inc. (https://github.com/splunk/pion) 00005 // 00006 // Distributed under the Boost Software License, Version 1.0. 00007 // See http://www.boost.org/LICENSE_1_0.txt 00008 // 00009 00010 #include <pion/admin_rights.hpp> 00011 00012 #ifndef _MSC_VER 00013 #include <sys/types.h> 00014 #include <unistd.h> 00015 #include <sys/types.h> 00016 #include <boost/regex.hpp> 00017 #include <boost/tokenizer.hpp> 00018 #include <boost/lexical_cast.hpp> 00019 #include <fstream> 00020 #endif 00021 00022 00023 namespace pion { // begin namespace pion 00024 00025 00026 // static members of admin_rights 00027 00028 const boost::int16_t admin_rights::ADMIN_USER_ID = 0; 00029 boost::mutex admin_rights::m_mutex; 00030 00031 00032 // admin_rights member functions 00033 00034 #ifdef _MSC_VER 00035 00036 admin_rights::admin_rights(bool use_log) 00037 : m_logger(PION_GET_LOGGER("pion.admin_rights")), 00038 m_lock(m_mutex), m_user_id(-1), m_has_rights(false), m_use_log(use_log) 00039 {} 00040 00041 void admin_rights::release(void) 00042 {} 00043 00044 long admin_rights::run_as_user(const std::string& user_name) 00045 { 00046 return -1; 00047 } 00048 00049 long admin_rights::run_as_group(const std::string& group_name) 00050 { 00051 return -1; 00052 } 00053 00054 long admin_rights::find_system_id(const std::string& name, 00055 const std::string& file) 00056 { 00057 return -1; 00058 } 00059 00060 #else // NOT #ifdef _MSC_VER 00061 00062 admin_rights::admin_rights(bool use_log) 00063 : m_logger(PION_GET_LOGGER("pion.admin_rights")), 00064 m_lock(m_mutex), m_user_id(-1), m_has_rights(false), m_use_log(use_log) 00065 { 00066 m_user_id = geteuid(); 00067 if ( seteuid(ADMIN_USER_ID) != 0 ) { 00068 if (m_use_log) 00069 PION_LOG_ERROR(m_logger, "Unable to upgrade to administrative rights"); 00070 m_lock.unlock(); 00071 return; 00072 } else { 00073 m_has_rights = true; 00074 if (m_use_log) 00075 PION_LOG_DEBUG(m_logger, "Upgraded to administrative rights"); 00076 } 00077 } 00078 00079 void admin_rights::release(void) 00080 { 00081 if (m_has_rights) { 00082 if ( seteuid(m_user_id) == 0 ) { 00083 if (m_use_log) 00084 PION_LOG_DEBUG(m_logger, "Released administrative rights"); 00085 } else { 00086 if (m_use_log) 00087 PION_LOG_ERROR(m_logger, "Unable to release administrative rights"); 00088 } 00089 m_has_rights = false; 00090 m_lock.unlock(); 00091 } 00092 } 00093 00094 long admin_rights::run_as_user(const std::string& user_name) 00095 { 00096 long user_id = find_system_id(user_name, "/etc/passwd"); 00097 if (user_id != -1) { 00098 if ( seteuid(user_id) != 0 ) 00099 user_id = -1; 00100 } else { 00101 user_id = geteuid(); 00102 } 00103 return user_id; 00104 } 00105 00106 long admin_rights::run_as_group(const std::string& group_name) 00107 { 00108 long group_id = find_system_id(group_name, "/etc/group"); 00109 if (group_id != -1) { 00110 if ( setegid(group_id) != 0 ) 00111 group_id = -1; 00112 } else { 00113 group_id = getegid(); 00114 } 00115 return group_id; 00116 } 00117 00118 long admin_rights::find_system_id(const std::string& name, 00119 const std::string& file) 00120 { 00121 // check if name is the system id 00122 const boost::regex just_numbers("\\d+"); 00123 if (boost::regex_match(name, just_numbers)) { 00124 return boost::lexical_cast<boost::int32_t>(name); 00125 } 00126 00127 // open system file 00128 std::ifstream system_file(file.c_str()); 00129 if (! system_file.is_open()) { 00130 return -1; 00131 } 00132 00133 // find id in system file 00134 typedef boost::tokenizer<boost::char_separator<char> > Tok; 00135 boost::char_separator<char> sep(":"); 00136 std::string line; 00137 boost::int32_t system_id = -1; 00138 00139 while (std::getline(system_file, line, '\n')) { 00140 Tok tokens(line, sep); 00141 Tok::const_iterator token_it = tokens.begin(); 00142 if (token_it != tokens.end() && *token_it == name) { 00143 // found line matching name 00144 if (++token_it != tokens.end() && ++token_it != tokens.end() 00145 && boost::regex_match(*token_it, just_numbers)) 00146 { 00147 // found id as third parameter 00148 system_id = boost::lexical_cast<boost::int32_t>(*token_it); 00149 } 00150 break; 00151 } 00152 } 00153 00154 return system_id; 00155 } 00156 00157 #endif // #ifdef _MSC_VER 00158 00159 } // end namespace pion 00160