diff app/src/main/java/net/sourceforge/jsocks/server/Ident.java @ 438:d29cce60f393

migrate from Eclipse to Android Studio
author Carl Byington <carl@five-ten-sg.com>
date Thu, 03 Dec 2015 11:23:55 -0800
parents src/net/sourceforge/jsocks/server/Ident.java@72de889ecfe7
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/app/src/main/java/net/sourceforge/jsocks/server/Ident.java	Thu Dec 03 11:23:55 2015 -0800
@@ -0,0 +1,158 @@
+package net.sourceforge.jsocks.server;
+import net.sourceforge.jsocks.*;
+import java.net.*;
+import java.io.*;
+import java.util.StringTokenizer;
+
+/**
+ Class Ident provides means to obtain user name of the owner of the socket 
+ on remote machine, providing remote machine runs identd daemon.
+ <p>
+ To use it:
+   <tt><pre>
+   Socket s = ss.accept();
+   Ident id = new Ident(s);
+   if(id.successful) goUseUser(id.userName);
+   else handleIdentError(id.errorCode,id.errorMessage)
+   </pre></tt>
+*/
+public class Ident{
+
+    /** Error Message can be null.*/
+    public String errorMessage;
+    /** Host type as returned by daemon, can be null, if error happened*/
+    public String hostType;
+    /** User name as returned by the identd daemon, or null, if it failed*/
+    public String userName;
+
+    /** If this is true then userName and hostType contain valid values.
+        Else errorCode contain the error code, and errorMessage contains
+        the corresponding message.
+    */
+    public boolean successful;
+    /** Error code*/
+    public int errorCode;
+    /** Identd on port 113 can't be contacted*/
+    public static final int ERR_NO_CONNECT = 1;
+    /** Connection timed out*/
+    public static final int ERR_TIMEOUT = 2;
+    /** Identd daemon responded with ERROR, in this case errorMessage
+        contains the string explanation, as send by the daemon.
+    */
+    public static final int ERR_PROTOCOL = 3;
+    /**
+     When parsing server response protocol error happened.
+    */
+    public static final int ERR_PROTOCOL_INCORRECT = 4;
+
+
+    /** Maximum amount of time we should wait before dropping the
+      connection to identd server.Setting it to 0 implies infinit
+      timeout.
+    */
+    public static final int connectionTimeout = 10000;
+    
+
+    /**
+     Constructor tries to connect to Identd daemon on the host of the
+     given socket, and retrieve user name of the owner of given socket 
+     connection on remote machine. After constructor returns public
+     fields are initialised to whatever the server returned.
+     <p>
+     If user name was successfully retrieved successful is set to true,
+     and userName and hostType are set to whatever server returned. If
+     however for some reason user name was not obtained, successful is set
+     to false and errorCode contains the code explaining the reason of
+     failure, and errorMessage contains human readable explanation.
+     <p>
+     Constructor may block, for a while.
+     @param s Socket whose ownership on remote end should be obtained.
+    */
+    public Ident(Socket s ){
+      Socket sock = null;
+      successful = false; //We are pessimistic
+
+      try{
+        sock = new Socket(s.getInetAddress(),113);
+        sock.setSoTimeout(connectionTimeout);
+        byte[] request = (""+s.getPort()+" , "+
+                             s.getLocalPort()+"\r\n").getBytes();
+
+        sock.getOutputStream().write(request);
+
+        BufferedReader in = new BufferedReader(
+                            new InputStreamReader(sock.getInputStream()));
+
+        parseResponse(in.readLine());
+
+      }catch(InterruptedIOException iioe){
+        errorCode = ERR_TIMEOUT;
+        errorMessage = "Connection to identd timed out.";
+      }catch(ConnectException ce){
+        errorCode = ERR_NO_CONNECT;
+        errorMessage = "Connection to identd server failed.";
+
+      }catch(IOException ioe){
+        errorCode = ERR_NO_CONNECT;
+        errorMessage = ""+ioe;
+      }finally{
+        try{ if(sock!=null) sock.close();}catch(IOException ioe){};
+      }
+    }
+
+    private void parseResponse(String response){
+      if(response == null){
+         errorCode = ERR_PROTOCOL_INCORRECT;
+         errorMessage = "Identd server closed connection.";
+         return;
+      }
+
+      StringTokenizer st = new StringTokenizer(response,":");
+      if(st.countTokens() < 3){
+         errorCode = ERR_PROTOCOL_INCORRECT;
+         errorMessage = "Can't parse server response.";
+         return;
+      }
+
+      st.nextToken(); //Discard first token, it's basically what we have send
+      String command = st.nextToken().trim().toUpperCase();
+
+      if(command.equals("USERID") && st.countTokens() >= 2){
+        successful = true;
+        hostType = st.nextToken().trim();
+        userName = st.nextToken("").substring(1);//Get all that is left
+      }else if(command.equals("ERROR")){
+        errorCode = ERR_PROTOCOL;
+        errorMessage = st.nextToken();
+      }else{
+        errorCode = ERR_PROTOCOL_INCORRECT;
+        System.out.println("Opa!");
+        errorMessage = "Can't parse server response.";
+      }
+
+
+    }
+
+///////////////////////////////////////////////
+//USED for Testing
+/*
+    public static void main(String[] args) throws IOException{
+
+       Socket s = null;
+       s = new Socket("gp101-16", 1391);
+
+       Ident id = new Ident(s);
+       if(id.successful){
+         System.out.println("User: "+id.userName);
+         System.out.println("HostType: "+id.hostType);
+       }else{
+         System.out.println("ErrorCode: "+id.errorCode);
+         System.out.println("ErrorMessage: "+id.errorMessage);
+
+       }
+
+       if(s!= null) s.close();
+    }
+//*/
+
+}