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.

Comments

blog comments powered by Disqus

Categories