FAM Non-superuser Hack

FAM is File Alteration Monitor.
Also see The Watchful Eye of FAM by Ethan McCallum.

I am trying to use it in an environment where I have no root access, and not using portmapper.
After some changes and testing, it seems to work.

  • Change SuperUser uid to the uid you intend to run the program with, and also SuperUser_groups gid.
  • Initialize Cred::Implementation::last = Cred::SuperUser.p;
  • Bind to a specific non-reserved port.
  • Remove the portmapper code following the binding.
  • Remove the superuser check.
  • Connect client to the same specific non-reserved port.
  • and initialize bestvers = 2; and remove the portmapper code checking out which port to connect to.

Disclaimer:I do not claim this changes works. Furthermore, I do not understand the security impact, so, use at your own risk if you do.

The changes are recorded in the 2 diff files, fam.src.diff and fam.lib.diff.

Common subdirectories: fam-2.7.0/src/.deps and fam-2.7.0p/src/.deps
diff -Nau -x Makefile fam-2.7.0/src/Cred.c++ fam-2.7.0p/src/Cred.c++
--- fam-2.7.0/src/Cred.c++	Fri Nov 21 14:38:48 2003
+++ fam-2.7.0p/src/Cred.c++	Wed Jul 11 07:49:37 2007
@@ -38,10 +38,13 @@
 #include 
 #endif

-static gid_t SuperUser_groups[1] = { 0 };
-const Cred Cred::SuperUser(0, 1, SuperUser_groups, -1);
+//static gid_t SuperUser_groups[1] = { 0 };
+//const Cred Cred::SuperUser(0, 1, SuperUser_groups, -1);
+static gid_t SuperUser_groups[1] = { 111 };
+const Cred Cred::SuperUser(2222, 1, SuperUser_groups, -1);
 Cred Cred::untrusted;
-const Cred::Implementation *Cred::Implementation::last = NULL;
+//const Cred::Implementation *Cred::Implementation::last = NULL;
+const Cred::Implementation *Cred::Implementation::last = Cred::SuperUser.p;
 Cred::Implementation **Cred::impllist;
 unsigned Cred::nimpl;
 unsigned Cred::nimpl_alloc;
diff -Nau -x Makefile fam-2.7.0/src/Listener.c++ fam-2.7.0p/src/Listener.c++
--- fam-2.7.0/src/Listener.c++	Sun Jan 19 17:37:29 2003
+++ fam-2.7.0p/src/Listener.c++	Wed Jul 11 04:07:01 2007
@@ -87,14 +87,18 @@
 	{   Log::perror("can't create TCP/IP socket for rendezvous");
 	    exit(1);
 	}
+	//struct sockaddr_in addr;
 	struct sockaddr_in addr;
 	memset(&addr, 0, sizeof addr);
 	addr.sin_family = AF_INET;
         addr.sin_addr.s_addr = local_only ? htonl(INADDR_LOOPBACK) : 0;
-	addr.sin_port = htons(0);
-	if (bindresvport(sock, &addr) < 0)
+	//addr.sin_port = htons(0);
+	addr.sin_port = htons(7777);
+	//if (bindresvport(sock, &addr) < 0)
+	if (bind(sock, (struct sockaddr*) &addr, sizeof(addr)) < 0)
 	{
-	    Log::perror("can't bind to reserved port");
+	    //Log::perror("can't bind to reserved port");
+	    Log::perror("can't bind to port 7777");
 	    exit(1);
 	}
 	if (listen(sock, 1) < 0)
@@ -102,12 +106,12 @@
 	    Log::perror("can't listen for rendezvous");
 	    exit(1);
 	}
-	(void) pmap_unset(program, version);
-	if (!pmap_set(program, version, IPPROTO_TCP, ntohs(addr.sin_port)))
-	{
-	    Log::error("can't register with portmapper.");
-	    exit(1);
-	}
+	//(void) pmap_unset(program, version);
+	//if (!pmap_set(program, version, IPPROTO_TCP, ntohs(addr.sin_port)))
+	//{
+	//    Log::error("can't register with portmapper.");
+	//    exit(1);
+	//}
 	set_rendezvous_fd(sock);
     }
 }
diff -Nau -x Makefile fam-2.7.0/src/main.c++ fam-2.7.0p/src/main.c++
--- fam-2.7.0/src/main.c++	Sat Jan 18 23:15:51 2003
+++ fam-2.7.0p/src/main.c++	Wed Jul 11 02:46:52 2007
@@ -157,10 +157,10 @@
         }
     }

-    if (getuid() != 0)
-    {   Log::error("must be superuser");
-	exit(1);
-    }
+    //if (getuid() != 0)
+    //{   Log::error("must be superuser");
+//	exit(1);
+    //}

     parse_config(opts);

Changes to the client library side.

Common subdirectories: fam-2.7.0/lib/.deps and fam-2.7.0p/lib/.deps
diff -Nau -x Makefile fam-2.7.0/lib/Client.c++ fam-2.7.0p/lib/Client.c++
--- fam-2.7.0/lib/Client.c++	Sat Jan 18 07:18:12 2003
+++ fam-2.7.0p/lib/Client.c++	Wed Jul 11 07:05:01 2007
@@ -52,6 +52,7 @@
     sin.sin_addr.s_addr = htonl(host);
     //  This is set below instead.
     //sin.sin_port = htons(pmap_getport(&sin, prog, vers, IPPROTO_TCP));
+    sin.sin_port = htons(7777);

     //
     //  We'll run through the list of pmaps ourselves instead of calling
@@ -60,6 +61,8 @@
     //  need to know which version of fam we're talking to.  (Isn't there
     //  an easier way to do that?)
     //
+    unsigned long bestvers = 2;
+/*
     pmaplist *pl = pmap_getmaps(&sin);  //  this is leaked; see note below loop
     unsigned long bestvers = 0;
     for (pmaplist *plp = pl; plp != NULL; plp = plp->pml_next)
@@ -83,7 +86,7 @@
     //  just leak it.  This sucks!  (call CLNT_CALL(client, PMAPPROC_DUMP, ...
     //  ourselves?)
     //xdr_free((xdrproc_t)xdr_pmaplist, &pl);
-
+*/
     if(sin.sin_port == 0)
     {
         //  Couldn't get port for rpc call.

Post a Comment

Your email is never shared. Required fields are marked *

*
*