1 19 20 package com.sslexplorer.tunnels; 21 22 import java.io.IOException ; 23 import java.util.ArrayList ; 24 import java.util.Collection ; 25 import java.util.HashSet ; 26 import java.util.List ; 27 import java.util.Set ; 28 29 import org.apache.commons.logging.Log; 30 import org.apache.commons.logging.LogFactory; 31 32 import com.maverick.multiplex.Channel; 33 import com.maverick.multiplex.MultiplexedConnection; 34 import com.maverick.multiplex.Request; 35 import com.maverick.multiplex.RequestHandler; 36 import com.maverick.util.ByteArrayReader; 37 import com.maverick.util.ByteArrayWriter; 38 import com.sslexplorer.agent.AbstractResourceService; 39 import com.sslexplorer.agent.AgentService; 40 import com.sslexplorer.agent.AgentTunnel; 41 import com.sslexplorer.agent.DefaultAgentManager; 42 import com.sslexplorer.core.CoreEvent; 43 import com.sslexplorer.core.CoreException; 44 import com.sslexplorer.core.CoreServlet; 45 import com.sslexplorer.core.stringreplacement.VariableReplacement; 46 import com.sslexplorer.policyframework.LaunchSession; 47 import com.sslexplorer.policyframework.LaunchSessionFactory; 48 import com.sslexplorer.policyframework.LaunchSessionManager; 49 import com.sslexplorer.policyframework.NoPermissionException; 50 import com.sslexplorer.policyframework.Policy; 51 import com.sslexplorer.policyframework.PolicyDatabaseFactory; 52 import com.sslexplorer.policyframework.PolicyException; 53 import com.sslexplorer.policyframework.ResourceAccessEvent; 54 import com.sslexplorer.policyframework.ResourceUtil; 55 import com.sslexplorer.security.SessionInfo; 56 import com.sslexplorer.tunnels.agent.LocalForwardingChannel; 57 import com.sslexplorer.tunnels.agent.RemoteTunnel; 58 import com.sslexplorer.tunnels.agent.RemoteTunnelManagerFactory; 59 60 66 public class TunnelingService extends AbstractResourceService implements RequestHandler { 67 68 69 static Log log = LogFactory.getLog(TunnelingService.class); 70 71 75 public static final String START_LOCAL_TUNNEL = "startLocalTunnel@3sp.com"; 77 84 public static final String SETUP_AND_LAUNCH_TUNNEL = "setupAndLaunchTunnel@3sp.com"; 86 89 public static final String START_REMOTE_TUNNEL = "startRemoteTunnel@3sp.com"; 90 91 94 public static final String STOP_REMOTE_TUNNEL = "stopRemoteTunnel@3sp.com"; 95 96 100 public static final String STOP_LOCAL_TUNNEL = "stopLocalTunnel@3sp.com"; 102 106 public static final String ACTIVE_LOCAL_TUNNELS = "activeLocalTunnels@3sp.com"; 108 private AgentTunnel agent; 110 111 114 public TunnelingService() { 115 super(TunnelPlugin.SSL_TUNNEL_RESOURCE_TYPE, new int[] { 116 TunnelsEventConstants.CREATE_TUNNEL, 117 TunnelsEventConstants.REMOVE_TUNNEL, 118 TunnelsEventConstants.UPDATE_TUNNEL }); 119 } 120 121 129 public void stopTunnels(LaunchSession launchSession) throws NoPermissionException, CoreException { 130 if (!DefaultAgentManager.getInstance().hasActiveAgent(launchSession.getSession())) { 131 throw new TunnelException(TunnelException.INTERNAL_ERROR, (Throwable )null, "No agent."); 132 } 133 134 Tunnel tunnel = (Tunnel) launchSession.getResource(); 135 launchSession.checkAccessRights(null, agent.getSession()); 136 MultiplexedConnection agent = DefaultAgentManager.getInstance().getAgentBySession(launchSession.getSession()); 137 138 try { 139 if (tunnel.getType() == TransportType.LOCAL_TUNNEL_ID) { 140 Collection <Tunnel> l = new ArrayList <Tunnel>(); 141 l.add(tunnel); 142 stopLocalTunnels(agent, l); 143 } else if (tunnel.getType() == TransportType.REMOTE_TUNNEL_ID) { 144 Collection <Tunnel> l = new ArrayList <Tunnel>(); 145 l.add(tunnel); 146 stopRemoteTunnels(agent, l); 147 } else { 148 throw new TunnelException(TunnelException.INTERNAL_ERROR, (Throwable )null, "Unknown tunnel type " + tunnel.getType()); 149 } 150 151 CoreServlet.getServlet().fireCoreEvent( 152 new ResourceAccessEvent(this, TunnelsEventConstants.TUNNEL_CLOSED, launchSession.getResource(), 153 launchSession.getPolicy(), launchSession.getSession(), CoreEvent.STATE_SUCCESSFUL)); 154 155 } catch (TunnelException te) { 156 CoreServlet.getServlet().fireCoreEvent( 157 new ResourceAccessEvent(this, TunnelsEventConstants.TUNNEL_CLOSED, launchSession.getResource(), 158 launchSession.getPolicy(), launchSession.getSession(), te)); 159 throw te; 160 } finally { 161 LaunchSessionFactory.getInstance().removeLaunchSession(launchSession); 162 } 163 } 164 165 174 public void startTunnel(LaunchSession launchSession) throws NoPermissionException, TunnelException, PolicyException { 175 176 if (!DefaultAgentManager.getInstance().hasActiveAgent(launchSession.getSession())) { 177 throw new TunnelException(TunnelException.INTERNAL_ERROR, (Throwable )null, "No agent."); 178 } else { 179 Tunnel tunnel = (Tunnel) launchSession.getResource(); 180 launchSession.checkAccessRights(null, agent.getSession()); 181 AgentTunnel agent = DefaultAgentManager.getInstance().getAgentBySession(launchSession.getSession()); 182 183 try { 184 if (tunnel.getType() == TransportType.LOCAL_TUNNEL_ID) { 185 startLocalTunnel(agent, tunnel, launchSession); 186 } else if (tunnel.getType() == TransportType.REMOTE_TUNNEL_ID) { 187 startRemoteTunnel(agent, tunnel, launchSession); 188 } else { 189 throw new TunnelException(TunnelException.INTERNAL_ERROR, (Throwable )null, "Unknown tunnel type " + tunnel.getType()); 190 } 191 192 CoreServlet.getServlet().fireCoreEvent( 194 new ResourceAccessEvent(this, TunnelsEventConstants.TUNNEL_OPENED, launchSession.getResource(), 195 launchSession.getPolicy(), launchSession.getSession(), CoreEvent.STATE_SUCCESSFUL)); 196 } catch (TunnelException te) { 197 198 CoreServlet.getServlet().fireCoreEvent( 200 new ResourceAccessEvent(this, TunnelsEventConstants.TUNNEL_OPENED, launchSession.getResource(), 201 launchSession.getPolicy(), launchSession.getSession(), te)); 202 203 throw te; 204 } 205 } 206 } 207 208 214 public Set <Integer > getActiveTunnels(SessionInfo session) { 215 216 try { 217 MultiplexedConnection tunnel = DefaultAgentManager.getInstance().getAgentBySession(session); 218 219 if (tunnel == null) 220 return null; 221 222 HashSet <Integer > activeTunnelIds = new HashSet <Integer >(); 223 224 226 Request request = new Request(ACTIVE_LOCAL_TUNNELS); 227 if (tunnel.sendRequest(request, true) && request.getRequestData()!=null) { 228 229 ByteArrayReader reader = new ByteArrayReader(request.getRequestData()); 230 int count = (int) reader.readInt(); 231 for (int i = 0; i < count; i++) { 232 activeTunnelIds.add(new Integer ((int) reader.readInt())); 233 } 234 } 235 236 Collection <RemoteTunnel> activeRemoteTunnels = RemoteTunnelManagerFactory.getInstance().getRemoteTunnels(session); 238 if (activeRemoteTunnels != null) { 239 synchronized (activeRemoteTunnels) { 240 for (RemoteTunnel r : activeRemoteTunnels) { 241 activeTunnelIds.add(r.getTunnel().getResourceId()); 242 } 243 } 244 } 245 246 return activeTunnelIds; 247 } catch (IOException e) { 248 log.error("Failed to get active tunnel list from agent", e); 249 return null; 250 } 251 } 252 253 public void performStartup(AgentTunnel agent) { 254 this.agent = agent; 255 notifyAutoStartTunnels(); 256 } 257 258 public Channel createChannel(MultiplexedConnection connection, String type) { 259 if (type.equals(LocalForwardingChannel.CHANNEL_TYPE)) { 260 return new LocalForwardingChannel(); 261 } else 262 return null; 263 } 264 265 public void initializeTunnel(AgentTunnel tunnel) { 266 tunnel.registerRequestHandler(SETUP_AND_LAUNCH_TUNNEL, this); 267 } 268 269 public boolean processRequest(Request request, MultiplexedConnection connection) { 270 AgentTunnel agent = (AgentTunnel) connection; 271 if (request.getRequestName().equals(SETUP_AND_LAUNCH_TUNNEL) && request.getRequestData()!=null) { 272 try { 273 ByteArrayReader reader = new ByteArrayReader(request.getRequestData()); 274 int id = (int)reader.readInt(); 275 Tunnel resource = (Tunnel)TunnelPlugin.SSL_TUNNEL_RESOURCE_TYPE.getResourceById(id); 276 if (resource == null) { 277 throw new Exception ("No resource with ID " + id); 278 } 279 Policy policy = LaunchSessionManager.getLaunchRequestPolicy(null, agent.getSession(), resource); 280 if (resource.sessionPasswordRequired(agent.getSession())) { 281 return true; 283 } else { 284 LaunchSession launchSession = LaunchSessionFactory.getInstance().createLaunchSession(agent.getSession(), 285 resource, 286 policy); 287 launchSession.checkAccessRights(null, agent.getSession()); 288 if (resource.getType() == TransportType.LOCAL_TUNNEL_ID) { 289 try { 290 Request req = buildLocalTunnel(resource, launchSession); 291 request.setRequestData(req.getRequestData()); 292 return true; 293 } catch (IOException ioe) { 294 throw new TunnelException(TunnelException.INTERNAL_ERROR, ioe); 295 } 296 } else if (resource.getType() == TransportType.REMOTE_TUNNEL_ID) { 297 startRemoteTunnel(agent, resource, launchSession); 298 request.setRequestData(null); 299 return true; 300 } else { 301 throw new TunnelException(TunnelException.INTERNAL_ERROR, (Throwable )null, "Unknown tunnel type " + resource.getType()); 302 } 303 } 304 } catch (Exception e) { 305 log.error("Failed to start tunnel.", e); 306 return false; 307 } 308 } 309 return false; 310 } 311 312 public void postReply(MultiplexedConnection connection) { 313 } 314 315 void startRemoteTunnel(AgentTunnel agent, Tunnel tunnel , LaunchSession launchSession) throws TunnelException { 316 RemoteTunnel remoteTunnel = RemoteTunnelManagerFactory.getInstance().createRemoteTunnel(tunnel, agent, launchSession); 317 remoteTunnel.start(); 318 } 319 320 void startLocalTunnel(AgentTunnel agent, Tunnel tunnel, LaunchSession launchSession) throws TunnelException { 321 try { 322 Request req = buildLocalTunnel(tunnel, launchSession); 323 326 if (!agent.sendRequest(req, Thread.currentThread() != agent.getThread())) { 327 throw new TunnelException(TunnelException.AGENT_REFUSED_LOCAL_TUNNEL, (Throwable )null); 328 } 329 } catch (IOException ioe) { 330 throw new TunnelException(TunnelException.INTERNAL_ERROR, ioe); 331 } 332 } 333 334 @SuppressWarnings ("unchecked") 335 void notifyAutoStartTunnels() { 336 try { 337 List <Tunnel> tunnels = ResourceUtil.getGrantedResource(agent.getSession(), TunnelPlugin.SSL_TUNNEL_RESOURCE_TYPE); 338 for (Tunnel tunnel : tunnels) { 339 if(tunnel.isAutoStart()) { 340 LaunchSession launchSession = LaunchSessionFactory.getInstance().createLaunchSession( 341 agent.getSession(), tunnel, PolicyDatabaseFactory.getInstance().getGrantingPolicyForUser( 342 agent.getSession().getUser(), tunnel)); 343 startTunnel(launchSession); 344 } 345 } 346 } catch (Exception e) { 347 log.error("Failed to start auto-start tunnels", e); 348 } 349 350 } 351 352 Request buildLocalTunnel(Tunnel tunnel, LaunchSession launchSession) throws IOException { 353 VariableReplacement r = new VariableReplacement(); 355 r.setLaunchSession(launchSession); 356 String destHost = r.replace(tunnel.getDestination().getHost()); 357 358 ByteArrayWriter msg = new ByteArrayWriter(); 359 msg.writeString(launchSession == null ? "" : launchSession.getId()); 360 msg.writeInt(tunnel.getResourceId()); 361 msg.writeString(tunnel.getResourceName()); 362 msg.writeInt(tunnel.getType()); 363 msg.writeString(tunnel.getTransport()); 364 msg.writeString(tunnel.getSourceInterface()); 365 msg.writeInt(tunnel.getSourcePort()); 366 msg.writeInt(tunnel.getDestination().getPort()); 367 msg.writeString(destHost); 368 Request req = new Request(START_LOCAL_TUNNEL, msg.toByteArray()); 369 return req; 370 371 } 372 373 void stopLocalTunnels(MultiplexedConnection agent, Collection <Tunnel> tunnels) throws CoreException { 374 375 CoreException e = null; 376 377 for (Tunnel tunnel : tunnels) { 378 try { 379 ByteArrayWriter msg = new ByteArrayWriter(); 380 msg.writeInt(tunnel.getResourceId()); 381 if (!agent.sendRequest(new Request(STOP_LOCAL_TUNNEL, msg.toByteArray()), false) && e == null) { 382 e = new TunnelException(TunnelException.AGENT_REFUSED_LOCAL_TUNNEL_STOP, (Throwable )null); 383 } 384 } catch (IOException ex) { 385 throw new TunnelException(TunnelException.INTERNAL_ERROR, ex); 386 } 387 } 388 if (e != null) { 389 throw e; 390 } 391 } 392 393 void stopRemoteTunnels(MultiplexedConnection agent, Collection <Tunnel> tunnels) throws CoreException { 394 395 CoreException e = null; 396 397 for (Tunnel tunnel : tunnels) { 398 try { 399 RemoteTunnel rt = RemoteTunnelManagerFactory.getInstance().getRemoteTunnel(tunnel.getResourceId()); 400 if (rt != null) { 401 rt.stopListener(); 402 } else { 403 throw new Exception ("No active with ID for " + tunnel.getResourceId()); 404 } 405 } catch (Exception ex) { 406 throw new TunnelException(TunnelException.INTERNAL_ERROR, ex); 407 } 408 } 409 if (e != null) { 410 throw e; 411 } 412 } 413 } 414 | Popular Tags |