changeset 1415:adb678c592f5

Remove RMI-based agent-proxy mechanism. It was discovered that, in certain configurations, the Thermostat agent disclosed JMX management URLs of all local Java virtual machines to any local user. A local, unprivileged user could use this flaw to escalate their privileges on the system. (CVE-2014-8120) More information will be available at: http://cve.mitre.org/cgi-bin/cvename.gci?name=CVE=2014-8120
author Elliott Baron <ebaron@redhat.com>
date Tue, 16 Dec 2014 11:54:58 -0700
parents 2c1c1a161396
children 2bdbf31ce2a6
files agent/core/pom.xml agent/core/src/main/java/com/redhat/thermostat/agent/RMIRegistry.java agent/core/src/main/java/com/redhat/thermostat/agent/internal/Activator.java agent/core/src/main/java/com/redhat/thermostat/agent/internal/RMIRegistryImpl.java agent/core/src/main/java/com/redhat/thermostat/utils/management/internal/AgentProxyClient.java agent/core/src/main/java/com/redhat/thermostat/utils/management/internal/MXBeanConnectionPoolImpl.java agent/core/src/main/java/com/redhat/thermostat/utils/management/internal/MXBeanConnector.java agent/core/src/main/java/com/redhat/thermostat/utils/management/internal/ProcessUserInfoBuilder.java agent/core/src/test/java/com/redhat/thermostat/agent/internal/ActivatorTest.java agent/core/src/test/java/com/redhat/thermostat/agent/internal/RMIRegistryImplTest.java agent/core/src/test/java/com/redhat/thermostat/utils/management/internal/AgentProxyClientTest.java agent/core/src/test/java/com/redhat/thermostat/utils/management/internal/MXBeanConnectionPoolImplTest.java agent/core/src/test/java/com/redhat/thermostat/utils/management/internal/MXBeanConnectorTest.java agent/proxy/pom.xml agent/proxy/server/Makefile agent/proxy/server/pom.xml agent/proxy/server/src/main/java/com/redhat/thermostat/agent/proxy/server/AgentProxy.java agent/proxy/server/src/main/java/com/redhat/thermostat/agent/proxy/server/AgentProxyControlImpl.java agent/proxy/server/src/main/java/com/redhat/thermostat/agent/proxy/server/AgentProxyControlWrapper.java agent/proxy/server/src/main/java/com/redhat/thermostat/agent/proxy/server/AgentProxyLoginContext.java agent/proxy/server/src/main/java/com/redhat/thermostat/agent/proxy/server/AgentProxyLoginImpl.java agent/proxy/server/src/main/java/com/redhat/thermostat/agent/proxy/server/AgentProxyLoginModule.java agent/proxy/server/src/main/java/com/redhat/thermostat/agent/proxy/server/AgentProxyNativeUtils.java agent/proxy/server/src/main/java/com/redhat/thermostat/agent/proxy/server/AgentProxyPrincipal.java agent/proxy/server/src/main/java/com/redhat/thermostat/agent/proxy/server/ProcDataSource.java agent/proxy/server/src/main/java/com/redhat/thermostat/agent/proxy/server/ProcessUserInfoBuilder.java agent/proxy/server/src/main/java/com/redhat/thermostat/agent/proxy/server/RegistryUtils.java agent/proxy/server/src/main/java/com/redhat/thermostat/agent/proxy/server/ShutdownListener.java agent/proxy/server/src/main/java/com/redhat/thermostat/agent/proxy/server/UnixCredentials.java agent/proxy/server/src/main/native/AgentProxy.c agent/proxy/server/src/test/java/com/redhat/thermostat/agent/proxy/server/AgentProxyControlImplTest.java agent/proxy/server/src/test/java/com/redhat/thermostat/agent/proxy/server/AgentProxyControlWrapperTest.java agent/proxy/server/src/test/java/com/redhat/thermostat/agent/proxy/server/AgentProxyLoginContextTest.java agent/proxy/server/src/test/java/com/redhat/thermostat/agent/proxy/server/AgentProxyLoginImplTest.java agent/proxy/server/src/test/java/com/redhat/thermostat/agent/proxy/server/AgentProxyLoginModuleTest.java agent/proxy/server/src/test/java/com/redhat/thermostat/agent/proxy/server/AgentProxyTest.java agent/proxy/server/src/test/java/com/redhat/thermostat/agent/proxy/server/ProcessUserInfoBuilderTest.java distribution/assembly/core-assembly.xml distribution/config/agent_proxy_jaas.conf distribution/config/commands/agent.properties distribution/config/commands/service.properties distribution/pom.xml distribution/scripts/thermostat distribution/scripts/thermostat-agent-proxy
diffstat 44 files changed, 489 insertions(+), 2649 deletions(-) [+]
line wrap: on
line diff
--- a/agent/core/pom.xml	Thu Aug 21 15:21:57 2014 -0400
+++ b/agent/core/pom.xml	Tue Dec 16 11:54:58 2014 -0700
@@ -75,11 +75,6 @@
     </dependency>
     <dependency>
       <groupId>com.redhat.thermostat</groupId>
-      <artifactId>thermostat-agent-proxy-common</artifactId>
-      <version>${project.version}</version>
-    </dependency>
-    <dependency>
-      <groupId>com.redhat.thermostat</groupId>
       <artifactId>thermostat-launcher</artifactId>
       <version>${project.version}</version>
     </dependency>
--- a/agent/core/src/main/java/com/redhat/thermostat/agent/RMIRegistry.java	Thu Aug 21 15:21:57 2014 -0400
+++ b/agent/core/src/main/java/com/redhat/thermostat/agent/RMIRegistry.java	Tue Dec 16 11:54:58 2014 -0700
@@ -45,8 +45,13 @@
 /**
  * Maintains an RMI registry used for inter-process communication between
  * the Thermostat agent and other helper processes on the same host.
+ * 
+ * <p>
+ * <b> RMI is no longer used by the Thermostat agent. Invoking any of this
+ * service's methods will result in a {@link RemoteException}. </b>
  */
 @Service
+@Deprecated
 public interface RMIRegistry {
 
     /**
--- a/agent/core/src/main/java/com/redhat/thermostat/agent/internal/Activator.java	Thu Aug 21 15:21:57 2014 -0400
+++ b/agent/core/src/main/java/com/redhat/thermostat/agent/internal/Activator.java	Tue Dec 16 11:54:58 2014 -0700
@@ -62,14 +62,15 @@
         context.registerService(RMIRegistry.class, registry, null);
         ServiceReference<CommonPaths> pathsRef = context.getServiceReference(CommonPaths.class);
         CommonPaths paths = context.getService(pathsRef);
-        pool = new MXBeanConnectionPoolImpl(registry, paths.getSystemBinRoot());
+        UserNameUtilImpl usernameUtil = new UserNameUtilImpl();
+        context.registerService(UserNameUtil.class, usernameUtil, null);
+        pool = new MXBeanConnectionPoolImpl(paths.getSystemBinRoot(), usernameUtil);
         context.registerService(MXBeanConnectionPool.class, pool, null);
         StorageCredentials creds = new AgentStorageCredentials(paths.getUserAgentAuthConfigFile());
         context.registerService(StorageCredentials.class, creds, null);
         AgentConfigsUtils.setConfigFiles(paths.getSystemAgentConfigurationFile(), paths.getUserAgentConfigurationFile());
         paths = null;
         context.ungetService(pathsRef);
-        context.registerService(UserNameUtil.class, new UserNameUtilImpl(), null);
         VmBlacklistImpl blacklist = new VmBlacklistImpl();
         blacklist.addVmFilter(new AgentProxyFilter());
         context.registerService(VmBlacklist.class, blacklist, null);
@@ -78,10 +79,7 @@
     @Override
     public void stop(BundleContext context) throws Exception {
         // Services automatically unregistered by framework
-        if (pool != null) {
-            pool.shutdown();
-            pool = null;
-        }
+        pool = null;
     }
 
     // Testing hook.
--- a/agent/core/src/main/java/com/redhat/thermostat/agent/internal/RMIRegistryImpl.java	Thu Aug 21 15:21:57 2014 -0400
+++ b/agent/core/src/main/java/com/redhat/thermostat/agent/internal/RMIRegistryImpl.java	Tue Dec 16 11:54:58 2014 -0700
@@ -36,121 +36,32 @@
 
 package com.redhat.thermostat.agent.internal;
 
-import java.io.IOException;
-import java.net.InetAddress;
-import java.net.ServerSocket;
-import java.rmi.NoSuchObjectException;
 import java.rmi.Remote;
 import java.rmi.RemoteException;
-import java.rmi.registry.LocateRegistry;
 import java.rmi.registry.Registry;
-import java.rmi.server.RMIClientSocketFactory;
-import java.rmi.server.RMIServerSocketFactory;
-import java.rmi.server.RMISocketFactory;
-import java.rmi.server.UnicastRemoteObject;
-import java.util.logging.Logger;
 
 import com.redhat.thermostat.agent.RMIRegistry;
-import com.redhat.thermostat.common.utils.LoggingUtils;
 
+@Deprecated
 public class RMIRegistryImpl implements RMIRegistry {
     
-    private static final Logger logger = LoggingUtils.getLogger(RMIRegistryImpl.class);
-
-    private RegistryWrapper registryWrapper;
-    private ServerSocketCreator serverSockCreator;
-    private Registry registry;
-    
-    public RMIRegistryImpl() {
-        this(new RegistryWrapper(), new ServerSocketCreator());
-    }
-    
-    RMIRegistryImpl(RegistryWrapper registryWrapper, ServerSocketCreator serverSockCreator) {
-        this.registryWrapper = registryWrapper;
-        this.serverSockCreator = serverSockCreator;
-    }
-    
-    public void start() throws RemoteException {
-        this.registry = registryWrapper.createRegistry(Registry.REGISTRY_PORT /* TODO customize */,
-                RMISocketFactory.getDefaultSocketFactory(),
-                new RMIServerSocketFactory() {
-                    
-                    @Override
-                    public ServerSocket createServerSocket(int port) throws IOException {
-                        // Allow only local connections
-                        return serverSockCreator.createSocket(port, 0, InetAddress.getLoopbackAddress());
-                    }
-                });
-        logger.fine("Starting RMI registry");
+    RMIRegistryImpl() {
     }
     
     @Override
     public Registry getRegistry() throws RemoteException {
-        // We get a class loading problem when returning the local registry reference,
-        // this returns a remote stub reference instead
-        return registryWrapper.getRegistry();
-    }
-    
-    public void stop() throws RemoteException {
-        if (registry != null) {
-            registryWrapper.destroyRegistry(registry);
-            registry = null;
-            logger.fine("Shutting down RMI registry");
-        }
+        throw new RemoteException("RMI is no longer used");
     }
     
     @Override
     public Remote export(Remote obj) throws RemoteException {
-        if (registry == null) {
-            throw new RemoteException("RMI registry is not running");
-        }
-        return registryWrapper.export(obj, 0);
+        throw new RemoteException("RMI is no longer used");
     }
     
     @Override
     public boolean unexport(Remote obj) throws RemoteException {
-        if (registry == null) {
-            throw new RemoteException("RMI registry is not running");
-        }
-        return registryWrapper.unexport(obj, true);
-    }
-    
-    /*
-     * For testing purposes only.
-     */
-    Registry getRegistryImpl() {
-        return registry;
+        throw new RemoteException("RMI is no longer used");
     }
     
-    static class RegistryWrapper {
-        Registry createRegistry(int port, RMIClientSocketFactory csf,
-                RMIServerSocketFactory ssf) throws RemoteException {
-            return LocateRegistry.createRegistry(port, csf, ssf);
-        }
-        
-        Registry getRegistry() throws RemoteException {
-            return LocateRegistry.getRegistry(InetAddress.getLoopbackAddress().getHostName());
-        }
-        
-        void destroyRegistry(Registry registry) throws NoSuchObjectException {
-            // Shuts down RMI registry
-            UnicastRemoteObject.unexportObject(registry, true);
-        }
-        
-        Remote export(Remote obj, int port) throws RemoteException {
-            return UnicastRemoteObject.exportObject(obj, 0);
-        }
-        
-        boolean unexport(Remote obj, boolean force) throws NoSuchObjectException {
-            return UnicastRemoteObject.unexportObject(obj, force);
-        }
-    }
-    
-    static class ServerSocketCreator {
-        ServerSocket createSocket(int port, int backlog, InetAddress bindAddr) throws IOException {
-            return new ServerSocket(port, backlog, bindAddr);
-        }
-    }
-
 }
 
--- a/agent/core/src/main/java/com/redhat/thermostat/utils/management/internal/AgentProxyClient.java	Thu Aug 21 15:21:57 2014 -0400
+++ b/agent/core/src/main/java/com/redhat/thermostat/utils/management/internal/AgentProxyClient.java	Tue Dec 16 11:54:58 2014 -0700
@@ -36,141 +36,107 @@
 
 package com.redhat.thermostat.utils.management.internal;
 
+import java.io.BufferedReader;
 import java.io.File;
 import java.io.IOException;
-import java.rmi.NotBoundException;
-import java.rmi.RemoteException;
-import java.rmi.registry.Registry;
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.TimeUnit;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.util.logging.Level;
 import java.util.logging.Logger;
 
-import com.redhat.thermostat.agent.RMIRegistry;
-import com.redhat.thermostat.agent.proxy.common.AgentProxyControl;
-import com.redhat.thermostat.agent.proxy.common.AgentProxyListener;
-import com.redhat.thermostat.agent.proxy.common.AgentProxyLogin;
 import com.redhat.thermostat.common.tools.ApplicationException;
-import com.redhat.thermostat.common.utils.LoggedExternalProcess;
 import com.redhat.thermostat.common.utils.LoggingUtils;
 
