/*
 *  © Darren McDonald 2010
 *
 *  This file is part of athena-ssl-cipher-check.
 *
 *  athena-ssl-cipher-check 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 3 of the License,
 *  or (at your option) any later version.
 *
 *  athena-ssl-cipher-check 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 athena-ssl-cipher-check. If not, see
 *  <http://www.gnu.org/licenses/>.
 *
 */

package athenasslciphercheck;

import java.lang.reflect.Proxy;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.text.SimpleDateFormat;
import java.util.Calendar;

/**
 *
 * @author ID-11T
 */
public class Main {
    public static void main(String[] args)
    {
        System.out.println( "Athena SSL Cipher Check, v"+Settings.VERSION+", Copyright © 2010 Darren McDonald\n"+
                            "This program comes with ABSOLUTELY NO WARRANTY. This is free\n"+
                            "software, and you are welcome to redistribute it under certain\n"+
                            "conditions. See the LICENSE file for details." );
        System.out.println("Send bugs and details of unknown ciphers to athena@dmcdonald.net");

        if( args.length == 1 && args[0].equals("--gui") ) //GUI
        {
            //Im not sure if I'll ever bother implimenting a GUI,
            System.out.println("Real men use a CLI");
        }
        else //command line
        {

            if( args.length == 0)
            {
                printUsage();
                return;
            }

            Settings settings;
            if( ( settings = parseCommandLine( args ) ) == null )
            {
                printUsage();
                return;
            }

            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            String date = sdf.format( Calendar.getInstance().getTime());

            if( !settings.getClient() )
            {
                connection.settings = settings;
        
                System.out.println( "" );
                System.out.println( "Scanning " + settings.getHost() + ":" + settings.getPort() + " at " + date );
                System.out.println( "" );
                
                System.out.println("SSLv2 Ciphers");
                ssl2CipherCheck ssl2 = new ssl2CipherCheck();
                ssl2.check();

                tlsHeuristics tls = new tlsHeuristics( settings );
                tls.checkTlsCiphers();
            }
            else
            {
                System.out.println( "" );
                System.out.println( "Listening on port 0.0.0.0:" + settings.getPort() + " for an incoming SSL connection, " + date );
                ClientCheck tmp = new ClientCheck( settings.getPort() );
            }

            if( settings.getLazy() )
            {
                System.out.println( Results.getLazy() );
            }

            if( Results.getCount() == 0 && !settings.getClient() )
            {
                System.out.println("");
                System.out.println("No SSLv3/TLSv1 results? Try --safe mode. See --help for details.");
            }
        }
    }

