--- /dev/null +++ b/modules/droproot.cpp @@ -0,0 +1,144 @@ +/* + * droproot.cpp + * + * Copyright (c) 2009 Vadtec (vadtec@vadtec.net) + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published + * by the Free Software Foundation. + * + * Copyright (C) 2004-2012 See the AUTHORS file for details. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published + * by the Free Software Foundation. + */ + +#include +#include +#include +#include + +class CDroproot : public CModule { + +public: + MODCONSTRUCTOR(CDroproot) { + } + + virtual ~CDroproot() { + } + + uid_t GetUser(const CString& sUser, CString& sMessage) { + uid_t ret = sUser.ToUInt(); + + if (ret != 0) + return ret; + + struct passwd *pUser = getpwnam(sUser.c_str()); + + if (!pUser) { + sMessage = "User [" + sUser + "] not found!"; + return 0; + } + + return pUser->pw_uid; + } + + gid_t GetGroup(const CString& sGroup, CString& sMessage) { + gid_t ret = sGroup.ToUInt(); + + if (ret != 0) + return ret; + + struct group *pGroup = getgrnam(sGroup.c_str()); + + if (!pGroup) { + sMessage = "Group [" + sGroup + "] not found!"; + return 0; + } + + return pGroup->gr_gid; + } + + virtual bool OnLoad(const CString& sArgs, CString& sMessage) { + CString sUser = sArgs.Token(0); + CString sGroup = sArgs.Token(1, true); + + if (sUser.empty() || sGroup.empty()) { + sMessage = "Usage: LoadModule = Droproot "; + return false; + } + + m_user = GetUser(sUser, sMessage); + + if (m_user == 0) { + sMessage + = "Error: Cannot run as root, check your config file | Useage: LoadModule = Droproot "; + return false; + } + + m_group = GetGroup(sGroup, sMessage); + + if (m_group == 0) { + sMessage + = "Error: Cannot run as root, check your config file | Useage: LoadModule = Droproot "; + return false; + } + + return true; + } + + virtual bool OnBoot() { + int u, eu, g, eg, sg; + + if ((geteuid() == 0) || (getuid() == 0) || (getegid() == 0) || (getgid() + == 0)) { + + CUtils::PrintAction("Dropping root permissions"); + + // Clear all the supplementary groups + sg = setgroups(0, NULL); + + if (sg < 0) { + CUtils::PrintStatus(false, + "Could not remove supplementary groups! [" + + CString(strerror(errno)) + "]"); + + return false; + } + + // Set the group (if we are root, this sets all three group IDs) + g = setgid(m_group); + eg = setegid(m_group); + + if ((g < 0) || (eg < 0)) { + CUtils::PrintStatus(false, "Could not switch group id! [" + + CString(strerror(errno)) + "]"); + + return false; + } + + // and set the user (if we are root, this sets all three user IDs) + u = setuid(m_user); + eu = seteuid(m_user); + + if ((u < 0) || (eu < 0)) { + CUtils::PrintStatus(false, "Could not switch user id! [" + + CString(strerror(errno)) + "]"); + + return false; + } + + CUtils::PrintStatus(true); + + return true; + } + + return true; + } + +protected: + uid_t m_user; + gid_t m_group; +}; + +GLOBALMODULEDEFS(CDroproot, "Allows ZNC to drop root privileges and run as an un-privileged user.")