1 /* 2 * Copyright (c) 2003 The Visigoth Software Society. All rights 3 * reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in 14 * the documentation and/or other materials provided with the 15 * distribution. 16 * 17 * 3. The end-user documentation included with the redistribution, if 18 * any, must include the following acknowledgement: 19 * "This product includes software developed by the 20 * Visigoth Software Society (http://www.visigoths.org/)." 21 * Alternately, this acknowledgement may appear in the software itself, 22 * if and wherever such third-party acknowledgements normally appear. 23 * 24 * 4. Neither the name "FreeMarker", "Visigoth", nor any of the names of the 25 * project contributors may be used to endorse or promote products derived 26 * from this software without prior written permission. For written 27 * permission, please contact visigoths@visigoths.org. 28 * 29 * 5. Products derived from this software may not be called "FreeMarker" or "Visigoth" 30 * nor may "FreeMarker" or "Visigoth" appear in their names 31 * without prior written permission of the Visigoth Software Society. 32 * 33 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED 34 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 35 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 36 * DISCLAIMED. IN NO EVENT SHALL THE VISIGOTH SOFTWARE SOCIETY OR 37 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 38 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 39 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF 40 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 41 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 42 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 43 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 44 * SUCH DAMAGE. 45 * ==================================================================== 46 * 47 * This software consists of voluntary contributions made by many 48 * individuals on behalf of the Visigoth Software Society. For more 49 * information on the Visigoth Software Society, please see 50 * http://www.visigoths.org/ 51 */ 52 53 package freemarker.debug.impl; 54 55 import java.io.IOException; 56 import java.io.ObjectInputStream; 57 import java.io.ObjectOutputStream; 58 import java.io.Serializable; 59 import java.io.UnsupportedEncodingException; 60 import java.net.ServerSocket; 61 import java.net.Socket; 62 import java.security.MessageDigest; 63 import java.security.SecureRandom; 64 import java.util.Arrays; 65 import java.util.Random; 66 67 import freemarker.debug.Debugger; 68 import freemarker.log.Logger; 69 import freemarker.template.utility.SecurityUtilities; 70 import freemarker.template.utility.UndeclaredThrowableException; 71 72 /** 73 * @author Attila Szegedi 74 * @version $Id: DebuggerServer.java,v 1.3 2004/09/09 15:34:38 szegedia Exp $ 75 */ 76 class DebuggerServer 77 { 78 private static final Logger logger = Logger.getLogger("freemarker.debug.server"); 79 // TODO: Eventually replace with Yarrow 80 private static final Random R = new SecureRandom(); 81 82 private final byte[] password; 83 private final int port; 84 private final Serializable debuggerStub; 85 86 public DebuggerServer(Serializable debuggerStub) 87 { 88 port = SecurityUtilities.getSystemProperty("freemarker.debug.port", Debugger.DEFAULT_PORT).intValue(); 89 try 90 { 91 password = SecurityUtilities.getSystemProperty("freemarker.debug.password", "").getBytes("UTF-8"); 92 } 93 catch (UnsupportedEncodingException e) 94 { 95 throw new UndeclaredThrowableException(e); 96 } 97 this.debuggerStub = debuggerStub; 98 } 99 100 public void start() 101 { 102 new Thread(new Runnable() 103 { 104 public void run() 105 { 106 startInternal(); 107 } 108 }, "FreeMarker Debugger Server Acceptor").start(); 109 } 110 111 private void startInternal() 112 { 113 try 114 { 115 ServerSocket ss = new ServerSocket(port); 116 for(;;) 117 { 118 Socket s = ss.accept(); 119 new Thread(new DebuggerAuthProtocol(s)).start(); 120 } 121 } 122 catch(IOException e) 123 { 124 logger.error("Debugger server shut down.", e); 125 } 126 } 127 128 private class DebuggerAuthProtocol implements Runnable 129 { 130 private final Socket s; 131 132 DebuggerAuthProtocol(Socket s) 133 { 134 this.s = s; 135 } 136 137 public void run() 138 { 139 try 140 { 141 ObjectOutputStream out = new ObjectOutputStream(s.getOutputStream()); 142 ObjectInputStream in = new ObjectInputStream(s.getInputStream()); 143 byte[] challenge = new byte[512]; 144 R.nextBytes(challenge); 145 out.writeInt(220); // protocol version 146 out.writeObject(challenge); 147 MessageDigest md = MessageDigest.getInstance("SHA"); 148 md.update(password); 149 md.update(challenge); 150 byte[] response = (byte[])in.readObject(); 151 if(Arrays.equals(response, md.digest())) 152 { 153 out.writeObject(debuggerStub); 154 } 155 else 156 { 157 out.writeObject(null); 158 } 159 } 160 catch(Exception e) 161 { 162 logger.warn("Connection to " + s.getInetAddress().getHostAddress() + " abruply broke", e); 163 } 164 } 165 166 } 167 }