    public static Settings parseCommandLine( String[] args )
    {
        Settings set = new Settings();
        set.setThrottle(0);
        set.setTimeout(5000);
        set.setBasicAuth("");
        set.setRetrys(3);
        set.setClient(false);

        String host = "";
        String port = "";

        int pType = Settings.DIRECT;
        String pHost = "";
        String pPort = "";

        for( int i = 0; i < args.length; i++ )
        {
            if( args[i].charAt(0) == '-' )
            {
                if( args[i].equals("--proxy") )
                {
                    if( i+1 < args.length )
                    {
                        if( args[i+1].equalsIgnoreCase("HTTP") )
                        {
                            pType = Settings.HTTP;
                        }
                        else if( args[i+1].equalsIgnoreCase("DIRECT") )
                        {
                            pType = Settings.DIRECT;
                        }
                        else 
                            return null;
                    }
                    else
                        return null;
                    i++;
                }
                else if( args[i].equals("--phost") )
                {
                    if( i+1 < args.length )
                    {
                        pHost = args[i+1];
                    }
                    else
                        return null;
                    i++;
                }
                else if( args[i].equals("--pport") )
                {
                    if( i+1 < args.length )
                    {
                        pPort = args[i+1];
                    }
                    else
                        return null;
                    i++;
                }
                else if( args[i].equals("--timeout") ||
                         args[i].equals("-t") )
                {
                    if( i+1 < args.length )
                    {
                        if( Integer.parseInt( args[i+1] ) < 1 )
                            return null;

                        set.setTimeout( Integer.parseInt( args[i+1] ) );                        
                    }
                    else
                        return null;
                    i++;
                }
                else if( args[i].equals("--delay") ||
                         args[i].equals("-d") )
                {
                    if( i+1 < args.length )
                    {
                        if( Integer.parseInt( args[i+1] ) < 0 )
                            return null;

                        set.setThrottle( Integer.parseInt( args[i+1] ) );
                    }
                    else
                        return null;
                    i++;
                }
                else if( args[i].equals("--retrys") || args[i].equals("-r") )
                {
                    if( i+1 < args.length )
                    {
                        set.setRetrys(i);
                    }
                    else
                        return null;
                    i++;
                }
                else if( args[i].equals("--client") || args[i].equals("-c") )
                {
                    set.setClient(true);
                }
                else if( args[i].equals("--basicauth") )
                {
                    if( i+1 < args.length )
                    {                        
                        set.setBasicAuth(args[i+1]);
                    }
                    else
                        return null;
                    i++;
                }
                else if( args[i].equals("--help") )
                {
                    printHelp();
                    return null;
                }
                else if( args[i].equals("-l") ||  args[i].equals("--lazy"))
                {
                    set.setLazy();
                }
                else if( args[i].equals("-s") ||  args[i].equals("--safe"))
                {
                    set.setSafe();
                }
            }
            else
            {
                if( host.length() == 0 )
                {
                    if( set.getClient() == true )
                    {
                        port = args[i];
                        Results.setPort(port);
                    }
                    else
                    {
                        host = args[i];
                        Results.setHost(host);
                    }
                }
                else if( port.length() == 0 )
                {
                    port = args[i];
                    Results.setPort(port);
                }
                else
                    return null;
            }
        }

        //Error Checking
        if( port.length() == 0 )
            return null;

        try
        {
            set.setPort( Integer.parseInt(port) );
        }
        catch( NumberFormatException ex )
        {
            return null;
        }

        if( set.getClient() == false )
        {
            set.setHost(host);
        }

        //Error Checking for Proxy Settings
        if( pType != Settings.DIRECT )
        {
            if( pHost.length() == 0 || pPort.length() == 0 || Integer.parseInt(pPort)  < 1 )
                return null;

            set.setProxyHost( pHost );
            set.setProxyPort( Integer.parseInt(pPort ) );
            set.setProxyType( pType );
        }

        return set;
    }

    public static void printUsage()
    {
            System.out.println();
            System.out.println("Basic Usage : java -jar athena-ssl-cipher-check [ip] [port]");
            System.out.println("         or : java -jar athena-ssl-cipher-check --client [port]");
            System.out.println("         or : java -jar athena-ssl-cipher-check --help");
    }

    public static void printHelp()
    {
        System.out.println();
        System.out.println("athena-ssl-cipher-check [options] [ip | hostname] [port] ");

        System.out.println("");
        System.out.println("Timing Opitons");
        System.out.println("         --timeout, -t [milliseconds]");
        System.out.println("                 Specify how long a request should wait for a reply");
        System.out.println("                 Default: 5000");
        System.out.println("         --delay, -d [milliseconds]");
        System.out.println("                 Specify how long to sleep for between sending requests");
        System.out.println("                 Default: 0");
        System.out.println("         --retrys, -r [retrys]");
        System.out.println("                 Specifies how many retrys the system will perform");
        System.out.println("                 Default: 3");
        System.out.println("         --safe, -s");
        System.out.println("                 Safe mode, sends cipher lists in smaller chunks which");
        System.out.println("                 is required by some SSL services written by developers");
        System.out.println("                 who havnt actually read any of the RFCs. If your results");
        System.out.println("                 come back without any SSlv3/TLS ciphers, try this mode.");
        System.out.println("                 This mode is slower than a normal scan.");

        System.out.println("");
        System.out.println("Proxy Support - Required Options");
        System.out.println("         --proxy [proxy type]");
        System.out.println("                 Supported Options: HTTP");
        System.out.println("         --phost [proxy ip/host]");
        System.out.println("         --pport [proxy port]");

        System.out.println("");
        System.out.println("Proxy Support - Authentication Options");
        System.out.println("         --basicauth [username:password] | *");
        System.out.println("                 * for interactive login");

        System.out.println("");
        System.out.println("Client Cipher Check");
        System.out.println("         --client, -c [port]");
        System.out.println("                 If client mode is used all other options will be ignored");

        System.out.println("");
        System.out.println("Output Options");
        System.out.println("         --lazy, -l");
        System.out.println("                 Lazy Consultant Mode, lists any ciphers which should be");
        System.out.println("                 disabled by issue. This is based on my understanding and");
        System.out.println("                 opinion. I could be completly wrong.");
    }
}
