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.