Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: infranet/InfranetFilter.java


1   /* Copyright (c) 2003, Massachusetts Institute of Technology
2    * All rights reserved.
3    *
4    * Permission to use, copy, modify and distribute this software and its
5    * documentation for any purpose, without fee, and without written agreement is
6    * hereby granted, provided that the above copyright notice and the following
7    * paragraph appears in all copies of this software.
8    *
9    * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
10   * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
11   * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
12   * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
13   * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
14   * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
15   * IN THE SOFTWARE.
16   *
17   * Author: Winston Wang
18   *
19   */
20  
21  package infranet;
22  
23  import java.util.*;
24  import java.io.*;
25  import java.net.*;
26  
27  import javax.servlet.*;
28  import javax.servlet.http.*;
29  import java.io.IOException;
30  
31  import java.security.*;
32  import javax.crypto.*;
33  import org.bouncycastle.openssl.PEMReader;
34  import org.bouncycastle.util.encoders.Hex;
35  import org.bouncycastle.jce.provider.BouncyCastleProvider;
36  
37  public class InfranetFilter implements Filter {
38      private static final boolean SAVE_DATA = false;
39      private static final int SOCKET_TIMEOUT = 15000;
40  
41      private static final int SHARED_KEY = 0;
42      private static final int UPDATE = 1;
43      private static final int DEMOD = 2;
44      private static final int SERVE = 3;
45  
46      private static String initialKey, docBase;
47      private static Map maxBytes;
48  
49      private static final String cdfPath = "WEB-INF/config/cdf.txt";
50      private static final String urlPath = "WEB-INF/config/url.txt";
51      private static final String symPath = "WEB-INF/config/symbol.txt";
52      private static final String capPath = "WEB-INF/config/outguess-table.txt";
53      private static final String rsaPath = "WEB-INF/config/rsa.priv";
54  
55      private static ServletContext context;
56      private static boolean first = true;
57  
58      private static class ClientState {
59    public int state;
60    public String key;
61    public Dictionary dict;
62    public InfranetMessage message;
63    public ClientState() throws IOException {
64        state = SHARED_KEY;
65        key = initialKey;
66        dict = new HexDictionary();
67        message = new InfranetMessage(dict.getDownstream());
68    }
69      }
70  
71      private static int fileCount = 0;
72      private static synchronized String getFileName() {
73    ++fileCount;
74    return "data-"+fileCount;
75      }
76  
77      public void init(FilterConfig config) {
78    try {
79        initialKey = config.getInitParameter("initialKey");
80        if (initialKey == null) {
81        System.out.println("web.xml error - No initial key specified");
82      }
83        context = config.getServletContext();
84        docBase = context.getRealPath("/");
85  
86        RangeDictionary.initCdf(docBase + cdfPath, docBase + symPath);
87  
88        if (!new File(docBase + urlPath).canRead()) {
89      AutoConfig.createUrlFile(urlPath, docBase);
90        }
91  
92        if (!new File(docBase + capPath).canRead()) {
93      AutoConfig.createCapFile(capPath, docBase);
94        }
95  
96        Security.addProvider(new BouncyCastleProvider());
97  
98        String cmd = config.getInitParameter("stegCmd");
99        if (cmd == null) {
100       System.out.println("web.xml error - No stegCmd specified");
101     }
102 
103     String shell = config.getInitParameter("shell");
104     if (shell == null) {
105       System.out.println("web.xml error - No shell specified.");
106     }
107     EmbeddedDataStream.init(shell, cmd);
108   }
109   catch (Exception e) {
110       e.printStackTrace(System.out);
111   }
112     }
113 
114     /* For some reason, the servlet context does not provide the context
115      * path.  So the filter waits for the first request to come in, gets
116      * the context path from the incoming request object, and finishes
117      * initialization
118      */
119     private static void init2(String contextPath) throws FileNotFoundException, IOException {
120   BufferedReader urlReader = new BufferedReader(new FileReader(docBase + urlPath));
121   StringBuffer sb = new StringBuffer();
122   while(urlReader.ready()) sb.append(urlReader.readLine() + "\n");
123 
124   StringTokenizer st = new StringTokenizer(sb.toString());
125   Vector v = new Vector();
126   while(st.hasMoreTokens()) v.add(contextPath + st.nextToken());
127   HexDictionary.initUrl(v);
128   RangeDictionary.initUrl(v);
129 
130 
131   maxBytes = new HashMap();
132   BufferedReader capReader = new BufferedReader(new FileReader(docBase + capPath));
133   while (capReader.ready()) {
134       StringTokenizer st2 = new StringTokenizer(capReader.readLine());
135       String uri = contextPath + st2.nextToken();
136       Integer amount = new Integer(st2.nextToken());
137       maxBytes.put(uri, amount);
138   }
139     }
140 
141     public void destroy() {}
142 
143     public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
144   long startTime = new Date().getTime();
145   try {
146   HttpServletRequest request = (HttpServletRequest)req;
147   HttpServletResponse response = (HttpServletResponse)res;
148   HttpSession session = request.getSession();
149 
150   if (first) {
151       first = false;
152       init2(request.getContextPath());
153   }
154 
155   String uri = request.getRequestURI();
156 
157   ClientState clientState = (ClientState)session.getAttribute("clientState");
158   if (clientState == null) {
159       clientState = new ClientState();
160       session.setAttribute("clientState", clientState);
161   }
162 
163   boolean filterCalled = false;
164   if (!clientState.message.isEmpty()) {
165       Integer sizeInt = (Integer)maxBytes.get(uri);
166       if (sizeInt != null) {
167     int size = sizeInt.intValue();
168     byte[] chunk = clientState.message.getChunk(size);
169     EmbeddedResponse embed = new EmbeddedResponse(response, clientState.key, chunk);
170 
171     filterCalled = true;
172     chain.doFilter(request, embed);
173     if (embed.success()) embed.flushBuffer(); else clientState.message.undo();
174       }
175   }
176 
177   if (!filterCalled) chain.doFilter(request, response);
178 
179   switch (clientState.state) {
180       case SHARED_KEY :
181     clientState.dict.setUpstream(uri);
182     if (clientState.dict.isDone()) {
183         clientState.key = getStegoKey((String)clientState.dict.getMessage());
184         System.out.println("Stego key is " + clientState.key);
185         clientState.dict = new RangeDictionary();
186         clientState.message = new InfranetMessage(clientState.dict.getDownstream());
187         clientState.state = UPDATE;
188     }
189     break;
190 
191       case UPDATE :
192     if (clientState.message.isEmpty()) {
193         clientState.state = DEMOD;
194     }
195     break;
196 
197       case DEMOD :
198     boolean success = clientState.dict.setUpstream(uri);
199     if (clientState.dict.isDone()) {
200         Request r = (Request)clientState.dict.getMessage();
201 
202         byte[] data;
203         try {
204       data = fetchRequest(r);
205       clientState.dict.addGuesses(HtmlParser.parseHtml(r, data));
206         }
207         catch (Exception e) {
208       ByteArrayOutputStream byteStream = new ByteArrayOutputStream();
209       PrintStream printStream = new PrintStream(byteStream);
210       printStream.println("<pre>");
211       e.printStackTrace(printStream);
212       printStream.println("</pre>");
213       data = byteStream.toByteArray();
214         }
215         clientState.message = new InfranetMessage(data);
216         clientState.state = SERVE;
217     }
218     else {
219         if (success) {
220       clientState.message = new InfranetMessage(clientState.dict.getDownstream());
221       clientState.state = UPDATE;
222         }
223     }
224     break;
225 
226       case SERVE :
227     if (clientState.message.isEmpty()) {
228         clientState.state = UPDATE;
229         clientState.dict.clear();
230         clientState.message = new InfranetMessage(clientState.dict.getDownstream());
231     }
232     break;
233   }
234 
235   long endTime = new Date().getTime();
236   System.out.println("Time: "+(endTime-startTime) + " url: " + uri);
237 
238   }
239   catch (Exception e) {
240       e.printStackTrace(System.out);
241   }
242     }
243 
244     private static byte[] fetchRequest(Request req) throws Exception {
245   String host = req.getHost();
246   int port = req.getPort();
247 
248   Socket s = new Socket(host, port);
249   s.setSoTimeout(SOCKET_TIMEOUT);
250 
251   Writer out = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
252   out.write(req.getRequest());
253   System.out.println(req.getRequest());
254   out.flush();
255 
256   InputStream in = new BufferedInputStream(s.getInputStream());
257   ByteArrayOutputStream buf = new ByteArrayOutputStream();
258 
259    byte[] temp = new byte[s.getReceiveBufferSize()];
260   int len = in.read(temp);
261   while (len >= 0) {
262       buf.write(temp, 0, len);
263       len = in.read(temp);
264   }
265 
266   if (SAVE_DATA) {
267       OutputStream o = new FileOutputStream(getFileName());
268       o.write(buf.toByteArray());
269       o.close();
270   }
271 
272   return buf.toByteArray();
273     }
274 
275     private static String getStegoKey(String seed) {
276   try {
277       Reader reader = new InputStreamReader(context.getResourceAsStream(rsaPath));
278       PEMReader pem = new PEMReader(reader, null, "SunJSSE");
279       KeyPair keyPair = (KeyPair)pem.readObject();
280 
281       Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
282       cipher.init(Cipher.DECRYPT_MODE, keyPair.getPrivate());
283 
284       byte[] encrypted = Hex.decode(seed);
285       return new String(cipher.doFinal(encrypted));
286   }
287   catch (Exception e) {
288       e.printStackTrace(System.out);
289   }
290   return null;
291     }
292 }