[PATCH] Drop root privileges (if we have them)

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi,

This patch is against 2.0.5 and has been tested on a Linux 2.4.22 box running glibc-2.3.2 and compiled with gcc-3.2.3. The idea is that since the GateKeeper is baring a lot of ports to the public Internet and does not need to run with root privileges, then it should be able to be launched at boot-time as an ordinary user and not as root.

Basically, the GateKeeper looks up a given username and then calls setgid() and setuid(). I have tested these syscalls under Linux to ensure that the GateKeeper cannot later reclaim root privileges.

I do not know how to achieve the same goal under Windows, so the WIN32 versions of my functions are just stubs.

And for interest, did you know that you can remove a chunk of template/inline code bloat by passing g++ the following flags?:

-frepo -fno-implement-inlines

The "-fno-implement-inlines" option tells the compiler not to generate a static or extern version of any inline function, whereas -frepo enables the compiler to eliminate duplicate template functions.

Cheers,
Chris
--- gk.cxx.orig	Wed Dec 11 07:30:52 2002
+++ gk.cxx	Tue Sep 16 23:04:06 2003
@@ -203,6 +203,14 @@
 
 #ifdef WIN32
 
+inline bool IsPrivilegedProcess()
+{
+	return false;
+}
+
+inline void SetProcessUser(const PString &username)
+{}
+
 BOOL WINAPI WinCtrlHandlerProc(DWORD dwCtrlType)
 {
 	PTRACE(1, "GK\tGatekeeper shutdown");
@@ -211,6 +219,48 @@
 }
 
 #else
+#  include <pwd.h>
+#  include <cstring>
+
+inline bool IsPrivilegedProcess()
+{
+	return (::geteuid() == 0);
+}
+
+static void SetProcessUser(const PString &username)
+{
+	static const size_t MAX_PASSWORD_BUFSIZE = 256;
+
+	struct passwd userdata;
+	struct passwd *userptr;
+	char buffer[MAX_PASSWORD_BUFSIZE];
+
+	int err = ::getpwnam_r(username,
+	                       &userdata,
+	                       buffer,
+	                       sizeof(buffer),
+	                       &userptr);
+	if (userptr == NULL) {
+		cerr << "Warning: Bad database entry for \""
+		     << username
+		     << "\": "
+		     << ::strerror(err)
+		     << endl;
+	}
+	else {
+		err = ::setgid(userptr->pw_gid);
+		if (err != 0)
+			cerr << "Failed to set group ID: "
+			     << ::strerror(err)
+			     << endl;
+
+		err = ::setuid(userptr->pw_uid);
+		if (err != 0)
+			cerr << "Failed to set user ID: "
+			     << ::strerror(err)
+			     << endl;
+	}
+}
 
 void UnixShutdownHandler(int sig)
 {
@@ -259,6 +309,7 @@
 		 "i-interface:"
 		 "l-timetolive:"
 		 "b-bandwidth:"
+		 "u-user:"
 #if PTRACING
 		 "t-trace."
 		 "o-output:"
@@ -363,6 +414,7 @@
 		"  -i  --interface IP : The IP that the gatekeeper listen to\n"
 		"  -l  --timetolive n : Time to live for client registration\n"
 		"  -b  --bandwidth n  : Specify the total bandwidth\n"
+		"  -u  --user name    : Run as this user\n"
 #if PTRACING
 		"  -t  --trace        : Set trace verbosity\n"
 		"  -o  --output file  : Write trace to this file\n"
@@ -394,6 +446,10 @@
 {
 	PArgList & args = GetArguments();
 	args.Parse(GetArgumentsParseString());
+
+	if (args.HasOption('u') && IsPrivilegedProcess()) {
+		SetProcessUser(args.GetOptionString('u'));
+	}
 
 	PIPSocket::Address GKHome = INADDR_ANY;
 

[Index of Archives]     [SIP]     [Open H.323]     [Gnu Gatekeeper]     [Asterisk PBX]     [ISDN Cause Codes]     [Yosemite News]

  Powered by Linux