--- /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 <znc/znc.h>
|
|
+#include <znc/User.h>
|
|
+#include <pwd.h>
|
|
+#include <grp.h>
|
|
+
|
|
+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 <uid> <gid>";
|
|
+ return false;
|
|
+ }
|
|
+
|
|
+ m_user = GetUser(sUser, sMessage);
|
|
+
|
|
+ if (m_user == 0) {
|
|
+ sMessage
|
|
+ = "Error: Cannot run as root, check your config file | Usage: LoadModule = Droproot <uid> <gid>";
|
|
+ return false;
|
|
+ }
|
|
+
|
|
+ m_group = GetGroup(sGroup, sMessage);
|
|
+
|
|
+ if (m_group == 0) {
|
|
+ sMessage
|
|
+ = "Error: Cannot run as root, check your config file | Usage: LoadModule = Droproot <uid> <gid>";
|
|
+ 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.")
|