-class AgentProxyClient implements AgentProxyListener {
+class AgentProxyClient {
     
-    private static final long SERVER_TIMEOUT_MS = 5000L;
     private static final String SERVER_NAME = "thermostat-agent-proxy";
     private static final Logger logger = LoggingUtils.getLogger(AgentProxyClient.class);
     
-    private final RMIRegistry registry;
     private final int pid;
     private final ProcessCreator procCreator;
     private final File binPath;
-    private final CountDownLatch started;
+    private final String username;
     
-    private AgentProxyControl proxy;
-    private Exception serverError;
-    
-    AgentProxyClient(RMIRegistry registry, int pid, File binPath) {
-        this(registry, pid, binPath, new CountDownLatch(1), 
-                new ProcessCreator());
+    AgentProxyClient(int pid, String user, File binPath) {
+        this(pid, user, binPath, new ProcessCreator());
     }
 
-    AgentProxyClient(RMIRegistry registry, int pid, File binPath,
-            CountDownLatch started, ProcessCreator procCreator) {
-        this.registry = registry;
+    AgentProxyClient(int pid, String user, File binPath, ProcessCreator procCreator) {
         this.pid = pid;
         this.binPath = binPath;
-        this.started = started;
         this.procCreator = procCreator;
+        this.username = user;
     }
 
-    void createProxy() throws IOException, ApplicationException {
-        // Export our listener
-        AgentProxyListener stub = (AgentProxyListener) registry.export(this);
-        String listenerName = REMOTE_PREFIX + String.valueOf(pid);
-        Registry reg = registry.getRegistry();
-        reg.rebind(listenerName, stub);
-        logger.fine("Registered proxy listener for " + pid);
+    String getJMXServiceURL() throws IOException, ApplicationException {
+        // Start the agent proxy
+        Process proxy = null;
+        Thread errReaderThread = null;
+        try {
+            proxy = startProcess();
+
+            final InputStream errStream = proxy.getErrorStream();
 
-        // Start the agent proxy, and wait until it exports itself
-        try {
-            startProcess();
-        } finally {
-            // Got started event or timed out, unregister our listener
+            // Log stderr in a separate thread
+            errReaderThread = new Thread(new Runnable() {
+                @Override
+                public void run() {
+                    BufferedReader errReader = new BufferedReader(new InputStreamReader(errStream));
+                    String line;
+                    try {
+                        while ((line = errReader.readLine()) != null 
+                                && !Thread.currentThread().isInterrupted()) {
+                            logger.info(line);
+                        }
+                        errReader.close();
+                    } catch (IOException e) {
+                        logger.log(Level.WARNING, "Failed to read error stream", e);
+                    }
+                }
+            });
+            errReaderThread.start();
+
+            // Get JMX service URL from stdout
+            BufferedReader outReader = new BufferedReader(new InputStreamReader(proxy.getInputStream()));
+            String url = outReader.readLine();
+
+            // Wait for process to terminate
             try {
-                reg.unbind(listenerName);
-                registry.unexport(this);
-            } catch (NotBoundException e) {
-                throw new RemoteException("Error unregistering listener", e);
+                proxy.waitFor();
+            } catch (InterruptedException e) {
+                errReaderThread.interrupt();
+                Thread.currentThread().interrupt();
             }
-        }
+            outReader.close();
+            if (url == null) {
+                throw new IOException("Failed to determine JMX service URL from proxy process");
+            }
 
-        // Check if server started successfully
-        if (serverError != null) {
-            throw new RemoteException("Server failed to start", serverError);
-        }
-
-        // Lookup server
-        String serverName = AgentProxyLogin.REMOTE_PREFIX + String.valueOf(pid);
-        try {
-            // Need to authenticate in order to obtain proxy object
-            AgentProxyLogin proxyLogin = (AgentProxyLogin) reg.lookup(serverName);
-            proxy = proxyLogin.login();
-        } catch (NotBoundException e) {
-            throw new RemoteException("Unable to find remote interface", e);
+            return url;
+        } finally {
+            if (proxy != null) {
+                proxy.destroy();
+            }
+            if (errReaderThread != null) {
+                try {
+                    errReaderThread.join();
+                } catch (InterruptedException e) {
+                    errReaderThread.interrupt();
+                    Thread.currentThread().interrupt();
+                }
+            }
         }
     }
 
-    private void startProcess() throws IOException, ApplicationException {
+    private Process startProcess() throws IOException, ApplicationException {
         String serverPath = binPath + File.separator + SERVER_NAME;
-        procCreator.createAndRunProcess(new String[] { serverPath, String.valueOf(pid) });
-        try {
-            boolean result = started.await(SERVER_TIMEOUT_MS, TimeUnit.MILLISECONDS);
-            if (!result) {
-                throw new RemoteException("Timeout while waiting for server");
-            }
-        } catch (InterruptedException e) {
-            // Restore interrupted status
-            Thread.currentThread().interrupt();
-        }
-    }
-    
-    void attach() throws RemoteException {
-        proxy.attach();
-    }
-    
-    boolean isAttached() throws RemoteException {
-        return proxy.isAttached();
-    }
-    
-    String getConnectorAddress() throws RemoteException {
-        return proxy.getConnectorAddress();
-    }
-    
-    void detach() throws RemoteException {
-        proxy.detach();
-    }
-    
-    @Override
-    public void serverStarted() throws RemoteException {
-        started.countDown();
-    }
-
-    @Override
-    public void serverFailedToStart(Exception error) throws RemoteException {
-        serverError = error;
-        started.countDown();
-    }
-    
-    /*
-     * For testing purposes only.
-     */
-    AgentProxyControl getProxy() {
-        return proxy;
+        return procCreator.createAndRunProcess(new String[] { serverPath, String.valueOf(pid), username });
     }
     
     static class ProcessCreator {
         Process createAndRunProcess(String[] args) throws IOException, ApplicationException {
-            LoggedExternalProcess process = new LoggedExternalProcess(args);
-            return process.runAndReturnProcess();
+            ProcessBuilder process = new ProcessBuilder(args);
+            return process.start();
         }
     }
     
--- a/agent/core/src/main/java/com/redhat/thermostat/utils/management/internal/MXBeanConnectionPoolImpl.java	Thu Aug 21 15:21:57 2014 -0400
+++ b/agent/core/src/main/java/com/redhat/thermostat/utils/management/internal/MXBeanConnectionPoolImpl.java	Tue Dec 16 11:54:58 2014 -0700
@@ -38,46 +38,34 @@
 
 import java.io.File;
 import java.io.IOException;
-import java.rmi.RemoteException;
 import java.util.HashMap;
 import java.util.Map;
-import java.util.logging.Level;
-import java.util.logging.Logger;
 
-import com.redhat.thermostat.agent.RMIRegistry;
-import com.redhat.thermostat.agent.internal.RMIRegistryImpl;
+import com.redhat.thermostat.agent.utils.ProcDataSource;
 import com.redhat.thermostat.agent.utils.management.MXBeanConnection;
 import com.redhat.thermostat.agent.utils.management.MXBeanConnectionPool;
+import com.redhat.thermostat.agent.utils.username.UserNameUtil;
 import com.redhat.thermostat.common.Pair;
 import com.redhat.thermostat.common.tools.ApplicationException;
-import com.redhat.thermostat.common.utils.LoggingUtils;
+import com.redhat.thermostat.utils.management.internal.ProcessUserInfoBuilder.ProcessUserInfo;
 
 public class MXBeanConnectionPoolImpl implements MXBeanConnectionPool {
 
-    private static final Logger logger = LoggingUtils.getLogger(MXBeanConnectionPoolImpl.class);
-    
     // pid -> (usageCount, actualObject)
     private Map<Integer, Pair<Integer, MXBeanConnectionImpl>> pool = new HashMap<>();
 
     private final ConnectorCreator creator;
-    private final RMIRegistryImpl registry;
     private final File binPath;
+    private final ProcessUserInfoBuilder userInfoBuilder;
 
-    public MXBeanConnectionPoolImpl(RMIRegistryImpl registry, File binPath) {
-        this(new ConnectorCreator(), registry, binPath);
+    public MXBeanConnectionPoolImpl(File binPath, UserNameUtil userNameUtil) {
+        this(new ConnectorCreator(), binPath, new ProcessUserInfoBuilder(new ProcDataSource(), userNameUtil));
     }
 
-    MXBeanConnectionPoolImpl(ConnectorCreator connectorCreator, RMIRegistryImpl registry, File binPath) {
+    MXBeanConnectionPoolImpl(ConnectorCreator connectorCreator, File binPath, ProcessUserInfoBuilder userInfoBuilder) {
         this.creator = connectorCreator;
-        this.registry = registry;
         this.binPath = binPath;
-        
-        // Start RMI registry
-        try {
-            registry.start();
-        } catch (RemoteException e) {
-            logger.log(Level.SEVERE, "Unable to start RMI registry", e);
-        }
+        this.userInfoBuilder = userInfoBuilder;
     }
 
     @Override
@@ -85,16 +73,14 @@
         Pair<Integer, MXBeanConnectionImpl> data = pool.get(pid);
         if (data == null) {
             MXBeanConnector connector = null;
-            try {
-                connector = creator.create(registry, pid, binPath);
-                connector.attach();
-                MXBeanConnectionImpl connection = connector.connect();
-                data = new Pair<Integer, MXBeanConnectionImpl>(1, connection);
-            } finally {
-                if (connector != null) {
-                    connector.close();
-                }
+            ProcessUserInfo info = userInfoBuilder.build(pid);
+            String username = info.getUsername();
+            if (username == null) {
+                throw new IOException("Unable to determine owner of " + pid);
             }
+            connector = creator.create(pid, username, binPath);
+            MXBeanConnectionImpl connection = connector.connect();
+            data = new Pair<Integer, MXBeanConnectionImpl>(1, connection);
         } else {
             data = new Pair<>(data.getFirst() + 1, data.getSecond());
         }
@@ -117,17 +103,9 @@
         }
     }
     
-    public void shutdown() {
-        try {
-            registry.stop();
-        } catch (RemoteException e) {
-            logger.log(Level.SEVERE, "Unable to stop RMI registry", e);
-        }
-    }
-
     static class ConnectorCreator {
-        public MXBeanConnector create(RMIRegistry registry, int pid, File binPath) throws IOException, ApplicationException {
-            MXBeanConnector connector = new MXBeanConnector(registry, pid, binPath);
+        public MXBeanConnector create(int pid, String user, File binPath) throws IOException, ApplicationException {
+            MXBeanConnector connector = new MXBeanConnector(pid, user, binPath);
             return connector;
         }
     }
--- a/agent/core/src/main/java/com/redhat/thermostat/utils/management/internal/MXBeanConnector.java	Thu Aug 21 15:21:57 2014 -0400
+++ b/agent/core/src/main/java/com/redhat/thermostat/utils/management/internal/MXBeanConnector.java	Tue Dec 16 11:54:58 2014 -0700
@@ -36,40 +36,32 @@
 
 package com.redhat.thermostat.utils.management.internal;
 
-import java.io.Closeable;
 import java.io.File;
 import java.io.IOException;
-import java.rmi.RemoteException;
 
 import javax.management.MBeanServerConnection;
 import javax.management.remote.JMXConnector;
 import javax.management.remote.JMXConnectorFactory;
 import javax.management.remote.JMXServiceURL;
 
-import com.redhat.thermostat.agent.RMIRegistry;
 import com.redhat.thermostat.common.tools.ApplicationException;
 
-class MXBeanConnector implements Closeable {
+class MXBeanConnector {
     
-    private final AgentProxyClient client;
     private final JMXConnectionCreator jmxCreator;
+    private final String serviceURL;
     
-    public MXBeanConnector(RMIRegistry registry, int pid, File binPath) throws IOException, ApplicationException {
-        this(new AgentProxyClient(registry, pid, binPath), new JMXConnectionCreator());
+    public MXBeanConnector(int pid, String user, File binPath) throws IOException, ApplicationException {
+        this(new AgentProxyClient(pid, user, binPath), new JMXConnectionCreator());
     }
     
     MXBeanConnector(AgentProxyClient client, JMXConnectionCreator jmxCreator) throws IOException, ApplicationException {
-        this.client = client;
         this.jmxCreator = jmxCreator;
-        client.createProxy();
-    }
-    
-    public synchronized void attach() throws Exception {
-        client.attach();
+        this.serviceURL = client.getJMXServiceURL();
     }
     
     public synchronized MXBeanConnectionImpl connect() throws IOException {
-        JMXServiceURL url = new JMXServiceURL(client.getConnectorAddress());
+        JMXServiceURL url = new JMXServiceURL(serviceURL);
         JMXConnector connection = jmxCreator.create(url);
         MBeanServerConnection mbsc = null;
         try {
@@ -83,15 +75,6 @@
         return new MXBeanConnectionImpl(connection, mbsc);
     }
     
-    public boolean isAttached() throws RemoteException {
-        return client.isAttached();
-    }
-    
-    @Override
-    public synchronized void close() throws IOException {
-        client.detach();
-    }
-
     static class JMXConnectionCreator {
         JMXConnector create(JMXServiceURL url) throws IOException {
             return JMXConnectorFactory.connect(url);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/agent/core/src/main/java/com/redhat/thermostat/utils/management/internal/ProcessUserInfoBuilder.java	Tue Dec 16 11:54:58 2014 -0700
@@ -0,0 +1,141 @@
+/*
+ * Copyright 2012-2014 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are not obligated to do so.  If you do not wish
+ * to do so, delete this exception statement from your version.
+ */
+
+package com.redhat.thermostat.utils.management.internal;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.Reader;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import com.redhat.thermostat.agent.utils.ProcDataSource;
+import com.redhat.thermostat.agent.utils.username.UserNameLookupException;
+import com.redhat.thermostat.agent.utils.username.UserNameUtil;
+import com.redhat.thermostat.common.utils.LoggingUtils;
+
+/*
+ * FIXME: This class was copied from system-backend to avoid adding new API.
+ */
+class ProcessUserInfoBuilder {
+    
+    private static final ProcessUserInfo NON_EXISTENT_USER = new ProcessUserInfo();
+    private static final String PROC_STATUS_UID = "Uid:";
+    private static final Logger logger = LoggingUtils.getLogger(ProcessUserInfoBuilder.class);
+    private ProcDataSource source;
+    private UserNameUtil userNameUtil;
+    
+    ProcessUserInfoBuilder(ProcDataSource source, UserNameUtil userNameUtil) {
+        this.source = source;
+        this.userNameUtil = userNameUtil;
+    }
+    
+    static class ProcessUserInfo {
+        
+        private long uid;
+        private String username;
+        
+        ProcessUserInfo(long uid, String username) {
+            this.uid = uid;
+            this.username = username;
+        }
+        
+        ProcessUserInfo() {
+            this.uid = -1;
+            this.username = null;
+        }
+        
+        public long getUid() {
+            return uid;
+        }
+        
+        public String getUsername() {
+            return username;
+        }
+    }
+    
+    ProcessUserInfo build(int pid) {
+        ProcessUserInfo info = NON_EXISTENT_USER;
+        try {
+            Reader reader = source.getStatusReader(pid);
+            long uid = getUidFromProcfs(new BufferedReader(reader));
+            String name = null;
+            try {
+                name = userNameUtil.getUserName(uid);
+            } catch (UserNameLookupException e) {
+                logger.log(Level.WARNING, "Unable to retrieve username for uid: " + uid, e);
+            }
+            info = new ProcessUserInfo(uid, name);
+        } catch (IOException e) {
+            logger.log(Level.WARNING, "Unable to read user info for " + pid, e);
+        }
+        
+        return info;
+    }
+
+    /*
+     * Look for the following line:
+     * Uid:  <RealUid>   <EffectiveUid>   <SavedUid>   <FSUid>
+     */
+    private long getUidFromProcfs(BufferedReader br) throws IOException {
+        long uid = -1;
+        String line;
+        while ((line = br.readLine()) != null) {
+            line = line.trim();
+            if (line.startsWith(PROC_STATUS_UID)) {
+                String[] parts = line.split("\\s+");
+                if (parts.length == 5) {
+                    try {
+                        // Use Real UID
+                        uid = Long.parseLong(parts[1]);
+                    } catch (NumberFormatException e) {
+                        throw new IOException("Unexpected output from ps command", e);
+                    }
+                }
+                else {
+                    throw new IOException("Expected 5 parts from split /proc/${pid}/status output, got " + parts.length);
+                }
+            }
+        }
+        if (uid < 0) {
+            throw new IOException("Unable to determine UID from /proc/${pid}/status");
+        }
+        return uid;
+    }
+
+
+}
+
--- a/agent/core/src/test/java/com/redhat/thermostat/agent/internal/ActivatorTest.java	Thu Aug 21 15:21:57 2014 -0400
+++ b/agent/core/src/test/java/com/redhat/thermostat/agent/internal/ActivatorTest.java	Tue Dec 16 11:54:58 2014 -0700
@@ -89,8 +89,6 @@
         activator.setPool(pool);
 
         activator.stop(context);
-
-        verify(pool).shutdown();
     }
 }
 
--- a/agent/core/src/test/java/com/redhat/thermostat/agent/internal/RMIRegistryImplTest.java	Thu Aug 21 15:21:57 2014 -0400
+++ b/agent/core/src/test/java/com/redhat/thermostat/agent/internal/RMIRegistryImplTest.java	Tue Dec 16 11:54:58 2014 -0700
@@ -1,123 +1,36 @@
 package com.redhat.thermostat.agent.internal;
 
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNull;
-import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.anyInt;
 import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
 
-import java.io.IOException;
-import java.net.InetAddress;
 import java.rmi.Remote;
 import java.rmi.RemoteException;
-import java.rmi.registry.Registry;
-import java.rmi.server.RMIClientSocketFactory;
-import java.rmi.server.RMIServerSocketFactory;
-import java.rmi.server.RMISocketFactory;
 
 import org.junit.Before;
 import org.junit.Test;
-import org.mockito.ArgumentCaptor;
-
-import com.redhat.thermostat.agent.internal.RMIRegistryImpl.RegistryWrapper;
-import com.redhat.thermostat.agent.internal.RMIRegistryImpl.ServerSocketCreator;
 
 public class RMIRegistryImplTest {
     
-    private RegistryWrapper wrapper;
-    private Registry reg;
     private RMIRegistryImpl registry;
-    private ServerSocketCreator sockCreator;
     
     @Before
-    public void setup() throws RemoteException {
-        wrapper = mock(RegistryWrapper.class);
-        reg = mock(Registry.class);
-        when(wrapper.createRegistry(anyInt(), any(RMIClientSocketFactory.class), 
-                any(RMIServerSocketFactory.class))).thenReturn(reg);
-        sockCreator = mock(ServerSocketCreator.class);
-        
-        registry = new RMIRegistryImpl(wrapper, sockCreator);
-    }
-
-    @Test
-    public void testRegistryStart() throws IOException {
-        registry.start();
-        
-        ArgumentCaptor<Integer> portCaptor = ArgumentCaptor.forClass(Integer.class);
-        ArgumentCaptor<RMIClientSocketFactory> csfCaptor = ArgumentCaptor.forClass(RMIClientSocketFactory.class);
-        ArgumentCaptor<RMIServerSocketFactory> ssfCaptor = ArgumentCaptor.forClass(RMIServerSocketFactory.class);
-        verify(wrapper).createRegistry(portCaptor.capture(), csfCaptor.capture(), ssfCaptor.capture());
-        
-        // Ensure defaults used for port and client socket factory
-        int port = portCaptor.getValue();
-        assertEquals(Registry.REGISTRY_PORT, port);
-        
-        RMIClientSocketFactory csf = csfCaptor.getValue();
-        assertEquals(RMISocketFactory.getDefaultSocketFactory(), csf);
-        
-        // Ensure bound to loopback address
-        RMIServerSocketFactory ssf = ssfCaptor.getValue();
-        ssf.createServerSocket(port);
-        verify(sockCreator).createSocket(port, 0, InetAddress.getLoopbackAddress());
-    }
-
-    @Test
-    public void testRegistryStop() throws IOException {
-        registry.start();
-        
-        registry.stop();
-        
-        verify(wrapper).destroyRegistry(reg);
-        assertNull(registry.getRegistryImpl());
-    }
-    
-    @Test
-    public void testRegistryStopNotStarted() throws IOException {
-        registry.stop();
-        
-        verify(wrapper, never()).destroyRegistry(reg);
-    }
-    
-    @Test
-    public void testGetRegistry() throws Exception {
-        Registry stub = mock(Registry.class);
-        when(wrapper.getRegistry()).thenReturn(stub);
-        assertEquals(stub, registry.getRegistry());
-    }
-    
-    @Test
-    public void testExportObject() throws Exception {
-        Remote obj = mock(Remote.class);
-        Remote stub = mock(Remote.class);
-        when(wrapper.export(obj, 0)).thenReturn(stub);
-        
-        registry.start();
-        assertEquals(stub, registry.export(obj));
+    public void setup() throws Exception {
+        registry = new RMIRegistryImpl();
     }
     
     @Test(expected=RemoteException.class)
-    public void testExportObjectNotStarted() throws Exception {
+    public void testGetRegistry() throws Exception {
+        registry.getRegistry();
+    }
+    
+    @Test(expected=RemoteException.class)
+    public void testExportObject() throws Exception {
         Remote obj = mock(Remote.class);
         registry.export(obj);
     }
     
-    @Test
+    @Test(expected=RemoteException.class)
     public void testUnexportObject() throws Exception {
         Remote obj = mock(Remote.class);
-        when(wrapper.unexport(obj, true)).thenReturn(true);
-        
-        registry.start();
-        assertEquals(true, registry.unexport(obj));
-        verify(wrapper).unexport(obj, true);
-    }
-    
-    @Test(expected=RemoteException.class)
-    public void testUnexportObjectNotStarted() throws Exception {
-        Remote obj = mock(Remote.class);
         registry.unexport(obj);
     }
 }
--- a/agent/core/src/test/java/com/redhat/thermostat/utils/management/internal/AgentProxyClientTest.java	Thu Aug 21 15:21:57 2014 -0400
+++ b/agent/core/src/test/java/com/redhat/thermostat/utils/management/internal/AgentProxyClientTest.java	Tue Dec 16 11:54:58 2014 -0700
@@ -37,186 +37,117 @@
 package com.redhat.thermostat.utils.management.internal;
 
 import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
 import static org.mockito.Matchers.any;
-import static org.mockito.Mockito.doAnswer;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
+import java.io.ByteArrayInputStream;
 import java.io.File;
 import java.io.IOException;
-import java.rmi.RemoteException;
-import java.rmi.registry.Registry;
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.TimeUnit;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.logging.Handler;
+import java.util.logging.LogRecord;
 
 import org.junit.Before;
 import org.junit.Test;
-import org.mockito.invocation.InvocationOnMock;
-import org.mockito.stubbing.Answer;
+import org.mockito.ArgumentCaptor;
 
-import com.redhat.thermostat.agent.internal.RMIRegistryImpl;
-import com.redhat.thermostat.agent.proxy.common.AgentProxyControl;
-import com.redhat.thermostat.agent.proxy.common.AgentProxyListener;
-import com.redhat.thermostat.agent.proxy.common.AgentProxyLogin;
-import com.redhat.thermostat.common.tools.ApplicationException;
+import com.redhat.thermostat.common.utils.LoggingUtils;
 import com.redhat.thermostat.utils.management.internal.AgentProxyClient.ProcessCreator;
 
 public class AgentProxyClientTest {
     
     private AgentProxyClient client;
-    private RMIRegistryImpl rmi;
-    private Registry registry;
     private ProcessCreator procCreator;
-    private CountDownLatch latch;
-    private AgentProxyListener listenerStub;
-    private AgentProxyLogin proxyLogin;
-    private AgentProxyControl proxyControl;
+    private String user;
     private File binPath;
     
     @Before
     public void setup() throws Exception {
-        rmi = mock(RMIRegistryImpl.class);
-        listenerStub = mock(AgentProxyListener.class);
-        when(rmi.export(any(AgentProxyListener.class))).thenReturn(listenerStub);
-        registry = mock(Registry.class);
-        when(rmi.getRegistry()).thenReturn(registry);
-        proxyLogin = mock(AgentProxyLogin.class);
-        when(registry.lookup(AgentProxyLogin.REMOTE_PREFIX + "0")).thenReturn(proxyLogin);
-        proxyControl = mock(AgentProxyControl.class);
-        when(proxyLogin.login()).thenReturn(proxyControl);
-        
         procCreator = mock(ProcessCreator.class);
         binPath = new File("/path/to/thermostat/bin");
-        latch = mock(CountDownLatch.class);
+        user = "Hello";
+        client = new AgentProxyClient(9000, user, binPath, procCreator);
     }
     
     @Test
     public void testCreateProxy() throws Exception {
-        createClient();
-        
-        // Verify listener exported and bound
-        verify(rmi).export(client);
-        verify(registry).rebind(AgentProxyListener.REMOTE_PREFIX + "0", listenerStub);
+        Process proxy = mock(Process.class);
+        final String jmxUrl = "myJmxUrl";
+        when(proxy.getInputStream()).thenReturn(new ByteArrayInputStream(jmxUrl.getBytes()));
+        when(proxy.getErrorStream()).thenReturn(new ByteArrayInputStream(new byte[0]));
+        when(procCreator.createAndRunProcess(any(String[].class))).thenReturn(proxy);
         
-        // Verify server created
-        String progName = "/path/to/thermostat/bin" + File.separator + "thermostat-agent-proxy";
-        verify(procCreator).createAndRunProcess(new String[] { progName, "0" });
-        verify(latch).countDown();
-        
-        // Verify listener removed
-        verify(registry).unbind(AgentProxyListener.REMOTE_PREFIX + "0");
-        verify(rmi).unexport(client);
-        
-        // Verify login
-        verify(registry).lookup(AgentProxyLogin.REMOTE_PREFIX + "0");
-        verify(proxyLogin).login();
+        // Check returned URL
+        String result = client.getJMXServiceURL();
+        assertEquals(jmxUrl, result);
         
-        // Check returned proxy control
-        assertEquals(proxyControl, client.getProxy());
-    }
-
-    private void createClient() throws InterruptedException, IOException,
-            ApplicationException {
-        client = new AgentProxyClient(rmi, 0, binPath, latch, procCreator);
+        // Check process arguments
+        ArgumentCaptor<String[]> argsCaptor = ArgumentCaptor.forClass(String[].class);
+        verify(procCreator).createAndRunProcess(argsCaptor.capture());
+        String[] args = argsCaptor.getValue();
+        assertEquals(3, args.length);
+        assertEquals("/path/to/thermostat/bin/thermostat-agent-proxy", args[0]);
+        assertEquals("9000", args[1]);
+        assertEquals("Hello", args[2]);
         
-        doAnswer(new Answer<Boolean>() {
-            @Override
-            public Boolean answer(InvocationOnMock invocation) throws Throwable {
-                // Trigger server started
-                client.serverStarted();
-                return true;
-            }
-        }).when(latch).await(any(Long.class), any(TimeUnit.class));
-        
-        client.createProxy();
+        // Check cleanup
+        verify(proxy).waitFor();
     }
     
     @Test
-    public void testCreateProxyFailed() throws Exception {
-        client = new AgentProxyClient(rmi, 0, binPath, latch, procCreator);
+    public void testErrorHandler() throws Exception {
+        Process proxy = mock(Process.class);
+        final String errors = "This is an error\nThis is also an error\nOh no!\n";
+        when(proxy.getInputStream()).thenReturn(new ByteArrayInputStream(new byte[0]));
+        when(proxy.getErrorStream()).thenReturn(new ByteArrayInputStream(errors.getBytes()));
+        when(procCreator.createAndRunProcess(any(String[].class))).thenReturn(proxy);
         
-        final Exception error = mock(Exception.class);
-        doAnswer(new Answer<Boolean>() {
-            @Override
-            public Boolean answer(InvocationOnMock invocation) throws Throwable {
-                // Trigger server started
-                client.serverFailedToStart(error);
-                return true;
-            }
-        }).when(latch).await(any(Long.class), any(TimeUnit.class));
+        List<LogRecord> logMessages = new ArrayList<>();
+        TestLogHandler logHandler = new TestLogHandler(logMessages);
+        LoggingUtils.getLogger(AgentProxyClient.class).addHandler(logHandler);
         
         try {
-            client.createProxy();
-            fail("Expected RemoteException");
-        } catch (RemoteException e) {
-            assertEquals(error, e.getCause());
-        }
-        
-        // Verify listener exported and bound
-        verify(rmi).export(client);
-        verify(registry).rebind(AgentProxyListener.REMOTE_PREFIX + "0", listenerStub);
-        
-        // Verify server created
-        String progName = "/path/to/thermostat/bin" + File.separator + "thermostat-agent-proxy";
-        verify(procCreator).createAndRunProcess(new String[] { progName, "0" });
-        verify(latch).countDown();
-        
-        // Verify listener removed
-        verify(registry).unbind(AgentProxyListener.REMOTE_PREFIX + "0");
-        verify(rmi).unexport(client);
-    }
-    
-    @Test
-    public void testCreateProxyTimeout() throws Exception {
-        when(latch.await(any(Long.class), any(TimeUnit.class))).thenReturn(false);
-        client = new AgentProxyClient(rmi, 0, binPath, latch, procCreator);
-        
-        try {
-            client.createProxy();
-            fail("Expected RemoteException");
-        } catch (RemoteException e) {
-            // Verify listener exported and bound
-            verify(rmi).export(client);
-            verify(registry).rebind(AgentProxyListener.REMOTE_PREFIX + "0", listenerStub);
-            
-            // Verify server created
-            String progName = "/path/to/thermostat/bin" + File.separator + "thermostat-agent-proxy";
-            verify(procCreator).createAndRunProcess(new String[] { progName, "0" });
-            
-            // Verify listener removed
-            verify(registry).unbind(AgentProxyListener.REMOTE_PREFIX + "0");
-            verify(rmi).unexport(client);
+            try {
+                client.getJMXServiceURL();
+                fail("Expected exception");
+            } catch (IOException e) {
+                // Expected
+            }
+            assertEquals(3, logMessages.size());
+            assertEquals("This is an error", logMessages.get(0).getMessage());
+            assertEquals("This is also an error", logMessages.get(1).getMessage());
+            assertEquals("Oh no!", logMessages.get(2).getMessage());
+        } finally {
+            LoggingUtils.getLogger(AgentProxyClient.class).removeHandler(logHandler);
         }
     }
     
-    @Test
-    public void testAttach() throws Exception {
-        createClient();
+    private static class TestLogHandler extends Handler {
         
-        client.attach();
-        verify(proxyControl).attach();
-    }
-    
-    @Test
-    public void testIsAttached() throws Exception {
-        createClient();
-        when(proxyControl.isAttached()).thenReturn(true);
+        private List<LogRecord> logMessages;
+        public TestLogHandler(List<LogRecord> logMessages) {
+            this.logMessages = logMessages;
+        }
+        
+        @Override
+        public void publish(LogRecord record) {
+            logMessages.add(record);
+        }
         
-        boolean result = client.isAttached();
-        verify(proxyControl).isAttached();
-        assertTrue(result);
+        @Override
+        public void flush() {
+            // Do nothing
+        }
+        
+        @Override
+        public void close() throws SecurityException {
+            // Do nothing
+        }
     }
-    
-    @Test
-    public void testDetach() throws Exception {
-        createClient();
-        
-        client.detach();
-        verify(proxyControl).detach();
-    }
-    
+
 }
 
--- a/agent/core/src/test/java/com/redhat/thermostat/utils/management/internal/MXBeanConnectionPoolImplTest.java	Thu Aug 21 15:21:57 2014 -0400
+++ b/agent/core/src/test/java/com/redhat/thermostat/utils/management/internal/MXBeanConnectionPoolImplTest.java	Tue Dec 16 11:54:58 2014 -0700
@@ -50,9 +50,9 @@
 
 import org.junit.Test;
 
-import com.redhat.thermostat.agent.internal.RMIRegistryImpl;
 import com.redhat.thermostat.agent.utils.management.MXBeanConnection;
 import com.redhat.thermostat.utils.management.internal.MXBeanConnectionPoolImpl.ConnectorCreator;
+import com.redhat.thermostat.utils.management.internal.ProcessUserInfoBuilder.ProcessUserInfo;
 
 public class MXBeanConnectionPoolImplTest {
 
@@ -64,20 +64,20 @@
         MXBeanConnector connector = mock(MXBeanConnector.class);
         ConnectorCreator creator = mock(ConnectorCreator.class);
 
-        when(creator.create(any(RMIRegistryImpl.class), anyInt(), any(File.class))).thenReturn(connector);
+        when(creator.create(anyInt(), any(String.class), any(File.class))).thenReturn(connector);
         when(connector.connect()).thenReturn(toReturn);
 
-        RMIRegistryImpl registry = mock(RMIRegistryImpl.class);
-        MXBeanConnectionPoolImpl pool = new MXBeanConnectionPoolImpl(creator, registry, binDir);
+        ProcessUserInfoBuilder builder = mock(ProcessUserInfoBuilder.class);
+        ProcessUserInfo info = new ProcessUserInfo(0, "Test");
+        when(builder.build(0)).thenReturn(info);
+        MXBeanConnectionPoolImpl pool = new MXBeanConnectionPoolImpl(creator, binDir, builder);
 
         MXBeanConnection connection = pool.acquire(0);
 
         assertNotNull(connection);
         assertEquals(connection, toReturn);
 
-        verify(connector).attach();
         verify(connector).connect();
-        verify(connector).close();
     }
 
     @Test
@@ -86,17 +86,17 @@
         MXBeanConnector connector = mock(MXBeanConnector.class);
         ConnectorCreator creator = mock(ConnectorCreator.class);
 
-        when(creator.create(any(RMIRegistryImpl.class), anyInt(), any(File.class))).thenReturn(connector);
+        when(creator.create(anyInt(), any(String.class), any(File.class))).thenReturn(connector);
         when(connector.connect()).thenReturn(toReturn);
 
-        RMIRegistryImpl registry = mock(RMIRegistryImpl.class);
-        MXBeanConnectionPoolImpl pool = new MXBeanConnectionPoolImpl(creator, registry, binDir);
+        ProcessUserInfoBuilder builder = mock(ProcessUserInfoBuilder.class);
+        ProcessUserInfo info = new ProcessUserInfo(0, "Test");
+        when(builder.build(0)).thenReturn(info);
+        MXBeanConnectionPoolImpl pool = new MXBeanConnectionPoolImpl(creator, binDir, builder);
 
         MXBeanConnection connection1 = pool.acquire(0);
 
-        verify(connector).attach();
         verify(connector).connect();
-        verify(connector).close();
 
         MXBeanConnection connection2 = pool.acquire(0);
 
@@ -112,11 +112,13 @@
         MXBeanConnector connector = mock(MXBeanConnector.class);
         ConnectorCreator creator = mock(ConnectorCreator.class);
 
-        when(creator.create(any(RMIRegistryImpl.class), anyInt(), any(File.class))).thenReturn(connector);
+        when(creator.create(anyInt(), any(String.class), any(File.class))).thenReturn(connector);
         when(connector.connect()).thenReturn(actualConnection);
 
-        RMIRegistryImpl registry = mock(RMIRegistryImpl.class);
-        MXBeanConnectionPoolImpl pool = new MXBeanConnectionPoolImpl(creator, registry, binDir);
+        ProcessUserInfoBuilder builder = mock(ProcessUserInfoBuilder.class);
+        ProcessUserInfo info = new ProcessUserInfo(0, "Test");
+        when(builder.build(0)).thenReturn(info);
+        MXBeanConnectionPoolImpl pool = new MXBeanConnectionPoolImpl(creator, binDir, builder);
 
         MXBeanConnection connection = pool.acquire(0);
 
@@ -133,11 +135,13 @@
         MXBeanConnector connector = mock(MXBeanConnector.class);
         ConnectorCreator creator = mock(ConnectorCreator.class);
 
-        when(creator.create(any(RMIRegistryImpl.class), anyInt(), any(File.class))).thenReturn(connector);
+        when(creator.create(anyInt(), any(String.class), any(File.class))).thenReturn(connector);
         when(connector.connect()).thenReturn(actualConnection);
 
-        RMIRegistryImpl registry = mock(RMIRegistryImpl.class);
-        MXBeanConnectionPoolImpl pool = new MXBeanConnectionPoolImpl(creator, registry, binDir);
+        ProcessUserInfoBuilder builder = mock(ProcessUserInfoBuilder.class);
+        ProcessUserInfo info = new ProcessUserInfo(0, "Test");
+        when(builder.build(0)).thenReturn(info);
+        MXBeanConnectionPoolImpl pool = new MXBeanConnectionPoolImpl(creator, binDir, builder);
 
         // connection1 == connection1 == actualConnection
         MXBeanConnection connection1 = pool.acquire(0);
@@ -153,15 +157,5 @@
 
     }
     
-    @Test
-    public void testShutdown() throws Exception {
-        RMIRegistryImpl registry = mock(RMIRegistryImpl.class);
-        ConnectorCreator creator = mock(ConnectorCreator.class);
-        MXBeanConnectionPoolImpl pool = new MXBeanConnectionPoolImpl(creator, registry, binDir);
-        verify(registry).start();
-        
-        pool.shutdown();
-        verify(registry).stop();
-    }
 }
 
--- a/agent/core/src/test/java/com/redhat/thermostat/utils/management/internal/MXBeanConnectorTest.java	Thu Aug 21 15:21:57 2014 -0400
+++ b/agent/core/src/test/java/com/redhat/thermostat/utils/management/internal/MXBeanConnectorTest.java	Tue Dec 16 11:54:58 2014 -0700
@@ -37,7 +37,6 @@
 package com.redhat.thermostat.utils.management.internal;
 
 import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
@@ -53,6 +52,8 @@
 
 public class MXBeanConnectorTest {
     
+    private static final String JMX_URL = "service:jmx:rmi://myHost:1099/blah";
+    
     private MXBeanConnector connector;
     private JMXConnectionCreator jmxCreator;
     private AgentProxyClient client;
@@ -61,47 +62,24 @@
     public void setup() throws Exception {
         jmxCreator = mock(JMXConnectionCreator.class);
         client = mock(AgentProxyClient.class);
+        when(client.getJMXServiceURL()).thenReturn(JMX_URL);
         connector = new MXBeanConnector(client, jmxCreator);
     }
     
     @Test
     public void testInit() throws Exception {
-        // MXBeanConnector constructor calls createProxy
-        verify(client).createProxy();
-    }
-    
-    @Test
-    public void testAttach() throws Exception {
-        connector.attach();
-        verify(client).attach();
-    }
-    
-    @Test
-    public void testIsAttached() throws Exception {
-        when(client.isAttached()).thenReturn(true);
-        boolean result = connector.isAttached();
-        verify(client).isAttached();
-        assertTrue(result);
-    }
-    
-    @Test
-    public void testClose() throws Exception {
-        connector.close();
-        verify(client).detach();
+        // MXBeanConnector constructor calls getJMXServiceURL
+        verify(client).getJMXServiceURL();
     }
     
     @Test
     public void testConnect() throws Exception {
-        String jmxUrl = "service:jmx:rmi://myHost:1099/blah";
-        when(client.getConnectorAddress()).thenReturn(jmxUrl);
-        
         JMXConnector jmxConnector = mock(JMXConnector.class);
-        when(jmxCreator.create(new JMXServiceURL(jmxUrl))).thenReturn(jmxConnector);
+        when(jmxCreator.create(new JMXServiceURL(JMX_URL))).thenReturn(jmxConnector);
         MBeanServerConnection connection = mock(MBeanServerConnection.class);
         when(jmxConnector.getMBeanServerConnection()).thenReturn(connection);
         
         MXBeanConnectionImpl result = connector.connect();
-        verify(client).getConnectorAddress();
         assertEquals(connection, result.get());
     }
 
--- a/agent/proxy/pom.xml	Thu Aug 21 15:21:57 2014 -0400
+++ b/agent/proxy/pom.xml	Tue Dec 16 11:54:58 2014 -0700
@@ -51,7 +51,6 @@
   <name>Thermostat Agent Proxy</name>
 
   <modules>
-    <module>common</module>
     <module>server</module>
   </modules>
 
--- a/agent/proxy/server/Makefile	Thu Aug 21 15:21:57 2014 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,41 +0,0 @@
-CC         = gcc
-JAVAH      = javah
-MYCFLAGS   = -c -Wall -fPIC
-MYLDFLAGS  = -fPIC -shared
-COPY       = cp -a
-
-CLASSPATH  = target/classes
-TARGET_DIR = target
-
-INCLUDE    = -I $(TARGET_DIR) -I $(JAVA_HOME)/include/ -I $(JAVA_HOME)/include/linux
-SOURCES    = src/main/native/AgentProxy.c
-TARGET     = $(TARGET_DIR)/AgentProxy.c
-OBJECTS    = $(TARGET:.c=.o)
-
-EXECUTABLE = libAgentProxy.so
-
-.PHONY:
-JNI_LIST = com.redhat.thermostat.agent.proxy.server.AgentProxyNativeUtils
-
-$(JNI_LIST):
-	$(JAVAH) -force -classpath $(CLASSPATH) -d $(TARGET_DIR) $(JNI_LIST)
-
-all: $(JNI_LIST) init $(SOURCES) $(EXECUTABLE)
-
-.PHONY:
-init:
-	$(COPY) $(SOURCES) $(TARGET)
-
-$(EXECUTABLE): $(OBJECTS)
-	$(CC) $(OBJECTS) -o $(TARGET_DIR)/$@ $(MYLDFLAGS) $(LDFLAGS)
-	
-.c.o:
-	$(CC) $(MYCFLAGS) $(CFLAGS) $(INCLUDE) $< -o $@
-
-clean-lib:
-	rm -f $(TARGET_DIR)/$(EXECUTABLE)
-	
-clean-obj:
-	rm -f $(OBJECTS) $(TARGET)
-	
-clean: clean-obj clean-lib
--- a/agent/proxy/server/pom.xml	Thu Aug 21 15:21:57 2014 -0400
+++ b/agent/proxy/server/pom.xml	Tue Dec 16 11:54:58 2014 -0700
@@ -49,33 +49,6 @@
   <name>Thermostat Agent Proxy Server</name>
 
   <build>
-    <plugins>
-      <plugin>
-        <groupId>org.codehaus.mojo</groupId>
-        <artifactId>exec-maven-plugin</artifactId>
-        <version>1.2.1</version>
-        <executions>  
-          <execution>
-            <phase>compile</phase>
-            <goals>
-              <goal>exec</goal>
-            </goals>
-          </execution>  
-        </executions>
-        <configuration>
-          <executable>make</executable>
-          <arguments>
-            <argument>all</argument>
-          </arguments>
-          <systemProperties>
-            <systemProperty>
-              <key>JAVA_HOME</key>
-              <value>${java.home}</value>
-            </systemProperty>
-          </systemProperties>
-        </configuration>
-      </plugin>
-    </plugins>
     <pluginManagement>
       <plugins>
         <!--This plugin's configuration is used to store Eclipse m2e settings only. It has no influence on the Maven build itself.-->
@@ -110,11 +83,6 @@
   <dependencies>
     <dependency>
       <groupId>com.redhat.thermostat</groupId>
-      <artifactId>thermostat-agent-proxy-common</artifactId>
-      <version>${project.version}</version>
-    </dependency>
-    <dependency>
-      <groupId>com.redhat.thermostat</groupId>
       <artifactId>thermostat-common-core</artifactId>
       <version>${project.version}</version>
     </dependency>
--- a/agent/proxy/server/src/main/java/com/redhat/thermostat/agent/proxy/server/AgentProxy.java	Thu Aug 21 15:21:57 2014 -0400
+++ b/agent/proxy/server/src/main/java/com/redhat/thermostat/agent/proxy/server/AgentProxy.java	Tue Dec 16 11:54:58 2014 -0700
@@ -37,50 +37,21 @@
 package com.redhat.thermostat.agent.proxy.server;
 
 import java.io.IOException;
-import java.rmi.NotBoundException;
-import java.rmi.RemoteException;
-import java.rmi.registry.Registry;
-import java.util.Timer;
-import java.util.TimerTask;
+import java.io.PrintStream;
 import java.util.logging.Level;
 import java.util.logging.Logger;
 
-import com.redhat.thermostat.agent.proxy.common.AgentProxyListener;
-import com.redhat.thermostat.agent.proxy.common.AgentProxyLogin;
 import com.redhat.thermostat.common.utils.LoggingUtils;
+import com.sun.tools.attach.AttachNotSupportedException;
 
 public class AgentProxy {
     
     private static final Logger logger = LoggingUtils.getLogger(AgentProxy.class);
-    private static final long TIMEOUT_MS = 300000L; // 5 minutes should be more than enough
-    private static final ShutdownListener shutdownListener = new ShutdownListener() {
-        @Override
-        public void shutdown() throws RemoteException {
-            shutdownProxy();
-        }
-    };
-    private static final TimerTask timeoutTask = new TimerTask() {
-        @Override
-        public void run() {
-            try {
-                shutdownProxy();
-                logger.warning("Server timed out");
-            } catch (RemoteException e) {
-                logger.log(Level.SEVERE, "Exception while shutting down "
-                        + "timed out server" , e);
-            }
-        }
-    };
-
-    private static String name = null;
+    
     private static int pid = -1;
-    private static Registry registry = null;
-    private static boolean bound = false;
-    private static AgentProxyLogin agent = null;
-    private static RegistryUtils registryUtils = new RegistryUtils();
-    private static AgentProxyNativeUtils nativeUtils = new AgentProxyNativeUtils();
-    private static ProcessUserInfoBuilder builder = new ProcessUserInfoBuilder(new ProcDataSource());
-    private static Timer timeoutTimer = new Timer(true);
+    private static AgentProxyControlImpl agent = null;
+    private static ControlCreator creator = new ControlCreator();
+    private static PrintStream outStream = System.out;
     
     public static void main(String[] args) {
         if (args.length < 1) {
@@ -94,87 +65,27 @@
             usage();
         }
         
-        // Schedule a timeout
-        timeoutTimer.schedule(timeoutTask, TIMEOUT_MS);
+        // Start proxy agent
+        agent = creator.create(pid);
         
-        // Load the native library
-        nativeUtils.loadLibrary();
-
-        // Look for registered status listener
-        AgentProxyListener listener;
         try {
-            String listenerName = AgentProxyListener.REMOTE_PREFIX + String.valueOf(pid);
-            registry = registryUtils.getRegistry();
-            listener = (AgentProxyListener) registry.lookup(listenerName);
-        } catch (RemoteException e) {
-            throw new RuntimeException("Failed to locate registry", e);
-        } catch (NotBoundException e) {
-            throw new RuntimeException("No listener registered", e);
-        }
-
-        // Start proxy agent
-        Exception ex = null;
-        try {
-            setupProxy(pid);
-        } catch (Exception e) {
-            logger.log(Level.SEVERE, "Failed to setup agent proxy for " + pid, e);
-            ex = e;
+            agent.attach();
+        } catch (AttachNotSupportedException | IOException e) {
+            logger.log(Level.SEVERE, "Failed to attach to VM (pid: " + pid + ")", e);
+            return;
         }
         
-        // Notify listener of result
-        try {
-            if (ex == null) {
-                // Success
-                listener.serverStarted();
-            }
-            else {
-                // Send exception to client
-                listener.serverFailedToStart(ex);
-            }
-        } catch (RemoteException e) {
-            throw new RuntimeException("Failed to notify listener", e);
-        }
-    }
-
-    private static void setupProxy(int pid) throws Exception {
         try {
-            UnixCredentials creds;
-            try {
-                creds = builder.build(pid);
-            } catch (IOException e) {
-                throw new Exception("Failed to read credentials", e);
-            }
-            
-            try {
-                // Set UID/GID to owner of target VM
-                nativeUtils.setCredentials(creds.getUid(), creds.getGid());
-            } catch (Exception e) {
-                throw new Exception("Failed to set credentials to " + creds.getUid() 
-                        + ":" + creds.getGid() , e);
-            }
-
-            agent = new AgentProxyLoginImpl(creds, pid, shutdownListener);
-            name = AgentProxyLogin.REMOTE_PREFIX + String.valueOf(pid);
-            AgentProxyLogin stub = (AgentProxyLogin) registryUtils.exportObject(agent);
-            registry.rebind(name, stub);
-            bound = true;
-            logger.info(name + " bound to RMI registry");
-        } catch (RemoteException e) {
-            throw new Exception("Failed to create remote object", e);
+            String connectorAddress = agent.getConnectorAddress();
+            outStream.println(connectorAddress);
+        } catch (IOException e) {
+            logger.log(Level.SEVERE, "Failed to retrieve JMX connection URL", e);
         }
-    }
-    
-    private static void shutdownProxy() throws RemoteException {
-        // Unbind from RMI registry
-        if (bound) {
-            try {
-                registry.unbind(name);
-                registryUtils.unexportObject(agent);
-                logger.info(name + " unbound from RMI registry");
-                bound = false;
-            } catch (NotBoundException e) {
-                throw new RemoteException("Object not bound", e);
-            }
+        
+        try {
+            agent.detach();
+        } catch (IOException e) {
+            logger.log(Level.WARNING, "Failed to detach from VM (pid: " + pid + ")", e); 
         }
     }
 
@@ -182,53 +93,25 @@
         throw new RuntimeException("usage: java " + AgentProxy.class.getName() + " <pidOfTargetJvm>");
     }
     
-    /*
-     * For testing purposes only.
-     */
-    static AgentProxyLogin getAgentProxyLogin() {
-        return agent;
-    }
-    
-    /*
-     * For testing purposes only.
-     */
-    static ShutdownListener getShutdownListener() {
-        return shutdownListener;
+    static class ControlCreator {
+        AgentProxyControlImpl create(int pid) {
+            return new AgentProxyControlImpl(pid);
+        }
     }
     
     /*
      * For testing purposes only.
      */
-    static boolean isBound() {
-        return bound;
-    }
-
-    /*
-     * For testing purposes only.
-     */
-    static void setRegistryUtils(RegistryUtils registryUtils) {
-        AgentProxy.registryUtils = registryUtils;
+    static void setControlCreator(ControlCreator creator) {
+        AgentProxy.creator = creator;
     }
     
     /*
      * For testing purposes only.
      */
-    static void setNativeUtils(AgentProxyNativeUtils nativeUtils) {
-        AgentProxy.nativeUtils = nativeUtils;
+    static void setOutStream(PrintStream stream) {
+        AgentProxy.outStream = stream;
     }
     
-    /*
-     * For testing purposes only.
-     */
-    static void setProcessUserInfoBuilder(ProcessUserInfoBuilder builder) {
-        AgentProxy.builder = builder;
-    }
-    
-    /*
-     * For testing purposes only.
-     */
-    static void setTimeoutTimer(Timer timeoutTimer) {
-        AgentProxy.timeoutTimer = timeoutTimer;
-    }
 }
 
--- a/agent/proxy/server/src/main/java/com/redhat/thermostat/agent/proxy/server/AgentProxyControlImpl.java	Thu Aug 21 15:21:57 2014 -0400
+++ b/agent/proxy/server/src/main/java/com/redhat/thermostat/agent/proxy/server/AgentProxyControlImpl.java	Tue Dec 16 11:54:58 2014 -0700
@@ -40,18 +40,14 @@
 import java.io.IOException;
 import java.rmi.RemoteException;
 import java.util.Properties;
-import java.util.Set;
 import java.util.logging.Logger;
 
-import javax.security.auth.Subject;
-
+import com.redhat.thermostat.common.utils.LoggingUtils;
 import com.sun.tools.attach.AgentInitializationException;
 import com.sun.tools.attach.AgentLoadException;
 import com.sun.tools.attach.AttachNotSupportedException;
 import com.sun.tools.attach.VirtualMachine;
 
-import com.redhat.thermostat.common.utils.LoggingUtils;
-
 class AgentProxyControlImpl {
     
     private static final Logger logger = LoggingUtils.getLogger(AgentProxyControlImpl.class);
@@ -74,65 +70,45 @@
         this.vmUtils = vmUtils;
     }
 
-    void attach(Subject user) throws RemoteException, SecurityException {
-        authCheck(user);
-        try {
-            vm = vmUtils.attach(String.valueOf(pid));
-            attached = true;
-            
-            Properties props = vm.getAgentProperties();
-            connectorAddress = props.getProperty(CONNECTOR_ADDRESS_PROPERTY);
-            if (connectorAddress == null) {
-                String home = null;
-                String agent = null;
-                try {
-                    props = vm.getSystemProperties();
-                    home = props.getProperty("java.home");
-                    agent = home + File.separator + "lib" + File.separator + "management-agent.jar";
-                    logger.fine("Loading '" + agent + "' into VM (pid: " + pid + ")");
-                    vm.loadAgent(agent);
+    void attach() throws AttachNotSupportedException, IOException {
+        vm = vmUtils.attach(String.valueOf(pid));
+        attached = true;
 
-                    props = vm.getAgentProperties();
-                    connectorAddress = props.getProperty(CONNECTOR_ADDRESS_PROPERTY);
-                } catch (IOException | AgentLoadException | AgentInitializationException e) {
-                    throw new RemoteException("Failed to load agent ('" + agent + "', from home '" + home + "') into VM (pid: " + pid + ")", e);
-                }
+        Properties props = vm.getAgentProperties();
+        connectorAddress = props.getProperty(CONNECTOR_ADDRESS_PROPERTY);
+        if (connectorAddress == null) {
+            String home = null;
+            String agent = null;
+            try {
+                props = vm.getSystemProperties();
+                home = props.getProperty("java.home");
+                agent = home + File.separator + "lib" + File.separator + "management-agent.jar";
+                logger.fine("Loading '" + agent + "' into VM (pid: " + pid + ")");
+                vm.loadAgent(agent);
+
+                props = vm.getAgentProperties();
+                connectorAddress = props.getProperty(CONNECTOR_ADDRESS_PROPERTY);
+            } catch (IOException | AgentLoadException | AgentInitializationException e) {
+                throw new RemoteException("Failed to load agent ('" + agent + "', from home '" + home + "') into VM (pid: " + pid + ")", e);
             }
-        } catch (AttachNotSupportedException | IOException e) {
-            throw new RemoteException("Failed to attach to VM (pid: " + pid + ")", e);
         }
     }
 
-    boolean isAttached(Subject user) throws RemoteException, SecurityException {
-        authCheck(user);
+    boolean isAttached() {
         return attached;
     }
 
-    String getConnectorAddress(Subject user) throws RemoteException, SecurityException {
-        authCheck(user);
+    String getConnectorAddress() throws IOException {
         if (!attached) {
-            throw new RemoteException("Agent not attached to target VM");
+            throw new IOException("Agent not attached to target VM");
         }
         return connectorAddress;
     }
 
-    void detach(Subject user) throws RemoteException, SecurityException {
-        authCheck(user);
-        try {
-            if (attached) {
-                vm.detach();
-                attached = false;
-            }
-        } catch (IOException e) {
-            throw new RemoteException("Failed to detach from VM", e);
-        }
-    }
-    
-    private void authCheck(Subject user) throws SecurityException {
-        // If we've added our Principal, we've authenticated this user
-        Set<AgentProxyPrincipal> principals = user.getPrincipals(AgentProxyPrincipal.class);
-        if (principals.isEmpty()) {
-            throw new SecurityException("Access Denied");
+    void detach() throws IOException {
+        if (attached) {
+            vm.detach();
+            attached = false;
         }
     }
     
--- a/agent/proxy/server/src/main/java/com/redhat/thermostat/agent/proxy/server/AgentProxyControlWrapper.java	Thu Aug 21 15:21:57 2014 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,98 +0,0 @@
-/*
- * Copyright 2012-2014 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are not obligated to do so.  If you do not wish
- * to do so, delete this exception statement from your version.
- */
-
-package com.redhat.thermostat.agent.proxy.server;
-
-import java.rmi.RemoteException;
-
-import javax.security.auth.Subject;
-import javax.security.auth.login.LoginException;
-
-import com.redhat.thermostat.agent.proxy.common.AgentProxyControl;
-
-class AgentProxyControlWrapper implements AgentProxyControl {
-    
-    private final Subject user;
-    private final AgentProxyLoginContext context;
-    private final AgentProxyControlImpl impl;
-    private final ShutdownListener listener;
-    private final RegistryUtils registryUtils;
-    
-    AgentProxyControlWrapper(Subject user, AgentProxyLoginContext context, AgentProxyControlImpl impl, 
-            ShutdownListener listener, RegistryUtils registryUtils) {
-        this.user = user;
-        this.context = context;
-        this.impl = impl;
-        this.listener = listener;
-        this.registryUtils = registryUtils;
-    }
-
-    @Override
-    public void attach() throws RemoteException, SecurityException {
-        impl.attach(user);
-    }
-
-    @Override
-    public boolean isAttached() throws RemoteException, SecurityException {
-        return impl.isAttached(user);
-    }
-
-    @Override
-    public String getConnectorAddress() throws RemoteException, SecurityException {
-        return impl.getConnectorAddress(user);
-    }
-
-    @Override
-    public void detach() throws RemoteException, SecurityException {
-        try {
-            impl.detach(user);
-        } finally {
-            try {
-                // Removes all Principals
-                context.logout();
-            } catch (LoginException e) {
-                throw new RemoteException("Failed to log out", e);
-            }
-            // Unexport this object
-            registryUtils.unexportObject(this);
-            
-            // Shutdown RMI server
-            listener.shutdown();
-        }
-    }
-
-}
-
--- a/agent/proxy/server/src/main/java/com/redhat/thermostat/agent/proxy/server/AgentProxyLoginContext.java	Thu Aug 21 15:21:57 2014 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,102 +0,0 @@
-/*
- * Copyright 2012-2014 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are not obligated to do so.  If you do not wish
- * to do so, delete this exception statement from your version.
- */
-
-package com.redhat.thermostat.agent.proxy.server;
-
-import java.io.IOException;
-
-import javax.security.auth.Subject;
-import javax.security.auth.callback.Callback;
-import javax.security.auth.callback.CallbackHandler;
-import javax.security.auth.callback.UnsupportedCallbackException;
-import javax.security.auth.login.LoginContext;
-import javax.security.auth.login.LoginException;
-
-import com.redhat.thermostat.agent.proxy.server.AgentProxyLoginModule.AgentProxyCallback;
-
-/*
- * Wraps both of our LoginModules.
- */
-class AgentProxyLoginContext {
-    
-    private static final String UNIX_LOGIN_MODULE = "UnixLogin";
-    private static final String AGENT_PROXY_LOGIN_MODULE = "AgentProxyLogin";
-    
-    private final LoginContext unixContext;
-    private final LoginContext context;
-    
-    AgentProxyLoginContext(Subject user, UnixCredentials creds) throws LoginException {
-        this(user, creds, new ContextCreator());
-    }
-    
-    AgentProxyLoginContext(Subject user, final UnixCredentials creds, ContextCreator creator) throws LoginException {
-        unixContext = creator.createContext(UNIX_LOGIN_MODULE, user);
-        context = creator.createContext(AGENT_PROXY_LOGIN_MODULE, user, new CallbackHandler() {
-            
-            @Override
-            public void handle(Callback[] callbacks) throws IOException,
-                    UnsupportedCallbackException {
-                for (Callback callback : callbacks) {
-                    if (callback instanceof AgentProxyCallback) {
-                        ((AgentProxyCallback) callback).setTargetCredentials(creds);
-                    }
-                }
-            }
-        });
-    }
-    
-    void login() throws LoginException {
-        unixContext.login();
-        context.login();
-    }
-    
-    void logout() throws LoginException {
-        context.logout();
-        unixContext.logout();
-    }
-    
-    static class ContextCreator {
-        LoginContext createContext(String name, Subject subject) throws LoginException {
-            return new LoginContext(name, subject);
-        }
-        
-        LoginContext createContext(String name, Subject subject, CallbackHandler handler) throws LoginException {
-            return new LoginContext(name, subject, handler);
-        }
-    }
-
-}
-
--- a/agent/proxy/server/src/main/java/com/redhat/thermostat/agent/proxy/server/AgentProxyLoginImpl.java	Thu Aug 21 15:21:57 2014 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,91 +0,0 @@
-/*
- * Copyright 2012-2014 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are not obligated to do so.  If you do not wish
- * to do so, delete this exception statement from your version.
- */
-
-package com.redhat.thermostat.agent.proxy.server;
-
-import java.rmi.RemoteException;
-
-import javax.security.auth.Subject;
-import javax.security.auth.login.LoginException;
-
-import com.redhat.thermostat.agent.proxy.common.AgentProxyControl;
-import com.redhat.thermostat.agent.proxy.common.AgentProxyLogin;
-
-class AgentProxyLoginImpl implements AgentProxyLogin {
-    
-    private final UnixCredentials creds;
-    private final AgentProxyControlImpl impl;
-    private final ShutdownListener listener;
-    private final LoginContextCreator contextCreator;
-    private final RegistryUtils registryUtils;
-    
-    AgentProxyLoginImpl(UnixCredentials creds, int pid, ShutdownListener listener) throws RemoteException {
-        this(creds, pid, listener, new LoginContextCreator(), new RegistryUtils());
-    }
-    
-    AgentProxyLoginImpl(UnixCredentials creds, int pid, ShutdownListener listener, 
-            LoginContextCreator contextCreator, RegistryUtils registryUtils) throws RemoteException {
-        this.creds = creds;
-        this.impl = new AgentProxyControlImpl(pid);
-        this.listener = listener;
-        this.contextCreator = contextCreator;
-        this.registryUtils = registryUtils;
-    }
-
-    @Override
-    public AgentProxyControl login() throws RemoteException, SecurityException {
-        Subject user = new Subject();
-        try {
-            AgentProxyLoginContext context = contextCreator.createContext(user, creds);
-            context.login();
-            
-            AgentProxyControl control = new AgentProxyControlWrapper(user, context, impl, 
-                    listener, registryUtils);
-            AgentProxyControl stub = (AgentProxyControl) registryUtils.exportObject(control);
-            return stub;
-        } catch (LoginException e) {
-            throw new RemoteException("Failed to login", e);
-        }
-    }
-    
-    static class LoginContextCreator {
-        AgentProxyLoginContext createContext(Subject user, UnixCredentials creds) throws LoginException {
-            return new AgentProxyLoginContext(user, creds);
-        }
-    }
-    
-}
-
--- a/agent/proxy/server/src/main/java/com/redhat/thermostat/agent/proxy/server/AgentProxyLoginModule.java	Thu Aug 21 15:21:57 2014 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,240 +0,0 @@
-/*
- * Copyright 2012-2014 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are not obligated to do so.  If you do not wish
- * to do so, delete this exception statement from your version.
- */
-
-package com.redhat.thermostat.agent.proxy.server;
-
-import java.io.IOException;
-import java.util.Map;
-import java.util.Set;
-import java.util.concurrent.CountDownLatch;
-
-import javax.security.auth.Subject;
-import javax.security.auth.callback.Callback;
-import javax.security.auth.callback.CallbackHandler;
-import javax.security.auth.callback.UnsupportedCallbackException;
-import javax.security.auth.login.LoginException;
-import javax.security.auth.spi.LoginModule;
-
-public class AgentProxyLoginModule implements LoginModule {
-    
-    private Subject subject;
-    private CallbackHandler callbackHandler;
-    private AgentProxyPrincipal principal;
-    private boolean loggedIn;
-    private boolean committed;
-    private boolean debug;
-    
-    interface AgentProxyCallback extends Callback {
-        
-        void setTargetCredentials(UnixCredentials creds);
-        
-    }
-
-    @Override
-    public void initialize(Subject subject, CallbackHandler callbackHandler,
-            Map<String, ?> sharedState, Map<String, ?> options) {
-        this.subject = subject;
-        this.callbackHandler = callbackHandler;
-        
-        // Check for debug option
-        debug = "true".equalsIgnoreCase((String) options.get("debug"));
-    }
-
-    @Override
-    public boolean login() throws LoginException {
-        loggedIn = false;
-        
-        // Get credentials of target process from callback
-        UnixCredentials creds = getTargetCredentials();
-
-        // Verify subject's credentials match those of target process
-        checkCredentials(creds);
-
-        // Add a custom principal to the subject to show we've authenticated
-        principal = createPrincipal();
-        if (debug) {
-            System.out.println("\t\t[AgentProxyLoginModule]: " +
-                    "created principal for user: " + principal.getName());
-        }
-        
-        loggedIn = true;
-        return true;
-    }
-    
-    private UnixCredentials getTargetCredentials() throws LoginException {
-        final CountDownLatch latch = new CountDownLatch(1);
-        final UnixCredentials[] credsContainer = new UnixCredentials[1];
-        
-        try {
-            callbackHandler.handle(new Callback[] { new AgentProxyCallback() {
-
-                @Override
-                public void setTargetCredentials(UnixCredentials creds) {
-                    credsContainer[0] = creds;
-                    latch.countDown();
-                }
-
-            }});
-
-            latch.await();
-            
-            return credsContainer[0];
-        } catch (IOException e) {
-            throw new LoginException(e.getMessage());
-        } catch (UnsupportedCallbackException e) {
-            throw new LoginException(e.getMessage());
-        } catch (InterruptedException e) {
-            throw new LoginException("Interrupted");
-        }
-    }
-
-    @Override
-    public boolean commit() throws LoginException {
-        committed = false;
-        
-        if (loggedIn) {
-            subject.getPrincipals().add(principal);
-            if (debug) {
-                System.out.println("\t\t[AgentProxyLoginModule]: " +
-                        "adding AgentProxyPrincipal to Subject");
-            }
-            committed = true;
-        }
-        return committed;
-    }
-
-    @Override
-    public boolean abort() throws LoginException {
-        if (debug) {
-            System.out.println("\t\t[AgentProxyLoginModule]: " +
-                    "aborted authentication attempt");
-        }
-        if (!loggedIn) {
-            return false;
-        }
-        else if (loggedIn && !committed) {
-            // Clean up state
-            loggedIn = false;
-            principal = null;
-        }
-        else {
-            // Clean up state & remove principal
-            logout();
-        }
-        
-        return true;
-    }
-
-    @Override
-    public boolean logout() throws LoginException {
-        // Remove principal
-        subject.getPrincipals().remove(principal);
-        if (debug) {
-            System.out.println("\t\t[AgentProxyLoginModule]: " +
-                    "removed principal for user: " + principal.getName());
-        }
-        
-        // Clean up state
-        loggedIn = false;
-        committed = false;
-        principal = null;
-        
-        return true;
-    }
-    
-    @SuppressWarnings("restriction")
-    private void checkCredentials(UnixCredentials creds) throws LoginException {
-        boolean uidOkay = false, gidOkay = false;
-        
-        // Check UID
-        Set<com.sun.security.auth.UnixNumericUserPrincipal> userPrincipals = subject.getPrincipals(com.sun.security.auth.UnixNumericUserPrincipal.class);
-        if (!userPrincipals.isEmpty()) {
-            com.sun.security.auth.UnixNumericUserPrincipal userPrincipal = userPrincipals.iterator().next();
-            if (debug) {
-                System.out.println("UnixLoginModule UID: " + userPrincipal.longValue() + ", PID: " + creds.getPid() + ", Owner: " + creds.getUid());
-            }
-            if (userPrincipal.longValue() == creds.getUid() || userPrincipal.longValue() == 0) {
-                uidOkay = true;
-            }
-        }
-        
-        // Check GID
-        Set<com.sun.security.auth.UnixNumericGroupPrincipal> groupPrincipals = subject.getPrincipals(com.sun.security.auth.UnixNumericGroupPrincipal.class);
-        for (com.sun.security.auth.UnixNumericGroupPrincipal groupPrincipal : groupPrincipals) {
-            if (groupPrincipal.longValue() == creds.getGid() || groupPrincipal.longValue() == 0) {
-                gidOkay = true;
-            }
-        }
-        
-        if (!uidOkay || !gidOkay) {
-            throw new LoginException("Access Denied");
-        }
-    }
-    
-    @SuppressWarnings("restriction")
-    private AgentProxyPrincipal createPrincipal() throws LoginException {
-        Set<com.sun.security.auth.UnixPrincipal> userPrincipals = subject.getPrincipals(com.sun.security.auth.UnixPrincipal.class);
-        if (userPrincipals.isEmpty()) {
-            throw new LoginException("Unable to obtain user ID");
-        }
-        
-        com.sun.security.auth.UnixPrincipal userPrincipal = userPrincipals.iterator().next();
-        return new AgentProxyPrincipal(userPrincipal.getName());
-    }
-    
-    /*
-     * For testing purposes only.
-     */
-    AgentProxyPrincipal getPrincipal() {
-        return principal;
-    }
-    
-    /*
-     * For testing purposes only.
-     */
-    boolean isLoggedIn() {
-        return loggedIn;
-    }
-    
-    /*
-     * For testing purposes only.
-     */
-    boolean isCommitted() {
-        return committed;
-    }
-    
-}
-
--- a/agent/proxy/server/src/main/java/com/redhat/thermostat/agent/proxy/server/AgentProxyNativeUtils.java	Thu Aug 21 15:21:57 2014 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,54 +0,0 @@
-/*
- * Copyright 2012-2014 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are not obligated to do so.  If you do not wish
- * to do so, delete this exception statement from your version.
- */
-
-package com.redhat.thermostat.agent.proxy.server;
-
-import com.redhat.thermostat.shared.config.NativeLibraryResolver;
-import com.redhat.thermostat.shared.config.internal.CommonPathsImpl;
-
-class AgentProxyNativeUtils {
-    
-    void loadLibrary() {
-        // TODO if this used OSGi, then we wouldn't need this line
-        NativeLibraryResolver.setCommonPaths(new CommonPathsImpl());
-        String libPath = NativeLibraryResolver.getAbsoluteLibraryPath("AgentProxy");
-        System.load(libPath);
-    }
-    
-    native void setCredentials(long uid, long gid) throws Exception;
-
-}
-
--- a/agent/proxy/server/src/main/java/com/redhat/thermostat/agent/proxy/server/AgentProxyPrincipal.java	Thu Aug 21 15:21:57 2014 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,55 +0,0 @@
-/*
- * Copyright 2012-2014 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are not obligated to do so.  If you do not wish
- * to do so, delete this exception statement from your version.
- */
-
-package com.redhat.thermostat.agent.proxy.server;
-
-import java.security.Principal;
-
-class AgentProxyPrincipal implements Principal {
-    
-    private final String name;
-    
-    AgentProxyPrincipal(String name) {
-        this.name = name;
-    }
-
-    @Override
-    public String getName() {
-        return name;
-    }
-
-}
-
--- a/agent/proxy/server/src/main/java/com/redhat/thermostat/agent/proxy/server/ProcDataSource.java	Thu Aug 21 15:21:57 2014 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,62 +0,0 @@
-/*
- * Copyright 2012-2014 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are not obligated to do so.  If you do not wish
- * to do so, delete this exception statement from your version.
- */
-
-package com.redhat.thermostat.agent.proxy.server;
-
-import java.io.FileReader;
-import java.io.IOException;
-import java.io.Reader;
-
-/**
- * Wrapper for files under /proc. See proc(5) for details about this.
- */
-class ProcDataSource {
-
-    private static final String PID_STATUS_FILE = "/proc/${pid}/status";
-
-    /**
-     * Returns a reader for /proc/$PID/status
-     */
-    Reader getStatusReader(int pid) throws IOException {
-        return new FileReader(getPidFile(PID_STATUS_FILE, pid));
-    }
-
-    private String getPidFile(String fileName, int pid) {
-        return fileName.replace("${pid}", Integer.toString(pid));
-    }
-
-}
-
--- a/agent/proxy/server/src/main/java/com/redhat/thermostat/agent/proxy/server/ProcessUserInfoBuilder.java	Thu Aug 21 15:21:57 2014 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,106 +0,0 @@
-/*
- * Copyright 2012-2014 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are not obligated to do so.  If you do not wish
- * to do so, delete this exception statement from your version.
- */
-
-package com.redhat.thermostat.agent.proxy.server;
-
-import java.io.BufferedReader;
-import java.io.IOException;
-import java.io.Reader;
-
-class ProcessUserInfoBuilder {
-    
-    private static final String PROC_STATUS_UID = "Uid:";
-    private static final String PROC_STATUS_GID = "Gid:";
-    
-    private final ProcDataSource source;
-    
-    ProcessUserInfoBuilder(ProcDataSource source) {
-        this.source = source;
-    }
-    
-    UnixCredentials build(int pid) throws IOException {
-        Reader reader = source.getStatusReader(pid);
-        UnixCredentials creds = getUidGidFromProcfs(new BufferedReader(reader), pid);
-        return creds;
-    }
-
-    /*
-     * Look for the following lines:
-     * Uid:  <RealUid>   <EffectiveUid>   <SavedUid>   <FSUid>
-     * Gid:  <RealGid>   <EffectiveGid>   <SavedGid>   <FSGid>
-     */
-    private UnixCredentials getUidGidFromProcfs(BufferedReader br, int pid) throws IOException {
-        long uid = -1;
-        long gid = -1;
-        String line;
-        while ((line = br.readLine()) != null) {
-            line = line.trim();
-            if (line.startsWith(PROC_STATUS_UID)) {
-                uid = parseUidGid(line);
-            }
-            else if (line.startsWith(PROC_STATUS_GID)) {
-                gid = parseUidGid(line);
-            }
-        }
-        if (uid < 0) {
-            throw new IOException("Unable to determine UID from /proc/${pid}/status");
-        }
-        if (gid < 0) {
-            throw new IOException("Unable to determine GID from /proc/${pid}/status");
-        }
-        
-        return new UnixCredentials(uid, gid, pid);
-    }
-
-    private long parseUidGid(String line) throws IOException {
-        long result = -1;
-        String[] parts = line.split("\\s+");
-        if (parts.length == 5) {
-            try {
-                // Use Effective UID/GID
-                result = Long.parseLong(parts[2]);
-            } catch (NumberFormatException e) {
-                throw new IOException("Unexpected output from ps command", e);
-            }
-        }
-        else {
-            throw new IOException("Expected 5 parts from split /proc/${pid}/status output, got " + parts.length);
-        }
-        return result;
-    }
-    
-}
-
--- a/agent/proxy/server/src/main/java/com/redhat/thermostat/agent/proxy/server/RegistryUtils.java	Thu Aug 21 15:21:57 2014 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,26 +0,0 @@
-package com.redhat.thermostat.agent.proxy.server;
-
-import java.net.InetAddress;
-import java.rmi.NoSuchObjectException;
-import java.rmi.Remote;
-import java.rmi.RemoteException;
-import java.rmi.registry.LocateRegistry;
-import java.rmi.registry.Registry;
-import java.rmi.server.UnicastRemoteObject;
-
-class RegistryUtils {
-    
-    Registry getRegistry() throws RemoteException {
-        return LocateRegistry.getRegistry(InetAddress.getLoopbackAddress().getHostName());
-    }
-    
-    Remote exportObject(Remote obj) throws RemoteException {
-        // Single arg method exports stub instead of real object
-        return UnicastRemoteObject.exportObject(obj, 0);
-    }
-    
-    void unexportObject(Remote obj) throws NoSuchObjectException {
-        UnicastRemoteObject.unexportObject(obj, true);
-    }
-    
-}
\ No newline at end of file
--- a/agent/proxy/server/src/main/java/com/redhat/thermostat/agent/proxy/server/ShutdownListener.java	Thu Aug 21 15:21:57 2014 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,46 +0,0 @@
-/*
- * Copyright 2012-2014 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are not obligated to do so.  If you do not wish
- * to do so, delete this exception statement from your version.
- */
-
-package com.redhat.thermostat.agent.proxy.server;
-
-import java.rmi.RemoteException;
-
-interface ShutdownListener {
-    
-    void shutdown() throws RemoteException;
-
-}
-
--- a/agent/proxy/server/src/main/java/com/redhat/thermostat/agent/proxy/server/UnixCredentials.java	Thu Aug 21 15:21:57 2014 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,64 +0,0 @@
-/*
- * Copyright 2012-2014 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are not obligated to do so.  If you do not wish
- * to do so, delete this exception statement from your version.
- */
-
-package com.redhat.thermostat.agent.proxy.server;
-
-class UnixCredentials {
-    
-    private final long uid;
-    private final long gid;
-    private final int pid;
-
-    UnixCredentials(long uid, long gid, int pid) {
-        this.uid = uid;
-        this.gid = gid;
-        this.pid = pid;
-    }
-    
-    long getUid() {
-        return uid;
-    }
-    
-    long getGid() {
-        return gid;
-    }
-    
-    int getPid() {
-        return pid;
-    }
-    
-}
-
--- a/agent/proxy/server/src/main/native/AgentProxy.c	Thu Aug 21 15:21:57 2014 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,76 +0,0 @@
-/*
- * Copyright 2012-2014 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are not obligated to do so.  If you do not wish
- * to do so, delete this exception statement from your version.
- */
-
-#include "com_redhat_thermostat_agent_proxy_server_AgentProxyNativeUtils.h"
-
-#include <unistd.h>
-#include <string.h>
-#include <errno.h>
-
-static jint throw_Exception(JNIEnv *, const char *, const char *);
-
-JNIEXPORT void JNICALL 
-Java_com_redhat_thermostat_agent_proxy_server_AgentProxyNativeUtils_setCredentials(
-        JNIEnv *env, jclass splitAgentKlass, jlong uid, jlong gid) {
-    int rc;
-    char *err;
-
-    // Need to setegid before seteuid, or otherwise we've dropped permissions
-    // needed to do so.
-    rc = setegid(gid);
-    if (rc < 0) {
-        err = strerror(errno);
-        throw_Exception(env, "java/lang/Exception", err);
-    }
-
-    rc = seteuid(uid);
-    if (rc < 0) {
-        err = strerror(errno);
-        throw_Exception(env, "java/lang/Exception", err);
-    }
-}
-
-static jint throw_Exception(JNIEnv *env, const char *class_name,
-        const char *message) {
-    jclass class;
-
-    class = (*env)->FindClass(env, class_name);
-    if (class == NULL) {
-        return -1;
-    }
-    return (*env)->ThrowNew(env, class, message);
-}
-
--- a/agent/proxy/server/src/test/java/com/redhat/thermostat/agent/proxy/server/AgentProxyControlImplTest.java	Thu Aug 21 15:21:57 2014 -0400
+++ b/agent/proxy/server/src/test/java/com/redhat/thermostat/agent/proxy/server/AgentProxyControlImplTest.java	Tue Dec 16 11:54:58 2014 -0700
@@ -47,11 +47,9 @@
 import static org.mockito.Mockito.when;
 
 import java.io.File;
-import java.rmi.RemoteException;
+import java.io.IOException;
 import java.util.Properties;
 
-import javax.security.auth.Subject;
-
 import org.junit.Before;
 import org.junit.Test;
 
@@ -84,9 +82,7 @@
     
     @Test
     public void testAttach() throws Exception {
-        Subject subject = new Subject();
-        addPrincipal(subject);
-        control.attach(subject);
+        control.attach();
         
         verify(vmUtils).attach("0");
         verify(vm, times(2)).getAgentProperties();
@@ -94,80 +90,37 @@
         verify(vm).loadAgent("/path/to/java/home" + File.separator + "lib" + File.separator + "management-agent.jar");
     }
 
-    @Test(expected=SecurityException.class)
-    public void testAttachDenied() throws Exception {
-        Subject subject = new Subject();
-        control.attach(subject);
-    }
-    
     @Test
     public void testIsAttached() throws Exception {
-        Subject subject = new Subject();
-        addPrincipal(subject);
-        
-        assertFalse(control.isAttached(subject));
-        control.attach(subject);
-        assertTrue(control.isAttached(subject));
-    }
-    
-    @Test(expected=SecurityException.class)
-    public void testIsAttachedDenied() throws Exception {
-        Subject subject = new Subject();
-        control.isAttached(subject);
+        assertFalse(control.isAttached());
+        control.attach();
+        assertTrue(control.isAttached());
     }
     
     @Test
     public void testGetAddress() throws Exception {
-        Subject subject = new Subject();
-        addPrincipal(subject);
-        
-        control.attach(subject);
-        String addr = control.getConnectorAddress(subject);
+        control.attach();
+        String addr = control.getConnectorAddress();
         assertEquals("myJmxUrl", addr);
     }
     
-    @Test(expected=SecurityException.class)
-    public void testGetAddressDenied() throws Exception {
-        Subject subject = new Subject();
-        control.getConnectorAddress(subject);
-    }
-    
-    @Test(expected=RemoteException.class)
+    @Test(expected=IOException.class)
     public void testGetAddressNotAttached() throws Exception {
-        Subject subject = new Subject();
-        addPrincipal(subject);
-        
-        control.getConnectorAddress(subject);
+        control.getConnectorAddress();
     }
     
     @Test
     public void testDetach() throws Exception {
-        Subject subject = new Subject();
-        addPrincipal(subject);
-        
-        control.attach(subject);
-        control.detach(subject);
+        control.attach();
+        control.detach();
         verify(vm).detach();
     }
     
     @Test
     public void testDetachNotAttached() throws Exception {
-        Subject subject = new Subject();
-        addPrincipal(subject);
-        
-        control.detach(subject);
+        control.detach();
         verify(vm, never()).detach();
     }
     
-    @Test(expected=SecurityException.class)
-    public void testDetachDenied() throws Exception {
-        Subject subject = new Subject();
-        control.detach(subject);
-    }
-
-    private void addPrincipal(Subject subject) {
-        subject.getPrincipals().add(new AgentProxyPrincipal("TEST"));
-    }
-
 }
 
--- a/agent/proxy/server/src/test/java/com/redhat/thermostat/agent/proxy/server/AgentProxyControlWrapperTest.java	Thu Aug 21 15:21:57 2014 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,95 +0,0 @@
-/*
- * Copyright 2012-2014 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are not obligated to do so.  If you do not wish
- * to do so, delete this exception statement from your version.
- */
-
-package com.redhat.thermostat.agent.proxy.server;
-
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
-
-import javax.security.auth.Subject;
-
-import org.junit.Before;
-import org.junit.Test;
-
-public class AgentProxyControlWrapperTest {
-    
-    private AgentProxyControlWrapper control;
-    private AgentProxyControlImpl impl;
-    private Subject user;
-    private AgentProxyLoginContext context;
-    private ShutdownListener listener;
-    private RegistryUtils registryUtils;
-    
-    @Before
-    public void setup() throws Exception {
-        user = new Subject();
-        context = mock(AgentProxyLoginContext.class);
-        impl = mock(AgentProxyControlImpl.class);
-        listener = mock(ShutdownListener.class);
-        registryUtils = mock(RegistryUtils.class);
-        control = new AgentProxyControlWrapper(user, context, impl, listener, registryUtils);
-    }
-    
-    @Test
-    public void testAttach() throws Exception {
-        control.attach();
-        verify(impl).attach(user);
-    }
-    
-    @Test
-    public void testIsAttached() throws Exception {
-        control.isAttached();
-        verify(impl).isAttached(user);
-    }
-    
-    @Test
-    public void testGetAddress() throws Exception {
-        control.getConnectorAddress();
-        verify(impl).getConnectorAddress(user);
-    }
-    
-    @Test
-    public void testDetach() throws Exception {
-        control.detach();
-        
-        verify(impl).detach(user);
-        verify(context).logout();
-        verify(listener).shutdown();
-        verify(registryUtils).unexportObject(control);
-    }
-    
-}
-
--- a/agent/proxy/server/src/test/java/com/redhat/thermostat/agent/proxy/server/AgentProxyLoginContextTest.java	Thu Aug 21 15:21:57 2014 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,106 +0,0 @@
-/*
- * Copyright 2012-2014 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are not obligated to do so.  If you do not wish
- * to do so, delete this exception statement from your version.
- */
-
-package com.redhat.thermostat.agent.proxy.server;
-
-import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.eq;
-import static org.mockito.Matchers.same;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import javax.security.auth.Subject;
-import javax.security.auth.callback.Callback;
-import javax.security.auth.callback.CallbackHandler;
-import javax.security.auth.login.LoginContext;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.mockito.ArgumentCaptor;
-
-import com.redhat.thermostat.agent.proxy.server.AgentProxyLoginContext.ContextCreator;
-import com.redhat.thermostat.agent.proxy.server.AgentProxyLoginModule.AgentProxyCallback;
-
-public class AgentProxyLoginContextTest {
-    
-    private AgentProxyLoginContext context;
-    private ContextCreator creator;
-    private Subject user;
-    private UnixCredentials creds;
-    private LoginContext unixContext;
-    private LoginContext ourContext;
-
-    @Before
-    public void setup() throws Exception {
-        user = new Subject();
-        creds = new UnixCredentials(9000, 9001, 0);
-        creator = mock(ContextCreator.class);
-        unixContext = mock(LoginContext.class);
-        ourContext = mock(LoginContext.class);
-        when(creator.createContext("UnixLogin", user)).thenReturn(unixContext);
-        when(creator.createContext(eq("AgentProxyLogin"), same(user), any(CallbackHandler.class))).thenReturn(ourContext);
-        context = new AgentProxyLoginContext(user, creds, creator);
-    }
-    
-    @Test
-    public void testCreate() throws Exception {
-        verify(creator).createContext("UnixLogin", user);
-        ArgumentCaptor<CallbackHandler> captor = ArgumentCaptor.forClass(CallbackHandler.class);
-        verify(creator).createContext(eq("AgentProxyLogin"), same(user), captor.capture());
-        CallbackHandler handler = captor.getValue();
-        
-        AgentProxyCallback callback = mock(AgentProxyCallback.class);
-        handler.handle(new Callback[] { callback });
-        verify(callback).setTargetCredentials(creds);
-    }
-    
-    @Test
-    public void testLogin() throws Exception {
-        context.login();
-        verify(unixContext).login();
-        verify(ourContext).login();
-    }
-    
-    @Test
-    public void testLogout() throws Exception {
-        context.logout();
-        verify(ourContext).logout();
-        verify(unixContext).logout();
-    }
-    
-}
-
--- a/agent/proxy/server/src/test/java/com/redhat/thermostat/agent/proxy/server/AgentProxyLoginImplTest.java	Thu Aug 21 15:21:57 2014 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,118 +0,0 @@
-/*
- * Copyright 2012-2014 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are not obligated to do so.  If you do not wish
- * to do so, delete this exception statement from your version.
- */
-
-package com.redhat.thermostat.agent.proxy.server;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
-import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.same;
-import static org.mockito.Mockito.doThrow;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import java.rmi.RemoteException;
-import java.rmi.registry.Registry;
-
-import javax.security.auth.Subject;
-import javax.security.auth.login.LoginException;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.mockito.ArgumentCaptor;
-
-import com.redhat.thermostat.agent.proxy.common.AgentProxyControl;
-import com.redhat.thermostat.agent.proxy.server.AgentProxyLoginImpl.LoginContextCreator;
-
-public class AgentProxyLoginImplTest {
-    
-    private RegistryUtils registryUtils;
-    private Registry registry;
-    private UnixCredentials creds;
-    private LoginContextCreator contextCreator;
-    private AgentProxyLoginContext context;
-
-    @Before
-    public void setup() throws Exception {
-        registry = mock(Registry.class);
-        registryUtils = mock(RegistryUtils.class);
-        when(registryUtils.getRegistry()).thenReturn(registry);
-        creds = new UnixCredentials(9000, 9001, 0);
-        contextCreator = mock(LoginContextCreator.class);
-        context = mock(AgentProxyLoginContext.class);
-        when(contextCreator.createContext(any(Subject.class), same(creds))).thenReturn(context);
-    }
-    
-    @Test
-    public void testLoginSuccess() throws Exception {
-        ShutdownListener listener = mock(ShutdownListener.class);
-        AgentProxyLoginImpl proxyLogin = new AgentProxyLoginImpl(creds, 0, listener, contextCreator, registryUtils);
-        AgentProxyControl stub = proxyLogin.login();
-        
-        ArgumentCaptor<AgentProxyControl> captor = ArgumentCaptor.forClass(AgentProxyControl.class);
-        verify(registryUtils).exportObject(captor.capture());
-        AgentProxyControl control = captor.getValue();
-        
-        assertTrue(control instanceof AgentProxyControlWrapper);
-        assertFalse(stub instanceof AgentProxyControlWrapper);
-    }
-    
-    @Test
-    public void testLoginFailure() throws Exception {
-        ShutdownListener listener = mock(ShutdownListener.class);
-        
-        // Simulate login failure
-        LoginException ex = new LoginException("TEST");
-        doThrow(ex).when(context).login();
-        
-        AgentProxyLoginImpl proxyLogin = new AgentProxyLoginImpl(creds, 0, listener, contextCreator, registryUtils);
-        
-        try {
-            proxyLogin.login();
-            fail("Expected exception from login");
-        } catch (RemoteException e) {
-            assertEquals(ex, e.getCause());
-        }
-        
-        verify(registryUtils, never()).exportObject(any(AgentProxyControl.class));
-    }
-
-}
-
--- a/agent/proxy/server/src/test/java/com/redhat/thermostat/agent/proxy/server/AgentProxyLoginModuleTest.java	Thu Aug 21 15:21:57 2014 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,247 +0,0 @@
-/*
- * Copyright 2012-2014 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are not obligated to do so.  If you do not wish
- * to do so, delete this exception statement from your version.
- */
-
-package com.redhat.thermostat.agent.proxy.server;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
-import static org.mockito.Mockito.*;
-
-import java.util.HashMap;
-import java.util.Set;
-
-import javax.security.auth.Subject;
-import javax.security.auth.callback.Callback;
-import javax.security.auth.callback.CallbackHandler;
-import javax.security.auth.login.LoginException;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.mockito.invocation.InvocationOnMock;
-import org.mockito.stubbing.Answer;
-
-import com.redhat.thermostat.agent.proxy.server.AgentProxyLoginModule.AgentProxyCallback;
-
-public class AgentProxyLoginModuleTest {
-    
-    private AgentProxyLoginModule module;
-    private CallbackHandler handler;
-    private Subject subject;
-
-    @Before
-    public void setup() throws Exception {
-        module = new AgentProxyLoginModule();
-        subject = new Subject();
-        handler = mock(CallbackHandler.class);
-        final UnixCredentials creds = new UnixCredentials(9000, 9001, 0);
-        doAnswer(new Answer<Void>() {
-            @Override
-            public Void answer(InvocationOnMock invocation) throws Throwable {
-                Callback[] callbacks = (Callback[]) invocation.getArguments()[0];
-                for (Callback callback : callbacks) {
-                    if (callback instanceof AgentProxyCallback) {
-                        ((AgentProxyCallback) callback).setTargetCredentials(creds);
-                    }
-                }
-                return null;
-            }
-        }).when(handler).handle(any(Callback[].class));
-        module.initialize(subject, handler, new HashMap<String, Object>(), new HashMap<String, Object>());
-    }
-    
-    @Test
-    public void testLoginSuccess() throws Exception {
-        addPrincipals();
-        
-        assertTrue(module.login());
-        
-        AgentProxyPrincipal principal = module.getPrincipal();
-        assertNotNull(principal);
-        assertEquals("TEST", principal.getName());
-        assertTrue(module.isLoggedIn());
-        assertFalse(module.isCommitted());
-        assertTrue(subject.getPrincipals(AgentProxyPrincipal.class).isEmpty());
-    }
-    
-    @SuppressWarnings("restriction")
-    @Test
-    public void testLoginBadUid() throws Exception {
-        subject.getPrincipals().add(new com.sun.security.auth.UnixPrincipal("TEST"));
-        subject.getPrincipals().add(new com.sun.security.auth.UnixNumericUserPrincipal(8000));
-        subject.getPrincipals().add(new com.sun.security.auth.UnixNumericGroupPrincipal(9001, true));
-        
-        verifyFailedLogin();
-    }
-
-    @SuppressWarnings("restriction")
-    @Test
-    public void testLoginMissingUid() throws Exception {
-        subject.getPrincipals().add(new com.sun.security.auth.UnixPrincipal("TEST"));
-        subject.getPrincipals().add(new com.sun.security.auth.UnixNumericGroupPrincipal(9001, true));
-        
-        verifyFailedLogin();
-    }
-    
-    @SuppressWarnings("restriction")
-    @Test
-    public void testLoginBadGid() throws Exception {
-        subject.getPrincipals().add(new com.sun.security.auth.UnixPrincipal("TEST"));
-        subject.getPrincipals().add(new com.sun.security.auth.UnixNumericUserPrincipal(9000));
-        subject.getPrincipals().add(new com.sun.security.auth.UnixNumericGroupPrincipal(8001, true));
-        
-        verifyFailedLogin();
-    }
-    
-    @SuppressWarnings("restriction")
-    @Test
-    public void testLoginMissingGid() throws Exception {
-        subject.getPrincipals().add(new com.sun.security.auth.UnixPrincipal("TEST"));
-        subject.getPrincipals().add(new com.sun.security.auth.UnixNumericUserPrincipal(9000));
-        
-        verifyFailedLogin();
-    }
-    
-    @SuppressWarnings("restriction")
-    @Test
-    public void testLoginMissingUsername() throws Exception {
-        subject.getPrincipals().add(new com.sun.security.auth.UnixNumericUserPrincipal(9000));
-        subject.getPrincipals().add(new com.sun.security.auth.UnixNumericGroupPrincipal(9001, true));
-        
-        verifyFailedLogin();
-    }
-    
-    @Test
-    public void testCommitSuccess() throws Exception {
-        addPrincipals();
-        
-        assertTrue(module.login());
-        assertTrue(module.commit());
-        
-        assertTrue(module.isLoggedIn());
-        assertTrue(module.isCommitted());
-        Set<AgentProxyPrincipal> principals = subject.getPrincipals(AgentProxyPrincipal.class);
-        assertFalse(principals.isEmpty());
-        assertEquals(module.getPrincipal(), principals.iterator().next());
-    }
-    
-    @Test
-    public void testCommitNotLoggedIn() throws Exception {
-        addPrincipals();
-        
-        assertFalse(module.commit());
-        
-        assertFalse(module.isLoggedIn());
-        assertFalse(module.isCommitted());
-        assertTrue(subject.getPrincipals(AgentProxyPrincipal.class).isEmpty());
-    }
-    
-    @Test
-    public void testAbortNotLoggedIn() throws Exception {
-        addPrincipals();
-        
-        assertFalse(module.abort());
-        
-        verifyStateReset();
-    }
-
-    @Test
-    public void testAbortNotCommitted() throws Exception {
-        addPrincipals();
-        
-        assertTrue(module.login());
-        assertTrue(module.abort());
-        
-        verifyStateReset();
-    }
-    
-    @Test
-    public void testAbortCommitted() throws Exception {
-        addPrincipals();
-        
-        assertTrue(module.login());
-        assertTrue(module.commit());
-        assertTrue(module.abort());
-        
-        verifyStateReset();
-    }
-    
-    @Test
-    public void testLogout() throws Exception {
-        addPrincipals();
-        
-        assertTrue(module.login());
-        assertTrue(module.commit());
-        assertTrue(module.logout());
-        
-        verifyStateReset();
-    }
-
-    @SuppressWarnings("restriction")
-    private void addPrincipals() {
-        subject.getPrincipals().add(new com.sun.security.auth.UnixPrincipal("TEST"));
-        subject.getPrincipals().add(new com.sun.security.auth.UnixNumericUserPrincipal(9000));
-        subject.getPrincipals().add(new com.sun.security.auth.UnixNumericGroupPrincipal(9001, true));
-    }
-
-    private void verifyFailedLogin() {
-        try {
-            module.login();
-            fail("Expected LoginException");
-        } catch (LoginException e) {
-            assertFalse(module.isLoggedIn());
-            assertNull(module.getPrincipal());
-            assertFalse(module.isCommitted());
-            assertTrue(subject.getPrincipals(AgentProxyPrincipal.class).isEmpty());
-        }
-    }
-
-    @SuppressWarnings("restriction")
-    private void verifyStateReset() {
-        assertFalse(module.isLoggedIn());
-        assertFalse(module.isCommitted());
-        assertNull(module.getPrincipal());
-        assertTrue(subject.getPrincipals(AgentProxyPrincipal.class).isEmpty());
-        assertFalse(subject.getPrincipals(com.sun.security.auth.UnixPrincipal.class).isEmpty());
-        assertFalse(subject.getPrincipals(com.sun.security.auth.UnixNumericUserPrincipal.class).isEmpty());
-        assertFalse(subject.getPrincipals(com.sun.security.auth.UnixNumericGroupPrincipal.class).isEmpty());
-    }
-
-}
-
--- a/agent/proxy/server/src/test/java/com/redhat/thermostat/agent/proxy/server/AgentProxyTest.java	Thu Aug 21 15:21:57 2014 -0400
+++ b/agent/proxy/server/src/test/java/com/redhat/thermostat/agent/proxy/server/AgentProxyTest.java	Tue Dec 16 11:54:58 2014 -0700
@@ -36,106 +36,99 @@
 
 package com.redhat.thermostat.agent.proxy.server;
 
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-import static org.mockito.Matchers.any;
 import static org.mockito.Mockito.doThrow;
 import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
-import java.rmi.RemoteException;
-import java.rmi.registry.Registry;
-import java.util.Timer;
-import java.util.TimerTask;
+import java.io.IOException;
+import java.io.PrintStream;
 
+import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
-import org.mockito.ArgumentCaptor;
 
-import com.redhat.thermostat.agent.proxy.common.AgentProxyListener;
-import com.redhat.thermostat.agent.proxy.common.AgentProxyLogin;
+import com.redhat.thermostat.agent.proxy.server.AgentProxy.ControlCreator;
 
 public class AgentProxyTest {
     
-    private AgentProxyNativeUtils nativeUtils;
-    private RegistryUtils registryUtils;
-    private Registry registry;
-    private AgentProxyLogin loginStub;
-    private AgentProxyListener listener;
-    private Timer timeoutTimer;
+    private static final String JMX_URL = "service:jmx:rmi://myHost:1099/blah";
+    
+    private AgentProxyControlImpl control;
+    private PrintStream outStream;
 
     @Before
     public void setup() throws Exception {
-        registry = mock(Registry.class);
-        listener = mock(AgentProxyListener.class);
-        when(registry.lookup(AgentProxyListener.REMOTE_PREFIX + "0")).thenReturn(listener);
-        registryUtils = mock(RegistryUtils.class);
-        when(registryUtils.getRegistry()).thenReturn(registry);
-        loginStub = mock(AgentProxyLogin.class);
-        when(registryUtils.exportObject(any(AgentProxyLogin.class))).thenReturn(loginStub);
-        
-        nativeUtils = mock(AgentProxyNativeUtils.class);
-        ProcessUserInfoBuilder builder = mock(ProcessUserInfoBuilder.class);
-        when(builder.build(0)).thenReturn(new UnixCredentials(9000, 9001, 0));
-        timeoutTimer = mock(Timer.class);
-        AgentProxy.setRegistryUtils(registryUtils);
-        AgentProxy.setNativeUtils(nativeUtils);
-        AgentProxy.setProcessUserInfoBuilder(builder);
-        AgentProxy.setTimeoutTimer(timeoutTimer);
+        ControlCreator creator = mock(ControlCreator.class);
+        control = mock(AgentProxyControlImpl.class);
+        when(control.getConnectorAddress()).thenReturn(JMX_URL);
+        outStream = mock(PrintStream.class);
+        when(creator.create(0)).thenReturn(control);
+        AgentProxy.setControlCreator(creator);
+        AgentProxy.setOutStream(outStream);
+    }
+    
+    @After
+    public void teardown() throws Exception {
+        AgentProxy.setControlCreator(new ControlCreator());
+        AgentProxy.setOutStream(System.out);
     }
     
     @Test
     public void testMainSuccess() throws Exception {
-        assertFalse(AgentProxy.isBound());
+        // Invoke main with PID of 0
+        AgentProxy.main(new String[] { "0" });
+        
+        verify(control).attach();
+        verify(control).getConnectorAddress();
+        verify(control).detach();
+        verify(outStream).println(JMX_URL);
+    }
+    
+    @Test
+    public void testMainAttachFails() throws Exception {
+        // Simulate failure binding the login object
+        doThrow(new IOException()).when(control).attach();
         
         // Invoke main with PID of 0
         AgentProxy.main(new String[] { "0" });
         
-        assertTrue(AgentProxy.isBound());
-        
-        // Verify timeout set
-        verify(timeoutTimer).schedule(any(TimerTask.class), any(Long.class));
-        
-        // Verify native library loaded and credentials properly set
-        verify(nativeUtils).loadLibrary();
-        verify(nativeUtils).setCredentials(9000, 9001);
-        
-        // Verify login object exported
-        AgentProxyLogin proxyLogin = AgentProxy.getAgentProxyLogin();
-        verify(registryUtils).exportObject(proxyLogin);
-        verify(registry).rebind(AgentProxyLogin.REMOTE_PREFIX + "0", loginStub);
-        
-        // Verify listener notified with positive response
-        verify(listener).serverStarted();
-        
-        // Shutdown server
-        ShutdownListener shutdownListener = AgentProxy.getShutdownListener();
-        shutdownListener.shutdown();
-        
-        // Verify login object unexported
-        verify(registry).unbind(AgentProxyLogin.REMOTE_PREFIX + "0");
-        verify(registryUtils).unexportObject(proxyLogin);
-        
-        assertFalse(AgentProxy.isBound());
+        verify(control).attach();
+        verify(control, never()).getConnectorAddress();
+        verify(control, never()).detach();
+        verify(outStream, never()).println(JMX_URL);
     }
     
     @Test
-    public void testMainFailure() throws Exception {
+    public void testMainGetAddressFails() throws Exception {
         // Simulate failure binding the login object
-        RemoteException ex = new RemoteException("TEST");
-        doThrow(ex).when(registry).rebind(AgentProxyLogin.REMOTE_PREFIX + "0", loginStub);
+        doThrow(new IOException()).when(control).getConnectorAddress();
         
         // Invoke main with PID of 0
         AgentProxy.main(new String[] { "0" });
         
-        // Verify listener notified with negative response
-        ArgumentCaptor<Exception> errorCaptor = ArgumentCaptor.forClass(Exception.class);
-        verify(listener).serverFailedToStart(errorCaptor.capture());
-        assertEquals(ex, errorCaptor.getValue().getCause());
+        verify(control).attach();
+        verify(control).getConnectorAddress();
         
-        assertFalse(AgentProxy.isBound());
+        // Should detach, but not print URL
+        verify(control).detach();
+        verify(outStream, never()).println(JMX_URL);
+    }
+    
+    @Test
+    public void testMainDetachFails() throws Exception {
+        // Simulate failure binding the login object
+        doThrow(new IOException()).when(control).detach();
+        
+        // Invoke main with PID of 0
+        AgentProxy.main(new String[] { "0" });
+        
+        // All should be called
+        verify(control).attach();
+        verify(control).getConnectorAddress();
+        verify(control).detach();
+        verify(outStream).println(JMX_URL);
     }
 
 }
--- a/agent/proxy/server/src/test/java/com/redhat/thermostat/agent/proxy/server/ProcessUserInfoBuilderTest.java	Thu Aug 21 15:21:57 2014 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,85 +0,0 @@
-/*
- * Copyright 2012-2014 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are not obligated to do so.  If you do not wish
- * to do so, delete this exception statement from your version.
- */
-
-package com.redhat.thermostat.agent.proxy.server;
-
-import static org.junit.Assert.assertEquals;
-import static org.mockito.Matchers.anyInt;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-
-import java.io.IOException;
-import java.io.StringReader;
-
-import org.junit.Test;
-
-import com.redhat.thermostat.common.tools.ApplicationException;
-
-public class ProcessUserInfoBuilderTest {
-
-    @Test
-    public void testBuild() throws IOException {
-        StringReader reader = new StringReader("Uid:   2000  2000  2000  2000\nGid:   2001  2001  2001  2001");
-        ProcDataSource source = mock(ProcDataSource.class);
-        when(source.getStatusReader(anyInt())).thenReturn(reader);
-        ProcessUserInfoBuilder builder = new ProcessUserInfoBuilder(source);
-        UnixCredentials creds = builder.build(1);
-
-        assertEquals(2000, creds.getUid());
-        assertEquals(2001, creds.getGid());
-        assertEquals(1, creds.getPid());
-    }
-
-    @Test(expected=IOException.class)
-    public void testBuildErrorUid() throws IOException, ApplicationException {
-        StringReader reader = new StringReader("Gid:   2001  2001  2001  2001");
-        ProcDataSource source = mock(ProcDataSource.class);
-        when(source.getStatusReader(anyInt())).thenReturn(reader);
-        ProcessUserInfoBuilder builder = new ProcessUserInfoBuilder(source);
-        builder.build(0);
-    }
-
-    @Test(expected=IOException.class)
-    public void testBuildErrorGid() throws IOException, ApplicationException {
-        StringReader reader = new StringReader("Uid:   2000  2000  2000  2000");
-        ProcDataSource source = mock(ProcDataSource.class);
-        when(source.getStatusReader(anyInt())).thenReturn(reader);
-        ProcessUserInfoBuilder builder = new ProcessUserInfoBuilder(source);
-        builder.build(0);
-    }
-    
-}
-
--- a/distribution/assembly/core-assembly.xml	Thu Aug 21 15:21:57 2014 -0400
+++ b/distribution/assembly/core-assembly.xml	Tue Dec 16 11:54:58 2014 -0700
@@ -59,7 +59,6 @@
         <include>com.redhat.thermostat:thermostat-agent-core</include>
         <include>com.redhat.thermostat:thermostat-agent-cli</include>
         <include>com.redhat.thermostat:thermostat-agent-command</include>
-        <include>com.redhat.thermostat:thermostat-agent-proxy-common</include>
         <include>com.redhat.thermostat:thermostat-agent-proxy-server</include>
         <include>com.redhat.thermostat:thermostat-killvm-agent</include>
         <include>com.redhat.thermostat:thermostat-killvm-client-swing</include>
--- a/distribution/config/agent_proxy_jaas.conf	Thu Aug 21 15:21:57 2014 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,7 +0,0 @@
-UnixLogin {
-   com.sun.security.auth.module.UnixLoginModule required debug=false;
-};
-
-AgentProxyLogin {
-   com.redhat.thermostat.agent.proxy.server.AgentProxyLoginModule required debug=false;
-};
--- a/distribution/config/commands/agent.properties	Thu Aug 21 15:21:57 2014 -0400
+++ b/distribution/config/commands/agent.properties	Tue Dec 16 11:54:58 2014 -0700
@@ -7,7 +7,6 @@
           com.redhat.thermostat.process=${project.version}, \
           com.redhat.thermostat.common.core=${project.version}, \
           com.redhat.thermostat.agent.cli=${project.version}, \
-          com.redhat.thermostat.agent.proxy.common=${project.version}, \
           com.redhat.thermostat.common.command=${project.version}, \
           com.redhat.thermostat.agent.command=${project.version}, \
           com.redhat.thermostat.killvm.agent=${project.version}, \
--- a/distribution/config/commands/service.properties	Thu Aug 21 15:21:57 2014 -0400
+++ b/distribution/config/commands/service.properties	Tue Dec 16 11:54:58 2014 -0700
@@ -10,7 +10,6 @@
           com.redhat.thermostat.agent.command=${project.version}, \
           com.redhat.thermostat.storage.cli=${project.version}, \
           com.redhat.thermostat.agent.cli=${project.version}, \
-          com.redhat.thermostat.agent.proxy.common=${project.version}, \
           org.jboss.netty=${netty.version}
 
 description = starts and stops the thermostat storage and agent
--- a/distribution/pom.xml	Thu Aug 21 15:21:57 2014 -0400
+++ b/distribution/pom.xml	Tue Dec 16 11:54:58 2014 -0700
@@ -145,7 +145,6 @@
                     <include>thermostat-users.properties</include>
                     <include>thermostat-roles.properties</include>
                     <include>thermostat_jaas.conf</include>
-                    <include>agent_proxy_jaas.conf</include>
                     <include>db.properties</include>
                     <include>logging.properties</include>
                     <include>osgi-export.properties</include>
@@ -209,8 +208,6 @@
                       todir="${project.build.directory}/image/libs/native" />
                 <copy file="${main.basedir}/agent/core/target/libUserNameUtilWrapper.so"
                       todir="${project.build.directory}/image/libs/native" />
-                <copy file="${main.basedir}/agent/proxy/server/target/libAgentProxy.so"
-                      todir="${project.build.directory}/image/libs/native" />
                 <copy file="${main.basedir}/laf-utils/target/libGTKThemeUtils.so"
                       todir="${project.build.directory}/image/libs/native" />
               </target>
--- a/distribution/scripts/thermostat	Thu Aug 21 15:21:57 2014 -0400
+++ b/distribution/scripts/thermostat	Tue Dec 16 11:54:58 2014 -0700
@@ -60,8 +60,6 @@
 SERVICE_CLASSPATH="${SERVICE_CLASSPATH}:${THERMOSTAT_LIBS}/thermostat-launcher-@project.version@.jar"
 SERVICE_CLASSPATH="${SERVICE_CLASSPATH}:${THERMOSTAT_LIBS}/thermostat-main-@project.version@.jar"
 SERVICE_CLASSPATH="${SERVICE_CLASSPATH}:${THERMOSTAT_LIBS}/thermostat-shared-config-@project.version@.jar"
-# This needs to be on the classpath for the RMI registry to find it
-SERVICE_CLASSPATH="${SERVICE_CLASSPATH}:${THERMOSTAT_LIBS}/thermostat-agent-proxy-common-@project.version@.jar"
 # FIXME: Remove once jfreechart is a real OSGi bundle upstream
 SERVICE_CLASSPATH="${SERVICE_CLASSPATH}:${THERMOSTAT_LIBS}/jfreechart-@jfreechart.version@.jar"
 SERVICE_CLASSPATH="${SERVICE_CLASSPATH}:${THERMOSTAT_LIBS}/jcommon-@jcommon.version@.jar"
--- a/distribution/scripts/thermostat-agent-proxy	Thu Aug 21 15:21:57 2014 -0400
+++ b/distribution/scripts/thermostat-agent-proxy	Tue Dec 16 11:54:58 2014 -0700
@@ -40,6 +40,10 @@
 JAVA_DIR="@java.dir@"
 JAVA="@java.home@/bin/java"
 
+if [ "$#" -lt 2 ]; then
+  echo "usage: $0 <pidOfTargetJvm> <userNameOfJvmOwner>" >&2
+fi
+
 if [ x"$THERMOSTAT_INSTALL_DIR" = x ] ; then
   THERMOSTAT_INSTALL_DIR="@thermostat.home@"
 fi
@@ -56,20 +60,20 @@
 # JARs necessary for the server
 SERVICE_CLASSPATH="${THERMOSTAT_LIBS}/thermostat-common-core-@project.version@.jar"
 SERVICE_CLASSPATH="${SERVICE_CLASSPATH}:${THERMOSTAT_LIBS}/thermostat-shared-config-@project.version@.jar"
-SERVICE_CLASSPATH="${SERVICE_CLASSPATH}:${THERMOSTAT_LIBS}/thermostat-agent-proxy-common-@project.version@.jar"
 SERVICE_CLASSPATH="${SERVICE_CLASSPATH}:${THERMOSTAT_LIBS}/thermostat-agent-proxy-server-@project.version@.jar"
 SERVICE_CLASSPATH="${TOOLS_JAR}:${SERVICE_CLASSPATH}"
 
 AGENT_PROXY_CLASS="com.redhat.thermostat.agent.proxy.server.AgentProxy"
 
-JAAS_CONFIG="${THERMOSTAT_HOME}/etc/agent_proxy_jaas.conf"
-
 # Set this to remote debug
 if [ x"$THERMOSTAT_DEBUG" != x ] ; then
   DEBUG_OPTS="-Xdebug -Xrunjdwp:transport=dt_socket,server=y,address=1082"
 fi
 
 # Start server
-${JAVA} -cp ${SERVICE_CLASSPATH} ${DEBUG_OPTS} "-Djava.security.auth.login.config=${JAAS_CONFIG}" \
-"-Djava.rmi.server.randomIDs=true" ${AGENT_PROXY_CLASS} "$1"
-
+# Drop permissions, if root
+if [ "$(/bin/id -u)" -eq 0 ]; then
+  /bin/su "$2" -c "${JAVA} -cp ${SERVICE_CLASSPATH} ${DEBUG_OPTS} ${AGENT_PROXY_CLASS} $1"
+else
+  ${JAVA} -cp ${SERVICE_CLASSPATH} ${DEBUG_OPTS} ${AGENT_PROXY_CLASS} $1
+fi