diff --git a/core/app.cpp b/core/app.cpp index 84f708f..a71c10e 100755 --- a/core/app.cpp +++ b/core/app.cpp @@ -7,6 +7,11 @@ * */ +#include +#include +#include +#include + #include "app.h" #include "plugin.h" #include "misc.h" @@ -138,7 +143,7 @@ bool App::Init() db.LogQueries(config.log_db_query); if( !CreateFCGISocket() ) - return false; + return false; // !! dodac logsave do logow request.Clear(); compress.Init(); @@ -148,7 +153,7 @@ bool App::Init() // !! teraz mamy dwa katalogi z templetami // !! o co chodzilo? if( !notify.Init() ) - return false; + return false; // !! dodac logsave do logow // call this after system.Init() (mount points identificators should be created) templates_notify.SetMountTypes( system.mounts.MountTypeCms(), @@ -714,3 +719,211 @@ Error status = request.status; FilterCompressSend(compressing, source); } } + + +void App::LogUser(const char * msg, uid_t id) +{ + log << log3 << msg << " "; + + passwd * p = getpwuid(id); + + if( p ) + log << p->pw_name; + else + log << id; + + log << logend; +} + + +void App::LogGroup(const char * msg, gid_t id, bool put_logend) +{ + log << log3 << msg << " "; + + group * g = getgrgid(id); + + if( g ) + log << g->gr_name; + else + log << (int)id; + + if( put_logend ) + log << logend; +} + + +void App::LogUsers() +{ +uid_t eid, rid; + + eid = geteuid(); + rid = getuid(); + + if( eid == rid ) + { + LogUser("App: effective/real user:", eid); + } + else + { + LogUser("App: effective user:", eid); + LogUser("App: real user:", rid); + } +} + + + +void App::LogEffectiveGroups(std::vector & tab) +{ + log << log3 << "App: effective groups:"; + + for(size_t i=0 ; i tab; +gid_t rgid; +int len; + + rgid = getgid(); + len = getgroups(0, 0); + + if( len <= 0 ) + { + log << log3 << "App: I can't read how many groups there are" << logend; + return; + } + + tab.resize(len); + len = getgroups(len, &(tab[0])); + + if( len == -1 ) + { + log << log3 << "App: I can't read groups" << logend; + return; + } + + if( len == 1 && rgid == tab[0] ) + { + LogGroup("App: effective/real group:", rgid); + } + else + { + tab.resize(len); + LogEffectiveGroups(tab); + LogGroup("App: real group:", rgid); + } +} + + +void App::LogUserGroups() +{ + LogUsers(); + LogGroups(); +} + + + +bool App::DropPrivileges(const std::string & user, uid_t uid, gid_t gid, bool additional_groups) +{ + if( additional_groups ) + { + if( initgroups(user.c_str(), gid) < 0 ) + { + log << log1 << "App: I can't init groups for user: " << user << logend << logsave; + return false; + } + } + else + { + if( setgroups(1, &gid) < 0 ) + { + log << log1 << "App: I can't init groups for user: " << user << logend << logsave; + return false; + } + } + + // for setting real and saved gid too + if( setgid(gid) ) + { + log << log1 << "App: I can't change real and saved gid" << logend << logsave; + return false; + } + + if( setuid(uid) < 0 ) + { + log << log1 << "App: I can't drop privileges to user: " << user + << " (uid:" << uid << ")" << logend << logsave; + return false; + } + + if( getuid()==0 || geteuid()==0 ) + { + log << log1 << "App: sorry, for security reasons you should not run me as the root" << logend << logsave; + return false; + } + +return true; +} + + +bool App::DropPrivileges() +{ + if( getuid()!=0 && geteuid()!=0 ) + return true; + + log << log2 << "App: dropping privileges" << logend; + + if( config.user.empty() ) + { + log << log1 << "App: you should specify user name in the config file " + << "to which I have to drop privileges" << logend << logsave; + return false; + } + + if( config.group.empty() ) + { + log << log1 << "App: you should specify group name in the config file " + << "to which I have to drop privileges" << logend << logsave; + return false; + } + + passwd * p = getpwnam(config.user.c_str()); + group * g = getgrnam(config.group.c_str()); + + if( !p ) + { + log << log1 << "App: there is no such a user as: \"" << config.user << "\"" << logend << logsave; + return false; + } + + if( !g ) + { + log << log1 << "App: there is no such a group as: \"" << config.group << "\"" << logend << logsave; + return false; + } + + if( !DropPrivileges(config.user, p->pw_uid, g->gr_gid, config.additional_groups) ) + return false; + +return true; +} + diff --git a/core/app.h b/core/app.h index 0074b51..63ba658 100755 --- a/core/app.h +++ b/core/app.h @@ -50,7 +50,8 @@ public: bool Init(); void Start(); void Close(); - + bool DropPrivileges(); + void LogUserGroups(); // configuration read from a config file @@ -150,6 +151,12 @@ private: bool IsCompressionAllowed(const std::string & source); bool CanSendContent(Header header); + void LogUser(const char * msg, uid_t id); + void LogGroup(const char * msg, gid_t id, bool put_logend = true); + void LogUsers(); + void LogEffectiveGroups(std::vector & tab); + void LogGroups(); + bool DropPrivileges(const std::string & user, uid_t uid, gid_t gid, bool additional_groups); // !! dodac do session managera? time_t last_sessions_save; diff --git a/core/config.cpp b/core/config.cpp index 9c1be8b..3ebb0e3 100755 --- a/core/config.cpp +++ b/core/config.cpp @@ -89,6 +89,10 @@ bool Config::ReadConfig(bool errors_to_stdout_, bool stdout_is_closed) void Config::AssignValues(bool stdout_is_closed) { + user = Text("user"); + group = Text("group"); + additional_groups = Bool("additional_groups", true); + log_file = Text("log_file"); log_notify_file = Text("log_notify_file"); log_delimiter = Text("log_delimiter", "---------------------------------------------------------------------------------"); diff --git a/core/config.h b/core/config.h index 60dbaf4..51ee216 100755 --- a/core/config.h +++ b/core/config.h @@ -24,6 +24,20 @@ public: // name of the config file (full path can be) std::string config_file; + // system user name (to which drop privileges) + // used only if winix is started as the root + std::string user; + + // system group name (to which drop privileges) + // used only if winix is started as the root + std::string group; + + // setting additional effective groups from /etc/group + // by using initgroups() + // used only if winix is started as the root + // default: true + bool additional_groups; + // log file name, log file name for notifications (sending emails, etc) std::string log_file, log_notify_file; diff --git a/core/log.cpp b/core/log.cpp index 8276beb..85acc19 100755 --- a/core/log.cpp +++ b/core/log.cpp @@ -19,6 +19,7 @@ Log::Log() item = 0; item_save = 1; lines = 0; + log_file_open = false; } @@ -29,14 +30,18 @@ void Log::Init(int log_l, const std::string & log_f, bool log_std, int log_reque log_stdout = log_std; item_save = log_request; - OpenFile(); + // don't open the file here + // because it would be created with the root as an owner } void Log::OpenFile() { if( !log_file.empty() ) + { file.open( log_file.c_str(), std::ios_base::out | std::ios_base::app ); + log_file_open = true; + } } @@ -216,7 +221,7 @@ void Log::SaveLog() if( log_file.empty() ) return; - if( !file ) + if( !log_file_open || !file ) { file.close(); file.clear(); @@ -227,7 +232,8 @@ void Log::SaveLog() return; } - file << source << std::endl; + file << source; + file.flush(); } diff --git a/core/log.h b/core/log.h index 75999f2..27a209b 100755 --- a/core/log.h +++ b/core/log.h @@ -25,16 +25,6 @@ enum Manipulators { logsave, logsavenow, logend, log1, log2, log3 }; class Log { -std::ostringstream buffer; -int log_level, current_level; -int item, item_save; -std::string log_file; -bool log_stdout; -std::ofstream file; -int lines; - - void OpenFile(); - public: Log(); @@ -54,8 +44,20 @@ public: Log & operator<<(Manipulators m); void SystemErr(int err); - void SaveLog(); + +private: + std::ostringstream buffer; + int log_level, current_level; + int item, item_save; + std::string log_file; + bool log_stdout; + std::ofstream file; + int lines; + bool log_file_open; + + void OpenFile(); + }; diff --git a/main/main.cpp b/main/main.cpp index 3b90e6a..57ca806 100755 --- a/main/main.cpp +++ b/main/main.cpp @@ -44,7 +44,6 @@ void signal_term(int) - void print_syntax() { std::cout << "Syntax:" << std::endl; @@ -86,6 +85,11 @@ int main(int argv, char ** argc) log.Init(app.config.log_level, app.config.log_file, app.config.log_stdout, app.config.log_request); nlog.Init(app.config.log_level, app.config.log_notify_file, false, 1); + if( !app.DropPrivileges() ) + return 3; + + app.LogUserGroups(); + // app.config.base_server can be changed (stripped from 'http://' or a last slash) // it is done when the config is read log << log3 << "base_server: " << app.config.base_server << logend;