def get_options(mods):
    parser = OptionParser(option_class=eng_option, conflict_handler="resolve")
    parser.add_option("-m", "--modulation", type="choice", choices=mods.keys(),
                      default='psk',
                      help="Select modulation from: %s [default=%%default]"
                            % (', '.join(mods.keys()),))
    parser.add_option("", "--amplitude", type="eng_float", default=0.2,
                      help="set Tx amplitude (0-1) (default=%default)")
    parser.add_option("-r", "--bitrate", type="eng_float", default=250e3,
                      help="Select modulation bit rate (default=%default)")
    parser.add_option("-S", "--samples-per-symbol", type="float", default=2,
                      help="set samples/symbol [default=%default]")
    parser.add_option("","--to-file", default=None,
                      help="Output file for modulated samples")
    if not parser.has_option("--verbose"):
        parser.add_option("-v", "--verbose", action="store_true", default=False)
    if not parser.has_option("--log"):
        parser.add_option("", "--log", action="store_true", default=False)

    uhd_transmitter.add_options(parser)

    for mod in mods.values():
        mod.add_options(parser)
		      
    (options, args) = parser.parse_args()
    if len(args) != 0:
        parser.print_help()
        sys.exit(1)
	
    return (options, args)
Пример #2
0
def get_options(demods):
    parser = OptionParser(option_class=eng_option, conflict_handler="resolve")
    parser.add_option("","--from-file", default=None,
                      help="input file of samples to demod")
    parser.add_option("-m", "--modulation", type="choice", choices=demods.keys(), 
                      default='psk',
                      help="Select modulation from: %s [default=%%default]"
                            % (', '.join(demods.keys()),))
    parser.add_option("-r", "--bitrate", type="eng_float", default=250e3,
                      help="Select modulation bit rate (default=%default)")
    parser.add_option("-S", "--samples-per-symbol", type="float", default=2,
                      help="set samples/symbol [default=%default]")
    if not parser.has_option("--verbose"):
        parser.add_option("-v", "--verbose", action="store_true", default=False)
    if not parser.has_option("--log"):
        parser.add_option("", "--log", action="store_true", default=False,
                      help="Log all parts of flow graph to files (CAUTION: lots of data)")

    uhd_receiver.add_options(parser)

    demods = digital.modulation_utils.type_1_demods()
    for mod in demods.values():
        mod.add_options(parser)
		      
    (options, args) = parser.parse_args()
    if len(args) != 0:
        parser.print_help()
        sys.exit(1)
	
    return (options, args)
Пример #3
0
def get_options(demods):
    parser = OptionParser(option_class=eng_option, conflict_handler="resolve")
    parser.add_option("", "--from-file", default=None,
                      help="input file of samples to demod")
    parser.add_option("-m", "--modulation", type="choice", choices=list(demods.keys()),
                      default='psk',
                      help="Select modulation from: %s [default=%%default]"
                            % (', '.join(list(demods.keys())),))
    parser.add_option("-r", "--bitrate", type="eng_float", default=250e3,
                      help="Select modulation bit rate (default=%default)")
    parser.add_option("-S", "--samples-per-symbol", type="float", default=2,
                      help="set samples/symbol [default=%default]")
    if not parser.has_option("--verbose"):
        parser.add_option("-v", "--verbose",
                          action="store_true", default=False)
    if not parser.has_option("--log"):
        parser.add_option("", "--log", action="store_true", default=False,
                          help="Log all parts of flow graph to files (CAUTION: lots of data)")

    uhd_receiver.add_options(parser)

    demods = digital.modulation_utils.type_1_demods()
    for mod in list(demods.values()):
        mod.add_options(parser)

    (options, args) = parser.parse_args()
    if len(args) != 0:
        parser.print_help()
        sys.exit(1)

    return (options, args)
Пример #4
0
def get_options(mods):
    parser = OptionParser(option_class=eng_option, conflict_handler="resolve")
    parser.add_option("-m", "--modulation", type="choice", choices=mods.keys(),
                      default='psk',
                      help="Select modulation from: %s [default=%%default]"
                            % (', '.join(mods.keys()),))
    parser.add_option("", "--amplitude", type="eng_float", default=0.2,
                      help="set Tx amplitude (0-1) (default=%default)")
    parser.add_option("-r", "--bitrate", type="eng_float", default=250e3,
                      help="Select modulation bit rate (default=%default)")
    parser.add_option("-S", "--samples-per-symbol", type="float", default=2,
                      help="set samples/symbol [default=%default]")
    parser.add_option("","--to-file", default=None,
                      help="Output file for modulated samples")
    if not parser.has_option("--verbose"):
        parser.add_option("-v", "--verbose", action="store_true", default=False)
    if not parser.has_option("--log"):
        parser.add_option("", "--log", action="store_true", default=False)

    uhd_transmitter.add_options(parser)

    for mod in mods.values():
        mod.add_options(parser)
		      
    (options, args) = parser.parse_args()
    if len(args) != 0:
        parser.print_help()
        sys.exit(1)
	
    return (options, args)
Пример #5
0
 def test_option(self):
     parser = OptionParser()
     self.pi.options( parser, env={} )
     self.assertEqual( parser.has_option( '--xml' ), True )
     self.assertEqual( parser.has_option( '--xml-formatter' ), True )
     opt = parser.get_option( '--xml' )
     self.assertEqual( opt.action, 'store_true' )
     self.assertEqual( opt.default, False )
     opt = parser.get_option( '--xml-formatter' )
     self.assertEqual( opt.action, 'store' )
     self.assertEqual( opt.default, 'nosexml.PrettyPrintFormatter' )
 def test_classic_migration_options(self):
     parser = OptionParser()
     migrate.add_parser_options(parser)
     self.assertFalse(parser.has_option("--registration-state"))
     self.assertTrue(parser.has_option("--org"))
     self.assertTrue(parser.has_option("--environment"))
     self.assertTrue(parser.has_option("--force"))
     (opts, args) = parser.parse_args([])
     migrate.set_defaults(opts, five_to_six_script=False)
     self.assertFalse(opts.five_to_six)
     self.assertEquals("purge", opts.registration_state)
Пример #7
0
 def test_classic_migration_options(self):
     parser = OptionParser()
     migrate.add_parser_options(parser)
     self.assertFalse(parser.has_option("--registration-state"))
     self.assertTrue(parser.has_option("--org"))
     self.assertTrue(parser.has_option("--environment"))
     self.assertTrue(parser.has_option("--force"))
     (opts, args) = parser.parse_args([])
     migrate.set_defaults(opts, five_to_six_script=False)
     self.assertFalse(opts.five_to_six)
     self.assertEquals("purge", opts.registration_state)
Пример #8
0
    def testAddConfigManagementToParser(self):

        parser = OptionParser()
        sampleFunction.addConfigToParser(parser)

        self.assertTrue(parser.has_option('-c'))
        self.assertTrue(parser.has_option('--config'))

        parser.parse_args(args=['-c', self.configFile])

        self.assertTrue(isinstance(parser.config, mc.Configuration))
Пример #9
0
class TestOptionParser(BaseTest):
    def setUp(self):
        self.parser = OptionParser()
        self.parser.add_option("-v", "--verbose", "-n", "--noisy",
                          action="store_true", dest="verbose")
        self.parser.add_option("-q", "--quiet", "--silent",
                          action="store_false", dest="verbose")

    def test_add_option_no_Option(self):
        self.assertTypeError(self.parser.add_option,
                             "not an Option instance: None", None)

    def test_add_option_invalid_arguments(self):
        self.assertTypeError(self.parser.add_option,
                             "invalid arguments", None, None)

    def test_get_option(self):
        opt1 = self.parser.get_option("-v")
        self.assert_(isinstance(opt1, Option))
        self.assertEqual(opt1._short_opts, ["-v", "-n"])
        self.assertEqual(opt1._long_opts, ["--verbose", "--noisy"])
        self.assertEqual(opt1.action, "store_true")
        self.assertEqual(opt1.dest, "verbose")

    def test_get_option_equals(self):
        opt1 = self.parser.get_option("-v")
        opt2 = self.parser.get_option("--verbose")
        opt3 = self.parser.get_option("-n")
        opt4 = self.parser.get_option("--noisy")
        self.assert_(opt1 is opt2 is opt3 is opt4)

    def test_has_option(self):
        self.assert_(self.parser.has_option("-v"))
        self.assert_(self.parser.has_option("--verbose"))

    def assert_removed(self):
        self.assert_(self.parser.get_option("-v") is None)
        self.assert_(self.parser.get_option("--verbose") is None)
        self.assert_(self.parser.get_option("-n") is None)
        self.assert_(self.parser.get_option("--noisy") is None)

        self.failIf(self.parser.has_option("-v"))
        self.failIf(self.parser.has_option("--verbose"))
        self.failIf(self.parser.has_option("-n"))
        self.failIf(self.parser.has_option("--noisy"))

        self.assert_(self.parser.has_option("-q"))
        self.assert_(self.parser.has_option("--silent"))

    def test_remove_short_opt(self):
        self.parser.remove_option("-n")
        self.assert_removed()

    def test_remove_long_opt(self):
        self.parser.remove_option("--verbose")
        self.assert_removed()

    def test_remove_nonexistent(self):
        self.assertRaises(self.parser.remove_option, ValueError,
                          "no such option 'foo'", funcargs=['foo'])
 def test_5to6_options(self):
     five_to_six = True
     parser = OptionParser()
     migrate.add_parser_options(parser, five_to_six)
     self.assertTrue(parser.has_option("--registration-state"))
     self.assertFalse(parser.has_option("--org"))
     self.assertFalse(parser.has_option("--environment"))
     self.assertFalse(parser.has_option("--force"))
     (opts, args) = parser.parse_args([])
     migrate.set_defaults(opts, five_to_six)
     self.assertTrue(opts.five_to_six)
     self.assertEquals(None, opts.org)
     self.assertEquals(None, opts.environment)
     self.assertTrue(opts.force)
Пример #11
0
 def test_5to6_options(self):
     five_to_six = True
     parser = OptionParser()
     migrate.add_parser_options(parser, five_to_six)
     self.assertTrue(parser.has_option("--registration-state"))
     self.assertFalse(parser.has_option("--org"))
     self.assertFalse(parser.has_option("--environment"))
     self.assertFalse(parser.has_option("--force"))
     (opts, args) = parser.parse_args([])
     migrate.set_defaults(opts, five_to_six)
     self.assertTrue(opts.five_to_six)
     self.assertEquals(None, opts.org)
     self.assertEquals(None, opts.environment)
     self.assertTrue(opts.force)
Пример #12
0
def main(allowed_options=None, description=None, usage=None):
    from os import getcwd
    from sys import argv
    from optparse import OptionParser
    from rabbitvcs.util.helper import get_common_directory
    
    parser = OptionParser(usage=usage, description=description)
    
    if allowed_options:
        for (option_args, option_kwargs) in allowed_options:
            parser.add_option(*option_args, **option_kwargs)
        
    (options, args) = parser.parse_args(argv)
    
    # Convert "." to current working directory
    paths = args[1:]
    for i in range(0, len(paths)):
        if paths[i] == ".":
            paths[i] = getcwd()
        
    if not paths:
        paths = [getcwd()]
        
    if parser.has_option("--base-dir") and not options.base_dir: 
        options.base_dir = get_common_directory(paths)
        
    return (options, paths)
Пример #13
0
def main(allowed_options=None, description=None, usage=None):
    from os import getcwd
    from sys import argv
    from optparse import OptionParser
    from rabbitvcs.util.helper import get_common_directory
    
    parser = OptionParser(usage=usage, description=description)
    
    if allowed_options:
        for (option_args, option_kwargs) in allowed_options:
            parser.add_option(*option_args, **option_kwargs)
        
    (options, args) = parser.parse_args(argv)
    
    # Convert "." to current working directory
    paths = args[1:]
    for i in range(0, len(paths)):
        if paths[i] == ".":
            paths[i] = getcwd()
        
    if not paths:
        paths = [getcwd()]
        
    if parser.has_option("--base-dir") and not options.base_dir: 
        options.base_dir = get_common_directory(paths)
        
    return (options, paths)
Пример #14
0
def main():
    """ Parser Options """
    parser = OptionParser (option_class=eng_option)
    MimoMPIF.add_parser_options (parser)
    if not parser.has_option("--phy-addr"):
        parser.add_option("", "--phy-addr", type="string", default="0.0.0.0", \
                help="set address for PHY [default=%default]")
    (options, args) = parser.parse_args ()
    if len(args)!=0:
        parser.print_help()
        sys.exit(1)

    global RATE_LIMIT
    if   (options.nchannels == 4): RATE_LIMIT = 32
    elif (options.nchannels == 2): RATE_LIMIT = 16
    elif (options.nchannels == 1): RATE_LIMIT = 8

    mac = mimo.mac(options.phy_addr, options.mac_port)
    mac.start()

    #f = FuncThread(send_data, "tx-data", mac)
    f = FuncThread(send_80211data, "tx-data", mac)
    f.setDaemon(1)
    g = FuncThread(recv_data, "rx-data", mac)
    g.setDaemon(1)
    h = FuncThread(recv_ctrl, "rx-ctrl", mac)
    h.setDaemon(1)

    for x in [f,g,h]: x.start()
    #for x in [g,h]: x.start()

    raw_input("Press Enter to quit:\n")
    mac.shutdown()

    p = persist()  # start a persitent thread
Пример #15
0
    def testDumpDefault(self):
        parser = OptionParser()
        sampleFunction.addConfigToParser(parser)

        self.assertTrue(parser.has_option('-d'))
        self.assertTrue(parser.has_option('--dump'))

        dumpfile = open(self.dumpFile, 'w')
        sys.stdout = dumpfile

        self.assertRaises(SystemExit, parser.parse_args, args=['-d'])

        sys.stdout = self.stdout
        dumpfile.close()

        self.assertEquals(sampleFunction.loadConfig(self.dumpFile),
                          sampleFunction.defaults)
Пример #16
0
    def testPopulateParser(self):

        parser = OptionParser()
        sampleFunction2.populateParser(parser)

        self.assertTrue(parser.has_option('-d'))
        self.assertTrue(parser.has_option('--dump'))

        dumpfile = open(self.dumpFile, 'w')
        sys.stdout = dumpfile

        self.assertRaises(SystemExit, parser.parse_args, args=['-d'])

        sys.stdout = self.stdout
        dumpfile.close()

        self.assertEquals(sampleFunction.loadConfig(self.dumpFile),
                          sampleFunction.defaults)

        argstring = '-x 3 -y 2.66 --func eval2 --cat mytest.cat --verbose False'

        self.assertTrue(parser.has_option('--cat'))
        self.assertTrue(parser.has_option('-v'))
        self.assertTrue(parser.has_option('--verbpse'))
Пример #17
0
def get_options():
    parser = OptionParser(option_class=eng_option, conflict_handler="resolve")

    parser.add_option("-n",
                      "--nbr-values",
                      type="int",
                      default=5,
                      help="number of values [default=%default]")

    parser.add_option(
        "-a",
        "--alpha",
        type="float",
        default=0.1,
        help="set alpha or P1/P: relation between P1 and P2 [default=%default]"
    )

    parser.add_option(
        "-s",
        "--snr",
        type="float",
        default=10,
        help="SNR or P/sigma^2 (dB) of a generated carrierr [default=%default]"
    )

    #     parser.add_option("-f", "--to-file", default=None,
    #                       help="File to save results of simulations")
    #     parser.add_option("","--from-file", default=None,
    #                       help="input file of samples to demod")
    #
    if not parser.has_option("--log"):
        parser.add_option(
            "",
            "--log",
            action="store_true",
            default=False,
            help="Log all parts of flow graph to files (CAUTION: lots of data)"
        )

    (options, args) = parser.parse_args()
    if len(args) != 0:
        parser.print_help()
        sys.exit(1)

    return (options, args)
Пример #18
0
def main():
    parser = OptionParser(usage='usage: %prog [options] ...',
                          version='%%prog %s' % VERSION)

    if os.name == 'posix':
        parser.add_option('-d',
                          '--daemonize',
                          action='store_true',
                          dest='daemonize',
                          help='run in the background as a daemon')
        parser.add_option('--pidfile',
                          action='store',
                          dest='pidfile',
                          help='when daemonizing, file to which to write pid')

    options, args = parser.parse_args()

    if options.daemonize and options.autoreload:
        parser.error('the --auto-reload option cannot be used with '
                     '--daemonize')

    if parser.has_option('pidfile') and options.pidfile:
        options.pidfile = os.path.abspath(options.pidfile)

    q = queue.Queue()

    opt = Options('default.conf')
    manager = PluginManager(opt, q)
    manager.run()

    try:
        if options.daemonize:
            daemonize(pidfile=options.pidfile, progname='opcua_plugin')

    except OSError as e:
        print("%s: %s" % (e.__class__.__name__, e), file=sys.stderr)
        sys.exit(1)
    except KeyboardInterrupt:
        pass
Пример #19
0
def main():
    usage_str="usage: %prog [options] file list ..."
    parser = OptionParser(usage=usage_str)
    parser.add_option("-f", "--field_num", dest="field_num", default=1,
                      help="specify the field number", metavar="FIELD_NUM")
    parser.add_option("-z", action="store_true", dest="zero",
                      help="set 0 for undefined value")
    (options, args) = parser.parse_args()
    # 'field_num' is specified in the range from 0(key) to 1, 2, ...(values)
    field_num = 1
    default_value = ""
    if (options.field_num):
        field_num = int(options.field_num)
    if (parser.has_option("zero")):
        default_value = 0
    files = args
    
    result= {}
    num_files = len(files)
    for i in range(num_files):
        fp = open(files[i])
        for line in fp:
            line = line.rstrip('\n')
            name_value_list = line.split('\t')
            name = name_value_list[0]
            if (len(name_value_list) > field_num):
                value = name_value_list[field_num]
            else:
                value = default_value
            if name[:2] == 'k.': continue
            if not result.has_key(name):
                result[name] = [ default_value for j in range(num_files) ]
            result[name][i] = value
        fp.close()

    for name in result.keys():
        print "%s\t%s"%(name, '\t'.join(map(str, result[name])))
Пример #20
0
class CommandLineParser():

    # Defines what --regular means
    REGULAR_CMD = ['sslv2', 'sslv3', 'tlsv1', 'tlsv1_1', 'tlsv1_2', 'reneg',
                   'resum', 'certinfo', 'http_get', 'hide_rejected_ciphers',
                   'compression', 'heartbleed']
    SSLYZE_USAGE = 'usage: %prog [options] target1.com target2.com:443 etc...'

    # StartTLS options
    START_TLS_PROTS = ['smtp', 'xmpp', 'pop3', 'ftp', 'imap', 'ldap', 'rdp', 'postgres', 'auto']
    START_TLS_USAGE = 'STARTTLS should be one of: ' + str(START_TLS_PROTS) +  \
        '. The \'auto\' option will cause SSLyze to deduce the protocol' + \
        ' (ftp, imap, etc.) from the supplied port number, for each target servers.'

    # Default values
    DEFAULT_RETRY_ATTEMPTS = 4
    DEFAULT_TIMEOUT = 5


    def __init__(self, available_plugins, sslyze_version):
        """
        Generates SSLyze's command line parser.
        """

        self._parser = OptionParser(version=sslyze_version,
                                    usage=self.SSLYZE_USAGE)

        # Add generic command line options to the parser
        self._add_default_options()

        # Add plugin-specific options to the parser
        self._add_plugin_options(available_plugins)

        # Add the --regular command line parameter as a shortcut if possible
        regular_help = 'Regular HTTPS scan; shortcut for'
        for cmd in self.REGULAR_CMD:
            regular_help += ' --' + cmd
            if cmd == 'certinfo': # gah
                regular_help += '=basic'

            if not self._parser.has_option('--' + cmd):
                return

        self._parser.add_option('--regular', action="store_true", dest=None,
                    help=regular_help)


    def parse_command_line(self):
        """
        Parses the command line used to launch SSLyze.
        """

        (args_command_list, args_target_list) = self._parser.parse_args()

        # Handle the --targets_in command line and fill args_target_list
        if args_command_list.targets_in:
            if args_target_list:
                raise CommandLineParsingError("Cannot use --targets_list and specify targets within the command line.")

            try: # Read targets from a file
                with open(args_command_list.targets_in) as f:
                    for target in f.readlines():
                        if target.strip(): # Ignore empty lines
                            if not target.startswith('#'): # Ignore comment lines
                                args_target_list.append(target.strip())
            except IOError:
                raise CommandLineParsingError("Can't read targets from input file '%s'." %  args_command_list.targets_in)

        if not args_target_list:
            raise CommandLineParsingError('No targets to scan.')

        # Handle the --regular command line parameter as a shortcut
        if self._parser.has_option('--regular'):
            if getattr(args_command_list, 'regular'):
                setattr(args_command_list, 'regular', False)
                for cmd in self.REGULAR_CMD:
                    if cmd=="certinfo":
                        # Allow user to override certinfo when using --regular
                        if getattr(args_command_list, 'certinfo') is None:
                            setattr(args_command_list, 'certinfo', 'basic') # Special case
                    else: 
                        setattr(args_command_list, cmd, True)

        # Create the shared_settings object from looking at the command line
        shared_settings = self._process_parsing_results(args_command_list)
        return args_command_list, args_target_list, shared_settings


    def _add_default_options(self):
        """
        Adds default command line options to the parser.
        """

        # Client certificate options
        clientcert_group = OptionGroup(self._parser,
            'Client certificate support', '')
        clientcert_group.add_option(
            '--cert',
            help='Client certificate filename.',
            dest='cert')
        clientcert_group.add_option(
            '--certform',
            help= 'Client certificate format. DER or PEM (default).',
            dest='certform',
            default='PEM')
        clientcert_group.add_option(
            '--key',
            help= 'Client private key filename.',
            dest='key')
        clientcert_group.add_option(
            '--keyform',
            help= 'Client private key format. DER or PEM (default).',
            dest='keyform',
            default='PEM')
        clientcert_group.add_option(
            '--pass',
            help= 'Client private key passphrase.',
            dest='keypass',
            default='')
        self._parser.add_option_group(clientcert_group)

        # XML output
        self._parser.add_option(
            '--xml_out',
            help='Writes the scan results as an XML document to the file XML_FILE.',
            dest='xml_file',
            default=None)

        # Read targets from input file
        self._parser.add_option(
            '--targets_in',
            help='Reads the list of targets to scan from the file TARGETS_IN. It should contain one host:port per line.',
            dest='targets_in',
            default=None)

        # Timeout
        self._parser.add_option(
            '--timeout',
            help= (
                'Sets the timeout value in seconds used for every socket '
                'connection made to the target server(s). Default is ' +
                str(self.DEFAULT_TIMEOUT) + 's.'),
            type='int',
            dest='timeout',
            default=self.DEFAULT_TIMEOUT)


        # Control connection retry attempts
        self._parser.add_option(
            '--nb_retries',
            help= (
                'Sets the number retry attempts for all network connections '
                'initiated throughout the scan. Increase this value if you are '
                'getting a lot of timeout/connection errors when scanning a '
                'specific server. Decrease this value to increase the speed '
                'of the scans; results may however return connection errors. '
                'Default is '
                + str(self.DEFAULT_RETRY_ATTEMPTS) + ' connection attempts.'),
            type='int',
            dest='nb_retries',
            default=self.DEFAULT_RETRY_ATTEMPTS)


        # HTTP CONNECT Proxy
        self._parser.add_option(
            '--https_tunnel',
            help= (
                'Tunnels all traffic to the target server(s) through an HTTP '
                'CONNECT proxy. HTTP_TUNNEL should be the proxy\'s URL: '
                '\'http://*****:*****@HOST:PORT/\'. For proxies requiring '
                'authentication, only Basic Authentication is supported.'),
            dest='https_tunnel',
            default=None)

        # STARTTLS
        self._parser.add_option(
            '--starttls',
            help= (
                'Performs StartTLS handshakes when connecting to the target '
                'server(s). ' + self.START_TLS_USAGE),
            dest='starttls',
            default=None)

        self._parser.add_option(
            '--xmpp_to',
            help= (
                'Optional setting for STARTTLS XMPP. '
                ' XMPP_TO should be the hostname to be put in the \'to\' attribute '
                'of the XMPP stream. Default is the server\'s hostname.'),
            dest='xmpp_to',
            default=None)

        # Server Name Indication
        self._parser.add_option(
            '--sni',
            help= (
                'Use Server Name Indication to specify the hostname to connect to.'
                ' Will only affect TLS 1.0+ connections.'),
            dest='sni',
            default=None)

    def _add_plugin_options(self, available_plugins):
        """
        Recovers the list of command line options implemented by the available
        plugins and adds them to the command line parser.
        """

        for plugin_class in available_plugins:
            plugin_desc = plugin_class.get_interface()

            # Add the current plugin's commands to the parser
            group = OptionGroup(self._parser, plugin_desc.title,
                                plugin_desc.description)
            for cmd in plugin_desc.get_commands():
                    group.add_option(cmd)

            # Add the current plugin's options to the parser
            for option in plugin_desc.get_options():
                    group.add_option(option)

            self._parser.add_option_group(group)


    def _process_parsing_results(self, args_command_list):
        """
        Performs various sanity checks on the command line that was used to
        launch SSLyze.
        Returns the shared_settings object to be fed to plugins.
        """

        shared_settings = {}
        # Sanity checks on the client cert options
        if bool(args_command_list.cert) ^ bool(args_command_list.key):
            raise CommandLineParsingError('No private key or certificate file were given. See --cert and --key.')

        # Private key and cert formats
        if args_command_list.certform == 'DER':
            args_command_list.certform = SSL_FILETYPE_ASN1
        elif args_command_list.certform == 'PEM':
            args_command_list.certform = SSL_FILETYPE_PEM
        else:
            raise CommandLineParsingError('--certform should be DER or PEM.')

        if args_command_list.keyform == 'DER':
            args_command_list.keyform = SSL_FILETYPE_ASN1
        elif args_command_list.keyform == 'PEM':
            args_command_list.keyform = SSL_FILETYPE_PEM
        else:
            raise CommandLineParsingError('--keyform should be DER or PEM.')

        # Let's try to open the cert and key files
        if args_command_list.cert:
            try:
                open(args_command_list.cert,"r")
            except:
                raise CommandLineParsingError('Could not open the client certificate file "' + str(args_command_list.cert) + '".')

        if args_command_list.key:
            try:
                open(args_command_list.key,"r")
            except:
                raise CommandLineParsingError('Could not open the client private key file "' + str(args_command_list.key) + '"')

            # Try to load the cert and key in OpenSSL
            try:
                sslClient = SslClient()
                sslClient.use_private_key(args_command_list.cert,
                                        args_command_list.certform,
                                        args_command_list.key,
                                        args_command_list.keyform,
                                        args_command_list.keypass)
            except _nassl.OpenSSLError as e:
                if 'bad decrypt' in str(e.args):
                    raise CommandLineParsingError('Could not decrypt the private key. Wrong passphrase ?')
                raise CommandLineParsingError('Could not load the certificate or the private key. Passphrase needed ?')



        # HTTP CONNECT proxy
        shared_settings['https_tunnel_host'] = None
        if args_command_list.https_tunnel:

            # Parse the proxy URL
            parsedUrl = urlparse(args_command_list.https_tunnel)

            if not parsedUrl.netloc:
                raise CommandLineParsingError(
                    'Invalid Proxy URL for --https_tunnel, discarding all tasks.')

            if parsedUrl.scheme in 'http':
               defaultPort = 80
            elif parsedUrl.scheme in 'https':
               defaultPort = 443
            else:
                raise CommandLineParsingError(
                    'Invalid URL scheme for --https_tunnel, discarding all tasks.')

            if not parsedUrl.hostname:
                raise CommandLineParsingError(
                    'Invalid Proxy URL for --https_tunnel, discarding all tasks.')

            try :
                shared_settings['https_tunnel_port'] = parsedUrl.port if parsedUrl.port else defaultPort
            except ValueError: # The supplied port was not a number
                raise CommandLineParsingError(
                    'Invalid Proxy URL for --https_tunnel, discarding all tasks.')

            shared_settings['https_tunnel_host'] = parsedUrl.hostname
            shared_settings['https_tunnel_user'] = parsedUrl.username
            shared_settings['https_tunnel_password'] = parsedUrl.password


        # STARTTLS
        if args_command_list.starttls:
            if args_command_list.starttls not in self.START_TLS_PROTS:
                raise CommandLineParsingError(self.START_TLS_USAGE)

        if args_command_list.starttls and args_command_list.https_tunnel:
            raise CommandLineParsingError(
                'Cannot have --https_tunnel and --starttls at the same time.')

        # Number of connection retries
        if args_command_list.nb_retries < 1:
            raise CommandLineParsingError(
                'Cannot have a number smaller than 1 for --nb_retries.')

        # All good, let's save the data
        for key, value in args_command_list.__dict__.iteritems():
            shared_settings[key] = value

        return shared_settings
Пример #21
0
class CommandLineParser(object):

    # Defines what --regular means
    REGULAR_CMD = [
        'sslv2', 'sslv3', 'tlsv1', 'tlsv1_1', 'tlsv1_2', 'tlsv1_3', 'reneg',
        'resum', 'certinfo', 'http_get', 'hide_rejected_ciphers',
        'compression', 'heartbleed', 'openssl_ccs', 'fallback', 'robot'
    ]
    SSLYZE_USAGE = 'usage: %prog [options] target1.com target2.com:443 target3.com:443{ip} etc...'

    # StartTLS options
    START_TLS_PROTOCOLS = [
        'smtp', 'xmpp', 'xmpp_server', 'pop3', 'ftp', 'imap', 'ldap', 'rdp',
        'postgres', 'auto'
    ]
    START_TLS_USAGE = 'StartTLS should be one of: {}. The \'auto\' option will cause SSLyze to deduce the protocol ' \
                      '(ftp, imap, etc.) from the supplied port number, ' \
                      'for each target servers.'.format(' , '.join(START_TLS_PROTOCOLS))

    # Mapping of StartTls protocols and ports; useful for starttls=auto
    STARTTLS_PROTOCOL_DICT = {
        'smtp': TlsWrappedProtocolEnum.STARTTLS_SMTP,
        587: TlsWrappedProtocolEnum.STARTTLS_SMTP,
        25: TlsWrappedProtocolEnum.STARTTLS_SMTP,
        'xmpp': TlsWrappedProtocolEnum.STARTTLS_XMPP,
        5222: TlsWrappedProtocolEnum.STARTTLS_XMPP,
        'xmpp_server': TlsWrappedProtocolEnum.STARTTLS_XMPP_SERVER,
        5269: TlsWrappedProtocolEnum.STARTTLS_XMPP_SERVER,
        'pop3': TlsWrappedProtocolEnum.STARTTLS_POP3,
        109: TlsWrappedProtocolEnum.STARTTLS_POP3,
        110: TlsWrappedProtocolEnum.STARTTLS_POP3,
        'imap': TlsWrappedProtocolEnum.STARTTLS_IMAP,
        143: TlsWrappedProtocolEnum.STARTTLS_IMAP,
        220: TlsWrappedProtocolEnum.STARTTLS_IMAP,
        'ftp': TlsWrappedProtocolEnum.STARTTLS_FTP,
        21: TlsWrappedProtocolEnum.STARTTLS_FTP,
        'ldap': TlsWrappedProtocolEnum.STARTTLS_LDAP,
        3268: TlsWrappedProtocolEnum.STARTTLS_LDAP,
        389: TlsWrappedProtocolEnum.STARTTLS_LDAP,
        'rdp': TlsWrappedProtocolEnum.STARTTLS_RDP,
        3389: TlsWrappedProtocolEnum.STARTTLS_RDP,
        'postgres': TlsWrappedProtocolEnum.STARTTLS_POSTGRES,
        5432: TlsWrappedProtocolEnum.STARTTLS_POSTGRES
    }

    def __init__(self, available_plugins, sslyze_version):
        # type: (Set[Type[Plugin]], Text) -> None
        """Generate SSLyze's command line parser.
        """
        self._parser = OptionParser(version=sslyze_version,
                                    usage=self.SSLYZE_USAGE)

        # Add generic command line options to the parser
        self._add_default_options()

        # Add plugin-specific options to the parser
        self._add_plugin_options(available_plugins)

        # Add the --regular command line parameter as a shortcut if possible
        regular_help = 'Regular HTTPS scan; shortcut for --{}'.format(
            ' --'.join(self.REGULAR_CMD))
        self._parser.add_option('--regular',
                                action='store_true',
                                dest=None,
                                help=regular_help)

    def parse_command_line(self):
        # type: () -> Tuple[List[ServerConnectivityTester], List[ServerStringParsingError], Any]
        """Parses the command line used to launch SSLyze.
        """
        (args_command_list, args_target_list) = self._parser.parse_args()

        if args_command_list.update_trust_stores:
            # Just update the trust stores and do nothing
            TrustStoresRepository.update_default()
            raise TrustStoresUpdateCompleted()

        # Handle the --targets_in command line and fill args_target_list
        if args_command_list.targets_in:
            if args_target_list:
                raise CommandLineParsingError(
                    'Cannot use --targets_list and specify targets within the command line.'
                )

            try:  # Read targets from a file
                with open(args_command_list.targets_in) as f:
                    for target in f.readlines():
                        if target.strip():  # Ignore empty lines
                            if not target.startswith(
                                    '#'):  # Ignore comment lines
                                args_target_list.append(target.strip())
            except IOError:
                raise CommandLineParsingError(
                    'Can\'t read targets from input file \'{}.'.format(
                        args_command_list.targets_in))

        if not args_target_list:
            raise CommandLineParsingError('No targets to scan.')

        # Handle the --regular command line parameter as a shortcut
        if self._parser.has_option('--regular'):
            if getattr(args_command_list, 'regular'):
                setattr(args_command_list, 'regular', False)
                for cmd in self.REGULAR_CMD:
                    setattr(args_command_list, cmd, True)

        # Sanity checks on the command line options
        # Prevent --quiet and --xml_out -
        if args_command_list.xml_file and args_command_list.xml_file == '-' and args_command_list.quiet:
            raise CommandLineParsingError(
                'Cannot use --quiet with --xml_out -.')

        # Prevent --quiet and --json_out -
        if args_command_list.json_file and args_command_list.json_file == '-' and args_command_list.quiet:
            raise CommandLineParsingError(
                'Cannot use --quiet with --json_out -.')

        # Prevent --xml_out - and --json_out -
        if args_command_list.json_file and args_command_list.json_file == '-' \
                and args_command_list.xml_file and args_command_list.xml_file == '-':
            raise CommandLineParsingError(
                'Cannot use --xml_out - with --json_out -.')

        # Sanity checks on the client cert options
        client_auth_creds = None
        if bool(args_command_list.cert) ^ bool(args_command_list.key):
            raise CommandLineParsingError(
                'No private key or certificate file were given. See --cert and --key.'
            )

        elif args_command_list.cert:
            # Private key formats
            if args_command_list.keyform == 'DER':
                key_type = OpenSslFileTypeEnum.ASN1
            elif args_command_list.keyform == 'PEM':
                key_type = OpenSslFileTypeEnum.PEM
            else:
                raise CommandLineParsingError(
                    '--keyform should be DER or PEM.')

            # Let's try to open the cert and key files
            try:
                client_auth_creds = ClientAuthenticationCredentials(
                    args_command_list.cert, args_command_list.key, key_type,
                    args_command_list.keypass)
            except ValueError as e:
                raise CommandLineParsingError(
                    'Invalid client authentication settings: {}.'.format(
                        e.args[0]))

        # HTTP CONNECT proxy
        http_tunneling_settings = None
        if args_command_list.https_tunnel:
            try:
                http_tunneling_settings = HttpConnectTunnelingSettings.from_url(
                    args_command_list.https_tunnel)
            except ValueError as e:
                raise CommandLineParsingError(
                    'Invalid proxy URL for --https_tunnel: {}.'.format(
                        e.args[0]))

        # STARTTLS
        tls_wrapped_protocol = TlsWrappedProtocolEnum.PLAIN_TLS
        if args_command_list.starttls:
            if args_command_list.starttls not in self.START_TLS_PROTOCOLS:
                raise CommandLineParsingError(self.START_TLS_USAGE)
            else:
                # StartTLS was specified
                if args_command_list.starttls in self.STARTTLS_PROTOCOL_DICT.keys(
                ):
                    # Protocol was given in the command line
                    tls_wrapped_protocol = self.STARTTLS_PROTOCOL_DICT[
                        args_command_list.starttls]

        # Create the server connectivity tester for each specified servers
        # A limitation when using the command line is that only one client_auth_credentials and http_tunneling_settings
        # can be specified, for all the servers to scan
        good_server_list = []
        bad_server_list = []
        for server_string in args_target_list:
            try:
                hostname, ip_address, port = CommandLineServerStringParser.parse_server_string(
                    server_string)
            except ServerStringParsingError as e:
                # Will happen if the server string is malformed
                bad_server_list.append(e)
                continue

            try:
                # TODO(AD): Unicode hostnames may fail on Python2
                # hostname = hostname.decode('utf-8')
                server_info = ServerConnectivityTester(
                    hostname=hostname,
                    port=port,
                    ip_address=ip_address,
                    tls_wrapped_protocol=tls_wrapped_protocol,
                    tls_server_name_indication=args_command_list.sni,
                    xmpp_to_hostname=args_command_list.xmpp_to,
                    client_auth_credentials=client_auth_creds,
                    http_tunneling_settings=http_tunneling_settings)
                good_server_list.append(server_info)
            except ValueError as e:
                # Will happen for example if xmpp_to is specified for a non-XMPP connection
                raise CommandLineParsingError(e.args[0])

        # Command line hacks
        # Handle --starttls=auto now that we parsed the server strings
        if args_command_list.starttls == 'auto':
            for server_info in good_server_list:
                # We use the port number to deduce the protocol
                if server_info.port in self.STARTTLS_PROTOCOL_DICT.keys():
                    server_info.tls_wrapped_protocol = self.STARTTLS_PROTOCOL_DICT[
                        server_info.port]

        # Handle --http_get now that we parsed the server strings
        # Doing it here is hacky as the option is defined within PluginOpenSSLCipherSuites
        if args_command_list.http_get:
            for server_info in good_server_list:
                if server_info.port == 443:
                    server_info.tls_wrapped_protocol = TlsWrappedProtocolEnum.HTTPS

        return good_server_list, bad_server_list, args_command_list

    def _add_default_options(self):
        # type: () -> None
        """Add default command line options to the parser.
        """
        # Updating the trust stores
        update_stores_group = OptionGroup(self._parser, 'Trust stores options',
                                          '')
        update_stores_group.add_option(
            '--update_trust_stores',
            help=
            'Update the default trust stores used by SSLyze. The latest stores will be downloaded from '
            'https://github.com/nabla-c0d3/trust_stores_observatory. This option is meant to be used separately, '
            'and will silence any other command line option supplied to SSLyze.',
            dest='update_trust_stores',
            action='store_true',
        )
        self._parser.add_option_group(update_stores_group)

        # Client certificate options
        clientcert_group = OptionGroup(self._parser,
                                       'Client certificate options', '')
        clientcert_group.add_option(
            '--cert',
            help=
            'Client certificate chain filename. The certificates must be in PEM format and must be sorted '
            'starting with the subject\'s client certificate, followed by intermediate CA certificates if '
            'applicable.',
            dest='cert')
        clientcert_group.add_option('--key',
                                    help='Client private key filename.',
                                    dest='key')
        clientcert_group.add_option(
            '--keyform',
            help='Client private key format. DER or PEM (default).',
            dest='keyform',
            default='PEM')
        clientcert_group.add_option('--pass',
                                    help='Client private key passphrase.',
                                    dest='keypass',
                                    default='')
        self._parser.add_option_group(clientcert_group)

        # Input / output
        output_group = OptionGroup(self._parser, 'Input and output options',
                                   '')
        # XML output
        output_group.add_option(
            '--xml_out',
            help=
            'Write the scan results as an XML document to the file XML_FILE. If XML_FILE is set to "-", the XML '
            'output will instead be printed to stdout.',
            dest='xml_file',
            default=None)
        # JSON output
        output_group.add_option(
            '--json_out',
            help=
            'Write the scan results as a JSON document to the file JSON_FILE. If JSON_FILE is set to "-", the '
            'JSON output will instead be printed to stdout. The resulting JSON file is a serialized version of '
            'the ScanResult objects described in SSLyze\'s Python API: the nodes and attributes will be the same. '
            'See https://nabla-c0d3.github.io/sslyze/documentation/available-scan-commands.html for more details.',
            dest='json_file',
            default=None)
        # Read targets from input file
        output_group.add_option(
            '--targets_in',
            help=
            'Read the list of targets to scan from the file TARGETS_IN. It should contain one host:port per '
            'line.',
            dest='targets_in',
            default=None)
        # No text output
        output_group.add_option(
            '--quiet',
            action='store_true',
            dest='quiet',
            help=
            'Do not output anything to stdout; useful when using --xml_out or --json_out.'
        )
        self._parser.add_option_group(output_group)

        # Connectivity option group
        connect_group = OptionGroup(self._parser, 'Connectivity options', '')
        # Connection speed
        connect_group.add_option(
            '--slow_connection',
            help=
            'Greatly reduce the number of concurrent connections initiated by SSLyze. This will make the scans '
            'slower but more reliable if the connection between your host and the server is slow, or if the '
            'server cannot handle many concurrent connections. Enable this option if you are getting a lot of '
            'timeouts or errors.',
            action='store_true',
            dest='slow_connection',
        )
        # HTTP CONNECT Proxy
        connect_group.add_option(
            '--https_tunnel',
            help=
            'Tunnel all traffic to the target server(s) through an HTTP CONNECT proxy. HTTP_TUNNEL should be the '
            'proxy\'s URL: \'http://*****:*****@HOST:PORT/\'. For proxies requiring authentication, only Basic '
            'Authentication is supported.',
            dest='https_tunnel',
            default=None)
        # STARTTLS
        connect_group.add_option(
            '--starttls',
            help=
            'Perform a StartTLS handshake when connecting to the target server(s). '
            '{}'.format(self.START_TLS_USAGE),
            dest='starttls',
            default=None)
        connect_group.add_option(
            '--xmpp_to',
            help=
            'Optional setting for STARTTLS XMPP. XMPP_TO should be the hostname to be put in the \'to\' '
            'attribute of the XMPP stream. Default is the server\'s hostname.',
            dest='xmpp_to',
            default=None)
        # Server Name Indication
        connect_group.add_option(
            '--sni',
            help=
            'Use Server Name Indication to specify the hostname to connect to.  Will only affect TLS 1.0+ '
            'connections.',
            dest='sni',
            default=None)
        self._parser.add_option_group(connect_group)

    def _add_plugin_options(self, available_plugins):
        # type: (Set[Type[Plugin]]) -> None
        """Recovers the list of command line options implemented by the available plugins and adds them to the command
        line parser.
        """
        for plugin_class in available_plugins:
            # Add the current plugin's commands to the parser
            group = OptionGroup(self._parser, plugin_class.get_title(),
                                plugin_class.get_description())
            for option in plugin_class.get_cli_option_group():
                group.add_option(option)
            self._parser.add_option_group(group)
Пример #22
0
class CommandLineParser:

    # Defines what --regular means
    REGULAR_CMD = [
        "sslv2",
        "sslv3",
        "tlsv1",
        "tlsv1_1",
        "tlsv1_2",
        "reneg",
        "resum",
        "certinfo",
        "http_get",
        "hide_rejected_ciphers",
        "compression",
    ]
    SSLYZE_USAGE = "usage: %prog [options] target1.com target2.com:443 etc..."

    # StartTLS options
    START_TLS_PROTS = ["smtp", "xmpp", "pop3", "ftp", "imap", "ldap", "rdp", "auto"]
    START_TLS_USAGE = (
        "STARTTLS should be one of: "
        + str(START_TLS_PROTS)
        + ". The 'auto' option will cause SSLyze to deduce the protocol"
        + " (ftp, imap, etc.) from the supplied port number, for each target servers."
    )

    # Default values
    DEFAULT_RETRY_ATTEMPTS = 5
    DEFAULT_TIMEOUT = 5

    def __init__(self, available_plugins, sslyze_version):
        """
        Generates SSLyze's command line parser.
        """

        self._parser = OptionParser(version=sslyze_version, usage=self.SSLYZE_USAGE)

        # Add generic command line options to the parser
        self._add_default_options()

        # Add plugin-specific options to the parser
        self._add_plugin_options(available_plugins)

        # Add the --regular command line parameter as a shortcut if possible
        regular_help = "Regular HTTPS scan; shortcut for"
        for cmd in self.REGULAR_CMD:
            regular_help += " --" + cmd
            if cmd == "certinfo":  # gah
                regular_help += "=basic"

            if self._parser.has_option("--" + cmd) == False:
                return

        self._parser.add_option("--regular", action="store_true", dest=None, help=regular_help)

    def parse_command_line(self):
        """
        Parses the command line used to launch SSLyze.
        """

        (args_command_list, args_target_list) = self._parser.parse_args()

        # Handle the --targets_in command line and fill args_target_list
        if args_command_list.targets_in:
            if args_target_list:
                raise CommandLineParsingError("Cannot use --targets_list and specify targets within the command line.")

            try:  # Read targets from a file
                with open(args_command_list.targets_in) as f:
                    for target in f.readlines():
                        if target.strip():  # Ignore empty lines
                            if not target.startswith("#"):  # Ignore comment lines
                                args_target_list.append(target.strip())
            except IOError:
                raise CommandLineParsingError("Can't read targets from input file '%s'." % args_command_list.targets_in)

        if args_target_list == []:
            raise CommandLineParsingError("No targets to scan.")

        # Handle the --regular command line parameter as a shortcut
        if self._parser.has_option("--regular"):
            if getattr(args_command_list, "regular"):
                setattr(args_command_list, "regular", False)
                for cmd in self.REGULAR_CMD:
                    setattr(args_command_list, cmd, True)
                setattr(args_command_list, "certinfo", "basic")  # Special case

        # Create the shared_settings object from looking at the command line
        shared_settings = self._process_parsing_results(args_command_list)

        return (args_command_list, args_target_list, shared_settings)

    def _add_default_options(self):
        """
        Adds default command line options to the parser.
        """

        # Client certificate options
        clientcert_group = OptionGroup(self._parser, "Client certificate support", "")
        clientcert_group.add_option("--cert", help="Client certificate filename.", dest="cert")
        clientcert_group.add_option(
            "--certform", help="Client certificate format. DER or PEM (default).", dest="certform", default="PEM"
        )
        clientcert_group.add_option("--key", help="Client private key filename.", dest="key")
        clientcert_group.add_option(
            "--keyform", help="Client private key format. DER or PEM (default).", dest="keyform", default="PEM"
        )
        clientcert_group.add_option("--pass", help="Client private key passphrase.", dest="keypass", default="")
        self._parser.add_option_group(clientcert_group)

        # XML output
        self._parser.add_option(
            "--xml_out",
            help=("Writes the scan results as an XML document to the file XML_FILE."),
            dest="xml_file",
            default=None,
        )

        # Read targets from input file
        self._parser.add_option(
            "--targets_in",
            help=(
                "Reads the list of targets to scan from the file TARGETS_IN. It should contain one host:port per line."
            ),
            dest="targets_in",
            default=None,
        )

        # Timeout
        self._parser.add_option(
            "--timeout",
            help=(
                "Sets the timeout value in seconds used for every socket "
                "connection made to the target server(s). Default is " + str(self.DEFAULT_TIMEOUT) + "s."
            ),
            type="int",
            dest="timeout",
            default=self.DEFAULT_TIMEOUT,
        )

        # Control connection retry attempts
        self._parser.add_option(
            "--nb_retries",
            help=(
                "Sets the number retry attempts for all network connections "
                "initiated throughout the scan. Increase this value if you are "
                "getting a lot of timeout/connection errors when scanning a "
                "specific server. Decrease this value to increase the speed "
                "of the scans; results may however return connection errors. "
                "Default is " + str(self.DEFAULT_RETRY_ATTEMPTS) + " connection attempts."
            ),
            type="int",
            dest="nb_retries",
            default=self.DEFAULT_RETRY_ATTEMPTS,
        )

        # HTTP CONNECT Proxy
        self._parser.add_option(
            "--https_tunnel",
            help=(
                "Tunnels all traffic to the target server(s) through an HTTP "
                "CONNECT proxy. HTTP_TUNNEL should be 'host:port'."
            ),
            dest="https_tunnel",
            default=None,
        )

        # STARTTLS
        self._parser.add_option(
            "--starttls",
            help=("Performs StartTLS handshakes when connecting to the target " "server(s). " + self.START_TLS_USAGE),
            dest="starttls",
            default=None,
        )

        self._parser.add_option(
            "--xmpp_to",
            help=(
                "Optional setting for STARTTLS XMPP. "
                " XMPP_TO should be the hostname to be put in the 'to' attribute "
                "of the XMPP stream. Default is the server's hostname."
            ),
            dest="xmpp_to",
            default=None,
        )

        # Server Name Indication
        self._parser.add_option(
            "--sni",
            help=(
                "Use Server Name Indication to specify the hostname to connect to."
                " Will only affect TLS 1.0+ connections."
            ),
            dest="sni",
            default=None,
        )

    def _add_plugin_options(self, available_plugins):
        """
        Recovers the list of command line options implemented by the available
        plugins and adds them to the command line parser.
        """

        for plugin_class in available_plugins:
            plugin_desc = plugin_class.get_interface()

            # Add the current plugin's commands to the parser
            group = OptionGroup(self._parser, plugin_desc.title, plugin_desc.description)
            for cmd in plugin_desc.get_commands():
                group.add_option(cmd)

            # Add the current plugin's options to the parser
            for option in plugin_desc.get_options():
                group.add_option(option)

            self._parser.add_option_group(group)

    def _process_parsing_results(self, args_command_list):
        """
        Performs various sanity checks on the command line that was used to
        launch SSLyze.
        Returns the shared_settings object to be fed to plugins.
        """

        shared_settings = {}
        # Sanity checks on the client cert options
        if bool(args_command_list.cert) ^ bool(args_command_list.key):
            raise CommandLineParsingError("No private key or certificate file were given. See --cert and --key.")

        # Private key and cert formats
        if args_command_list.certform is "DER":
            args_command_list.certform = SSL_FILETYPE_ASN1
        elif args_command_list.certform is "PEM":
            args_command_list.certform = SSL_FILETYPE_PEM
        else:
            raise CommandLineParsingError("--certform should be DER or PEM.")

        if args_command_list.keyform is "DER":
            args_command_list.keyform = SSL_FILETYPE_ASN1
        elif args_command_list.keyform is "PEM":
            args_command_list.keyform = SSL_FILETYPE_PEM
        else:
            raise CommandLineParsingError("--keyform should be DER or PEM.")

        # Let's try to open the cert and key files
        if args_command_list.cert:
            try:
                open(args_command_list.cert, "r")
            except:
                raise CommandLineParsingError(
                    'Could not open the client certificate file "' + str(args_command_list.cert) + '".'
                )

        if args_command_list.key:
            try:
                open(args_command_list.key, "r")
            except:
                raise CommandLineParsingError(
                    'Could not open the client private key file "' + str(args_command_list.key) + '"'
                )

            # Try to load the cert and key in OpenSSL
            try:
                sslClient = SslClient()
                sslClient.use_private_key(
                    args_command_list.cert,
                    args_command_list.certform,
                    args_command_list.key,
                    args_command_list.keyform,
                    args_command_list.keypass,
                )
            except _nassl.OpenSSLError as e:
                if "bad decrypt" in str(e.args):
                    raise CommandLineParsingError("Could not decrypt the private key. Wrong passphrase ?")
                raise CommandLineParsingError("Could not load the certificate or the private key. Passphrase needed ?")

        # HTTP CONNECT proxy
        if args_command_list.https_tunnel:
            if "2.7." not in platform.python_version():  # Python 2.7 only
                raise CommandLineParsingError(
                    "--https_tunnel requires Python 2.7.X. " "Current version is " + platform.python_version() + "."
                )

            try:  # Need to parse the proxy host:port string now
                (host, port) = TargetStringParser.parse_target_str(args_command_list.https_tunnel, 443)
                shared_settings["https_tunnel_host"] = host
                shared_settings["https_tunnel_port"] = port
            except InvalidTargetError:
                raise CommandLineParsingError("Not a valid host/port for --https_tunnel" ", discarding all tasks.")

        else:
            shared_settings["https_tunnel_host"] = None
            shared_settings["https_tunnel_port"] = None

        # STARTTLS
        if args_command_list.starttls:
            if args_command_list.starttls not in self.START_TLS_PROTS:
                raise CommandLineParsingError(self.START_TLS_USAGE)

        if args_command_list.starttls and args_command_list.https_tunnel:
            raise CommandLineParsingError("Cannot have --https_tunnel and --starttls at the same time.")

        # Number of connection retries
        if args_command_list.nb_retries < 1:
            raise CommandLineParsingError("Cannot have a number smaller than 1 for --nb_retries.")

        # All good, let's save the data
        for key, value in args_command_list.__dict__.iteritems():
            shared_settings[key] = value

        return shared_settings
class CommandLineParser():

    # Defines what --regular means
    REGULAR_CMD = [
        'sslv2', 'sslv3', 'tlsv1', 'reneg', 'resum', 'certinfo', 'http_get',
        'hide_rejected_ciphers', 'compression', 'tlsv1_1', 'tlsv1_2'
    ]
    SSLYZE_USAGE = 'usage: %prog [options] target1.com target2.com:443 etc...'

    def __init__(self, available_plugins, sslyze_version, timeout):
        """
        Generates SSLyze's command line parser.
        """

        self._parser = OptionParser(version=sslyze_version,
                                    usage=self.SSLYZE_USAGE)

        # Add generic command line options to the parser
        self._add_default_options(timeout)

        # Add plugin-specific options to the parser
        self._add_plugin_options(available_plugins)

        # Add the --regular command line parameter as a shortcut if possible
        regular_help = 'Regular HTTPS scan; shortcut for'
        for cmd in self.REGULAR_CMD:
            regular_help += ' --' + cmd
            if (self._parser.has_option('--' + cmd) == False):
                return

        self._parser.add_option('--regular',
                                action="store_true",
                                dest=None,
                                help=regular_help)

    def parse_command_line(self):
        """
        Parses the command line used to launch SSLyze.
        """

        (args_command_list, args_target_list) = self._parser.parse_args()

        # Handle the --targets_in command line and fill args_target_list
        if args_command_list.targets_in:
            if args_target_list:
                raise CommandLineParsingError(
                    "Cannot use --targets_list and specify targets within the command line."
                )

            try:  # Read targets from a file
                with open(args_command_list.targets_in) as f:
                    for target in f.readlines():
                        if target.strip():  # Ignore empty lines
                            if not target.startswith(
                                    '#'):  # Ignore comment lines
                                args_target_list.append(target.strip())
            except IOError:
                raise CommandLineParsingError(
                    "Can't read targets from input file '%s'." %
                    args_command_list.targets_in)

        if args_target_list == []:
            raise CommandLineParsingError('No targets to scan.')

        # Handle the --regular command line parameter as a shortcut
        if self._parser.has_option('--regular'):
            if getattr(args_command_list, 'regular'):
                setattr(args_command_list, 'regular', False)
                for cmd in self.REGULAR_CMD:
                    setattr(args_command_list, cmd, True)
                setattr(args_command_list, 'certinfo', 'basic')  # Special case

        # Create the shared_settings object from looking at the command line
        shared_settings = self._process_parsing_results(args_command_list)

        return (args_command_list, args_target_list, shared_settings)

    def _add_default_options(self, timeout):
        """
        Adds default command line options to the parser.
        """

        # Client certificate options
        clientcert_group = OptionGroup(self._parser,
                                       'Client certificate support', '')
        clientcert_group.add_option('--cert',
                                    help='Client certificate filename.',
                                    dest='cert')
        clientcert_group.add_option(
            '--certform',
            help='Client certificate format. DER or PEM (default).',
            dest='certform',
            default='PEM')
        clientcert_group.add_option('--key',
                                    help='Client private key filename.',
                                    dest='key')
        clientcert_group.add_option(
            '--keyform',
            help='Client private key format. DER or PEM (default).',
            dest='keyform',
            default='PEM')
        clientcert_group.add_option('--pass',
                                    help='Client private key passphrase.',
                                    dest='keypass')
        self._parser.add_option_group(clientcert_group)

        # XML output
        self._parser.add_option(
            '--xml_out',
            help=
            ('Writes the scan results as an XML document to the file XML_FILE.'
             ),
            dest='xml_file',
            default=None)

        # Read targets from input file
        self._parser.add_option(
            '--targets_in',
            help=
            ('Reads the list of targets to scan from the file TARGETS_IN. It should contain one host:port per line.'
             ),
            dest='targets_in',
            default=None)

        # Timeout
        self._parser.add_option(
            '--timeout',
            help=('Sets the timeout value in seconds used for every socket '
                  'connection made to the target server(s). Default is 5s.'),
            type='int',
            dest='timeout',
            default=timeout)

        # HTTP CONNECT Proxy
        self._parser.add_option(
            '--https_tunnel',
            help=
            ('Sets an HTTP CONNECT proxy to tunnel SSL traffic to the target '
             'server(s). HTTP_TUNNEL should be \'host:port\'. '
             'Requires Python 2.7'),
            dest='https_tunnel',
            default=None)

        # STARTTLS
        self._parser.add_option(
            '--starttls',
            help=
            ('Identifies the target server(s) as a SMTP or an XMPP server(s) '
             'and scans the server(s) using STARTTLS. '
             'STARTTLS should be \'smtp\' or \'xmpp\'.'),
            dest='starttls',
            default=None)

        self._parser.add_option(
            '--xmpp_to',
            help=
            ('Optional setting for STARTTLS XMPP. '
             ' XMPP_TO should be the hostname to be put in the \'to\' attribute '
             'of the XMPP stream. Default is the server\'s hostname.'),
            dest='xmpp_to',
            default=None)

        # Server Name Indication
        self._parser.add_option(
            '--sni',
            help=
            ('Use Server Name Indication to specify the hostname to connect to.'
             ' Will only affect TLS 1.0+ connections.'),
            dest='sni',
            default=None)

    def _add_plugin_options(self, available_plugins):
        """
        Recovers the list of command line options implemented by the available
        plugins and adds them to the command line parser.
        """

        for plugin_class in available_plugins:
            plugin_desc = plugin_class.get_interface()

            # Add the current plugin's commands to the parser
            group = OptionGroup(self._parser, plugin_desc.title,\
                                plugin_desc.description)
            for cmd in plugin_desc.get_commands():
                group.add_option(cmd)

            # Add the current plugin's options to the parser
            for option in plugin_desc.get_options():
                group.add_option(option)

            self._parser.add_option_group(group)

    def _process_parsing_results(self, args_command_list):
        """
        Performs various sanity checks on the command line that was used to 
        launch SSLyze.
        Returns the shared_settings object to be fed to plugins.
        """

        shared_settings = {}
        # Sanity checks on the client cert options
        if bool(args_command_list.cert) ^ bool(args_command_list.key):
            raise CommandLineParsingError(
                'No private key or certificate file were given. See --cert and --key.'
            )

        # Let's try to open the cert and key files
        if args_command_list.cert:
            try:
                open(args_command_list.cert, "r")
            except:
                raise CommandLineParsingError(
                    'Could not open the client certificate file "' +
                    str(args_command_list.cert) + '".')

        if args_command_list.key:
            try:
                open(args_command_list.key, "r")
            except:
                raise CommandLineParsingError(
                    'Could not open the client private key file "' +
                    str(args_command_list.key) + '"')

        # Parse client cert options
        if args_command_list.certform not in ['DER', 'PEM']:
            raise CommandLineParsingError('--certform should be DER or PEM.')

        if args_command_list.keyform not in ['DER', 'PEM']:
            raise CommandLineParsingError('--keyform should be DER or PEM.')

        # HTTP CONNECT proxy
        if args_command_list.https_tunnel:
            if '2.7.' not in platform.python_version():  # Python 2.7 only
                raise CommandLineParsingError(
                    '--https_tunnel requires Python 2.7.X. '
                    'Current version is ' + platform.python_version() + '.')

            try:  # Need to parse the proxy host:port string now
                proxy_test = SSLServerTester(args_command_list.https_tunnel)
                shared_settings['https_tunnel_host'] = proxy_test.get_target(
                )[0]
                shared_settings['https_tunnel_port'] = proxy_test.get_target(
                )[2]
            except InvalidTargetError:
                raise CommandLineParsingError(
                    'Not a valid host/port for --https_tunnel'
                    ', discarding all tasks.')

        else:
            shared_settings['https_tunnel_host'] = None
            shared_settings['https_tunnel_port'] = None

        # STARTTLS
        if args_command_list.starttls not in [None, 'smtp', 'xmpp']:
            raise CommandLineParsingError(
                '--starttls should be \'smtp\' or \'xmpp\'.')

        if args_command_list.starttls and args_command_list.https_tunnel:
            raise CommandLineParsingError(
                'Cannot have --https_tunnel and --starttls at the same time.')

        # All good, let's save the data
        for key, value in args_command_list.__dict__.iteritems():
            shared_settings[key] = value

        return shared_settings
Пример #24
0
def parse_opts(tmpcmdline, silent=False):
	myaction=None
	myopts = {}
	myfiles=[]

	actions = frozenset([
		"clean", "check-news", "config", "depclean", "help",
		"info", "list-sets", "metadata", "moo",
		"prune", "regen",  "search",
		"sync",  "unmerge", "version",
	])

	longopt_aliases = {"--cols":"--columns", "--skip-first":"--skipfirst"}
	y_or_n = ("y", "n")
	true_y_or_n = ("True", "y", "n")
	true_y = ("True", "y")
	argument_options = {

		"--ask": {
			"shortopt" : "-a",
			"help"    : "prompt before performing any actions",
			"type"    : "choice",
			"choices" : true_y_or_n
		},

		"--autounmask": {
			"help"    : "automatically unmask packages",
			"type"    : "choice",
			"choices" : true_y_or_n
		},

		"--autounmask-unrestricted-atoms": {
			"help"    : "write autounmask changes with >= atoms if possible",
			"type"    : "choice",
			"choices" : true_y_or_n
		},

		"--autounmask-keep-masks": {
			"help"    : "don't add package.unmask entries",
			"type"    : "choice",
			"choices" : true_y_or_n
		},

		"--autounmask-write": {
			"help"    : "write changes made by --autounmask to disk",
			"type"    : "choice",
			"choices" : true_y_or_n
		},

		"--accept-properties": {
			"help":"temporarily override ACCEPT_PROPERTIES",
			"action":"store"
		},

		"--backtrack": {

			"help"   : "Specifies how many times to backtrack if dependency " + \
				"calculation fails ",

			"action" : "store"
		},

		"--buildpkg": {
			"shortopt" : "-b",
			"help"     : "build binary packages",
			"type"     : "choice",
			"choices"  : true_y_or_n
		},

		"--buildpkg-exclude": {
			"help"   :"A space separated list of package atoms for which " + \
				"no binary packages should be built. This option overrides all " + \
				"possible ways to enable building of binary packages.",

			"action" : "append"
		},

		"--config-root": {
			"help":"specify the location for portage configuration files",
			"action":"store"
		},
		"--color": {
			"help":"enable or disable color output",
			"type":"choice",
			"choices":("y", "n")
		},

		"--complete-graph": {
			"help"    : "completely account for all known dependencies",
			"type"    : "choice",
			"choices" : true_y_or_n
		},

		"--complete-graph-if-new-use": {
			"help"    : "trigger --complete-graph behavior if USE or IUSE will change for an installed package",
			"type"    : "choice",
			"choices" : y_or_n
		},

		"--complete-graph-if-new-ver": {
			"help"    : "trigger --complete-graph behavior if an installed package version will change (upgrade or downgrade)",
			"type"    : "choice",
			"choices" : y_or_n
		},

		"--deep": {

			"shortopt" : "-D",

			"help"   : "Specifies how deep to recurse into dependencies " + \
				"of packages given as arguments. If no argument is given, " + \
				"depth is unlimited. Default behavior is to skip " + \
				"dependencies of installed packages.",

			"action" : "store"
		},

		"--depclean-lib-check": {
			"help"    : "check for consumers of libraries before removing them",
			"type"    : "choice",
			"choices" : true_y_or_n
		},

		"--deselect": {
			"help"    : "remove atoms/sets from the world file",
			"type"    : "choice",
			"choices" : true_y_or_n
		},

		"--dynamic-deps": {
			"help": "substitute the dependencies of installed packages with the dependencies of unbuilt ebuilds",
			"type": "choice",
			"choices": y_or_n
		},

		"--exclude": {
			"help"   :"A space separated list of package names or slot atoms. " + \
				"Emerge won't  install any ebuild or binary package that " + \
				"matches any of the given package atoms.",

			"action" : "append"
		},

		"--fail-clean": {
			"help"    : "clean temp files after build failure",
			"type"    : "choice",
			"choices" : true_y_or_n
		},

		"--ignore-built-slot-operator-deps": {
			"help": "Ignore the slot/sub-slot := operator parts of dependencies that have "
				"been recorded when packages where built. This option is intended "
				"only for debugging purposes, and it only affects built packages "
				"that specify slot/sub-slot := operator dependencies using the "
				"experimental \"4-slot-abi\" EAPI.",
			"type": "choice",
			"choices": y_or_n
		},

		"--jobs": {

			"shortopt" : "-j",

			"help"   : "Specifies the number of packages to build " + \
				"simultaneously.",

			"action" : "store"
		},

		"--keep-going": {
			"help"    : "continue as much as possible after an error",
			"type"    : "choice",
			"choices" : true_y_or_n
		},

		"--load-average": {

			"help"   :"Specifies that no new builds should be started " + \
				"if there are other builds running and the load average " + \
				"is at least LOAD (a floating-point number).",

			"action" : "store"
		},

		"--misspell-suggestions": {
			"help"    : "enable package name misspell suggestions",
			"type"    : "choice",
			"choices" : ("y", "n")
		},

		"--with-bdeps": {
			"help":"include unnecessary build time dependencies",
			"type":"choice",
			"choices":("y", "n")
		},
		"--reinstall": {
			"help":"specify conditions to trigger package reinstallation",
			"type":"choice",
			"choices":["changed-use"]
		},

		"--reinstall-atoms": {
			"help"   :"A space separated list of package names or slot atoms. " + \
				"Emerge will treat matching packages as if they are not " + \
				"installed, and reinstall them if necessary. Implies --deep.",

			"action" : "append",
		},

		"--binpkg-respect-use": {
			"help"    : "discard binary packages if their use flags \
				don't match the current configuration",
			"type"    : "choice",
			"choices" : true_y_or_n
		},

		"--getbinpkg": {
			"shortopt" : "-g",
			"help"     : "fetch binary packages",
			"type"     : "choice",
			"choices"  : true_y_or_n
		},

		"--getbinpkgonly": {
			"shortopt" : "-G",
			"help"     : "fetch binary packages only",
			"type"     : "choice",
			"choices"  : true_y_or_n
		},

		"--usepkg-exclude": {
			"help"   :"A space separated list of package names or slot atoms. " + \
				"Emerge will ignore matching binary packages. ",

			"action" : "append",
		},

		"--rebuild-exclude": {
			"help"   :"A space separated list of package names or slot atoms. " + \
				"Emerge will not rebuild these packages due to the " + \
				"--rebuild flag. ",

			"action" : "append",
		},

		"--rebuild-ignore": {
			"help"   :"A space separated list of package names or slot atoms. " + \
				"Emerge will not rebuild packages that depend on matching " + \
				"packages due to the --rebuild flag. ",

			"action" : "append",
		},

		"--package-moves": {
			"help"     : "perform package moves when necessary",
			"type"     : "choice",
			"choices"  : true_y_or_n
		},

		"--quiet": {
			"shortopt" : "-q",
			"help"     : "reduced or condensed output",
			"type"     : "choice",
			"choices"  : true_y_or_n
		},

		"--quiet-build": {
			"help"     : "redirect build output to logs",
			"type"     : "choice",
			"choices"  : true_y_or_n,
		},

		"--rebuild-if-new-slot": {
			"help"     : ("Automatically rebuild or reinstall packages when slot/sub-slot := "
				"operator dependencies can be satisfied by a newer slot, so that "
				"older packages slots will become eligible for removal by the "
				"--depclean action as soon as possible."),
			"type"     : "choice",
			"choices"  : true_y_or_n
		},

		"--rebuild-if-new-rev": {
			"help"     : "Rebuild packages when dependencies that are " + \
				"used at both build-time and run-time are built, " + \
				"if the dependency is not already installed with the " + \
				"same version and revision.",
			"type"     : "choice",
			"choices"  : true_y_or_n
		},

		"--rebuild-if-new-ver": {
			"help"     : "Rebuild packages when dependencies that are " + \
				"used at both build-time and run-time are built, " + \
				"if the dependency is not already installed with the " + \
				"same version. Revision numbers are ignored.",
			"type"     : "choice",
			"choices"  : true_y_or_n
		},

		"--rebuild-if-unbuilt": {
			"help"     : "Rebuild packages when dependencies that are " + \
				"used at both build-time and run-time are built.",
			"type"     : "choice",
			"choices"  : true_y_or_n
		},

		"--rebuilt-binaries": {
			"help"     : "replace installed packages with binary " + \
			             "packages that have been rebuilt",
			"type"     : "choice",
			"choices"  : true_y_or_n
		},
		
		"--rebuilt-binaries-timestamp": {
			"help"   : "use only binaries that are newer than this " + \
			           "timestamp for --rebuilt-binaries",
			"action" : "store"
		},

		"--root": {
		 "help"   : "specify the target root filesystem for merging packages",
		 "action" : "store"
		},

		"--root-deps": {
			"help"    : "modify interpretation of depedencies",
			"type"    : "choice",
			"choices" :("True", "rdeps")
		},

		"--select": {
			"help"    : "add specified packages to the world set " + \
			            "(inverse of --oneshot)",
			"type"    : "choice",
			"choices" : true_y_or_n
		},

		"--selective": {
			"help"    : "identical to --noreplace",
			"type"    : "choice",
			"choices" : true_y_or_n
		},

		"--use-ebuild-visibility": {
			"help"     : "use unbuilt ebuild metadata for visibility checks on built packages",
			"type"     : "choice",
			"choices"  : true_y_or_n
		},

		"--useoldpkg-atoms": {
			"help"   :"A space separated list of package names or slot atoms. " + \
				"Emerge will prefer matching binary packages over newer unbuilt packages. ",

			"action" : "append",
		},

		"--usepkg": {
			"shortopt" : "-k",
			"help"     : "use binary packages",
			"type"     : "choice",
			"choices"  : true_y_or_n
		},

		"--usepkgonly": {
			"shortopt" : "-K",
			"help"     : "use only binary packages",
			"type"     : "choice",
			"choices"  : true_y_or_n
		},
	}

	from optparse import OptionParser
	parser = OptionParser()
	if parser.has_option("--help"):
		parser.remove_option("--help")

	for action_opt in actions:
		parser.add_option("--" + action_opt, action="store_true",
			dest=action_opt.replace("-", "_"), default=False)
	for myopt in options:
		parser.add_option(myopt, action="store_true",
			dest=myopt.lstrip("--").replace("-", "_"), default=False)
	for shortopt, longopt in shortmapping.items():
		parser.add_option("-" + shortopt, action="store_true",
			dest=longopt.lstrip("--").replace("-", "_"), default=False)
	for myalias, myopt in longopt_aliases.items():
		parser.add_option(myalias, action="store_true",
			dest=myopt.lstrip("--").replace("-", "_"), default=False)

	for myopt, kwargs in argument_options.items():
		shortopt = kwargs.pop("shortopt", None)
		args = [myopt]
		if shortopt is not None:
			args.append(shortopt)
		parser.add_option(dest=myopt.lstrip("--").replace("-", "_"),
			*args, **kwargs)

	tmpcmdline = insert_optional_args(tmpcmdline)

	myoptions, myargs = parser.parse_args(args=tmpcmdline)

	if myoptions.ask in true_y:
		myoptions.ask = True
	else:
		myoptions.ask = None

	if myoptions.autounmask in true_y:
		myoptions.autounmask = True

	if myoptions.autounmask_unrestricted_atoms in true_y:
		myoptions.autounmask_unrestricted_atoms = True

	if myoptions.autounmask_keep_masks in true_y:
		myoptions.autounmask_keep_masks = True

	if myoptions.autounmask_write in true_y:
		myoptions.autounmask_write = True

	if myoptions.buildpkg in true_y:
		myoptions.buildpkg = True

	if myoptions.buildpkg_exclude:
		bad_atoms = _find_bad_atoms(myoptions.buildpkg_exclude, less_strict=True)
		if bad_atoms and not silent:
			parser.error("Invalid Atom(s) in --buildpkg-exclude parameter: '%s'\n" % \
				(",".join(bad_atoms),))

	if myoptions.changed_use is not False:
		myoptions.reinstall = "changed-use"
		myoptions.changed_use = False

	if myoptions.deselect in true_y:
		myoptions.deselect = True

	if myoptions.binpkg_respect_use is not None:
		if myoptions.binpkg_respect_use in true_y:
			myoptions.binpkg_respect_use = 'y'
		else:
			myoptions.binpkg_respect_use = 'n'

	if myoptions.complete_graph in true_y:
		myoptions.complete_graph = True
	else:
		myoptions.complete_graph = None

	if myoptions.depclean_lib_check in true_y:
		myoptions.depclean_lib_check = True

	if myoptions.exclude:
		bad_atoms = _find_bad_atoms(myoptions.exclude)
		if bad_atoms and not silent:
			parser.error("Invalid Atom(s) in --exclude parameter: '%s' (only package names and slot atoms (with wildcards) allowed)\n" % \
				(",".join(bad_atoms),))

	if myoptions.reinstall_atoms:
		bad_atoms = _find_bad_atoms(myoptions.reinstall_atoms)
		if bad_atoms and not silent:
			parser.error("Invalid Atom(s) in --reinstall-atoms parameter: '%s' (only package names and slot atoms (with wildcards) allowed)\n" % \
				(",".join(bad_atoms),))

	if myoptions.rebuild_exclude:
		bad_atoms = _find_bad_atoms(myoptions.rebuild_exclude)
		if bad_atoms and not silent:
			parser.error("Invalid Atom(s) in --rebuild-exclude parameter: '%s' (only package names and slot atoms (with wildcards) allowed)\n" % \
				(",".join(bad_atoms),))

	if myoptions.rebuild_ignore:
		bad_atoms = _find_bad_atoms(myoptions.rebuild_ignore)
		if bad_atoms and not silent:
			parser.error("Invalid Atom(s) in --rebuild-ignore parameter: '%s' (only package names and slot atoms (with wildcards) allowed)\n" % \
				(",".join(bad_atoms),))

	if myoptions.usepkg_exclude:
		bad_atoms = _find_bad_atoms(myoptions.usepkg_exclude)
		if bad_atoms and not silent:
			parser.error("Invalid Atom(s) in --usepkg-exclude parameter: '%s' (only package names and slot atoms (with wildcards) allowed)\n" % \
				(",".join(bad_atoms),))

	if myoptions.useoldpkg_atoms:
		bad_atoms = _find_bad_atoms(myoptions.useoldpkg_atoms)
		if bad_atoms and not silent:
			parser.error("Invalid Atom(s) in --useoldpkg-atoms parameter: '%s' (only package names and slot atoms (with wildcards) allowed)\n" % \
				(",".join(bad_atoms),))

	if myoptions.fail_clean in true_y:
		myoptions.fail_clean = True

	if myoptions.getbinpkg in true_y:
		myoptions.getbinpkg = True
	else:
		myoptions.getbinpkg = None

	if myoptions.getbinpkgonly in true_y:
		myoptions.getbinpkgonly = True
	else:
		myoptions.getbinpkgonly = None

	if myoptions.keep_going in true_y:
		myoptions.keep_going = True
	else:
		myoptions.keep_going = None

	if myoptions.package_moves in true_y:
		myoptions.package_moves = True

	if myoptions.quiet in true_y:
		myoptions.quiet = True
	else:
		myoptions.quiet = None

	if myoptions.quiet_build in true_y:
		myoptions.quiet_build = 'y'

	if myoptions.rebuild_if_new_slot in true_y:
		myoptions.rebuild_if_new_slot = 'y'

	if myoptions.rebuild_if_new_ver in true_y:
		myoptions.rebuild_if_new_ver = True
	else:
		myoptions.rebuild_if_new_ver = None

	if myoptions.rebuild_if_new_rev in true_y:
		myoptions.rebuild_if_new_rev = True
		myoptions.rebuild_if_new_ver = None
	else:
		myoptions.rebuild_if_new_rev = None

	if myoptions.rebuild_if_unbuilt in true_y:
		myoptions.rebuild_if_unbuilt = True
		myoptions.rebuild_if_new_rev = None
		myoptions.rebuild_if_new_ver = None
	else:
		myoptions.rebuild_if_unbuilt = None

	if myoptions.rebuilt_binaries in true_y:
		myoptions.rebuilt_binaries = True

	if myoptions.root_deps in true_y:
		myoptions.root_deps = True

	if myoptions.select in true_y:
		myoptions.select = True
		myoptions.oneshot = False
	elif myoptions.select == "n":
		myoptions.oneshot = True

	if myoptions.selective in true_y:
		myoptions.selective = True

	if myoptions.backtrack is not None:

		try:
			backtrack = int(myoptions.backtrack)
		except (OverflowError, ValueError):
			backtrack = -1

		if backtrack < 0:
			backtrack = None
			if not silent:
				parser.error("Invalid --backtrack parameter: '%s'\n" % \
					(myoptions.backtrack,))

		myoptions.backtrack = backtrack

	if myoptions.deep is not None:
		deep = None
		if myoptions.deep == "True":
			deep = True
		else:
			try:
				deep = int(myoptions.deep)
			except (OverflowError, ValueError):
				deep = -1

		if deep is not True and deep < 0:
			deep = None
			if not silent:
				parser.error("Invalid --deep parameter: '%s'\n" % \
					(myoptions.deep,))

		myoptions.deep = deep

	if myoptions.jobs:
		jobs = None
		if myoptions.jobs == "True":
			jobs = True
		else:
			try:
				jobs = int(myoptions.jobs)
			except ValueError:
				jobs = -1

		if jobs is not True and \
			jobs < 1:
			jobs = None
			if not silent:
				parser.error("Invalid --jobs parameter: '%s'\n" % \
					(myoptions.jobs,))

		myoptions.jobs = jobs

	if myoptions.load_average == "True":
		myoptions.load_average = None

	if myoptions.load_average:
		try:
			load_average = float(myoptions.load_average)
		except ValueError:
			load_average = 0.0

		if load_average <= 0.0:
			load_average = None
			if not silent:
				parser.error("Invalid --load-average parameter: '%s'\n" % \
					(myoptions.load_average,))

		myoptions.load_average = load_average
	
	if myoptions.rebuilt_binaries_timestamp:
		try:
			rebuilt_binaries_timestamp = int(myoptions.rebuilt_binaries_timestamp)
		except ValueError:
			rebuilt_binaries_timestamp = -1

		if rebuilt_binaries_timestamp < 0:
			rebuilt_binaries_timestamp = 0
			if not silent:
				parser.error("Invalid --rebuilt-binaries-timestamp parameter: '%s'\n" % \
					(myoptions.rebuilt_binaries_timestamp,))

		myoptions.rebuilt_binaries_timestamp = rebuilt_binaries_timestamp

	if myoptions.use_ebuild_visibility in true_y:
		myoptions.use_ebuild_visibility = True
	else:
		# None or "n"
		pass

	if myoptions.usepkg in true_y:
		myoptions.usepkg = True
	else:
		myoptions.usepkg = None

	if myoptions.usepkgonly in true_y:
		myoptions.usepkgonly = True
	else:
		myoptions.usepkgonly = None

	for myopt in options:
		v = getattr(myoptions, myopt.lstrip("--").replace("-", "_"))
		if v:
			myopts[myopt] = True

	for myopt in argument_options:
		v = getattr(myoptions, myopt.lstrip("--").replace("-", "_"), None)
		if v is not None:
			myopts[myopt] = v

	if myoptions.searchdesc:
		myoptions.search = True

	for action_opt in actions:
		v = getattr(myoptions, action_opt.replace("-", "_"))
		if v:
			if myaction:
				multiple_actions(myaction, action_opt)
				sys.exit(1)
			myaction = action_opt

	if myaction is None and myoptions.deselect is True:
		myaction = 'deselect'

	if myargs and isinstance(myargs[0], bytes):
		for i in range(len(myargs)):
			myargs[i] = portage._unicode_decode(myargs[i])

	myfiles += myargs

	return myaction, myopts, myfiles
Пример #25
0
def process_cmd_line():
    """
    Processes the command line arguments and sets up the
    system control variables accordingly. If an error occurred, an error message indicating the fault will be printed before the returning False.
    :return Returns options if no errors occurred, otherwise False.
    """
    # Set up parser
    opt_parser = OptionParser()
    opt_parser.prog = "direcMeasure"
    usage = set_usage(opt_parser.prog)
    opt_parser.set_usage(usage)
    opt_parser.set_defaults(run_type="f", verbose=False)

    # Main options
    opt_parser.add_option(
        "-c",
        "--config",
        type="string",
        action="store",
        dest="cfg",
        default='',
        help=
        "Configuration file used to control the system. Must be a JSON file.")
    opt_parser.add_option("-a",
                          "--alignOnly",
                          action="callback",
                          callback=config_run,
                          dest="run_type",
                          help="Only run the alignment routine.")
    opt_parser.add_option("--calibrate",
                          action="store_true",
                          dest="calibrate",
                          default=False,
                          help="Run the calibration interface.")
    opt_parser.add_option("--plot",
                          action="store_true",
                          dest="plot",
                          default=False,
                          help="Run the calibration interface.")
    # Plot options
    opt_parser.add_option("--dataFile",
                          type="string",
                          action="store",
                          dest="data_file",
                          default='',
                          help="Plot option. Input data file to plot")
    opt_parser.add_option(
        "--plotType",
        type="string",
        action="store",
        dest="plot_type",
        default='',
        help=
        f"Plot option. Type of plot to generate. Must be one of the following"
        f" {parser.ALLOWED_PLOT_TYPES}.")
    opt_parser.add_option(
        "--freq",
        type="string",
        action="store",
        dest="plot_freq",
        default='',
        help="Plot option. Frequency to plot at. Must be in Hz, MHz, or GHz")
    opt_parser.add_option(
        "--phi",
        type="float",
        action="store",
        dest="plot_phi",
        default=200.0,
        help="Plot option. Test phi angle to plot at. Must be in degrees "
        "and between -180 and 180 degrees.")
    opt_parser.add_option(
        "--theta",
        type="float",
        action="store",
        dest="plot_theta",
        default=200.0,
        help="Plot option. Test theta angle to plot at. Must be in degrees "
        "and between -180 and 180 degrees.")
    opt_parser.add_option(
        "--probePhi",
        type="float",
        action="store",
        dest="plot_p_phi",
        default=200.0,
        help="Plot option. Probe phi angle to plot at. Must be in degrees "
        "and between -180 and 180 degrees.")
    opt_parser.add_option("--sParams",
                          type="string",
                          action="store",
                          dest="sParams",
                          default="S21",
                          help="Plot option. S parameters to plot.")
    opt_parser.add_option("--logName",
                          type="string",
                          action="store",
                          dest="log_name",
                          default=None,
                          help="Filename for terminal output log.")
    opt_parser.add_option("--logPath",
                          type="string",
                          action="store",
                          dest="log_path",
                          default=None,
                          help="Filepath for terminal output log.")
    opt_parser.add_option(
        "--dataPath",
        type="string",
        action="store",
        dest="data_path",
        default=None,
        help="Filepath for data file taken during experiment.")
    opt_parser.add_option(
        "--dataName",
        type="string",
        action="store",
        dest="data_name",
        default=None,
        help="Filename for data file taken during experiment.")
    opt_parser.add_option(
        "--plotName",
        type="string",
        action="store",
        dest="plot_name",
        default=None,
        help="Filename for plot generated during experiment.")
    opt_parser.add_option(
        "--plotPath",
        type="string",
        action="store",
        dest="plot_path",
        default=None,
        help="Filepath for plot generated during experiment.")

    opt_parser.add_option(
        "--setTestPhi",
        type="float",
        action="store",
        dest="test_phi",
        default=None,
        help=
        "Sets the test-side phi angle to the specified angle. Must be in degrees "
        "and between -180 and 180 degrees.")
    opt_parser.add_option(
        "--zeroTestPhi",
        action="store_true",
        dest="zero_test_phi",
        default=False,
        help="Sets the current test-side phi angle to be the zero reference.")
    opt_parser.add_option(
        "--alignTestPhi",
        action="store_true",
        dest="align_test_phi",
        default=False,
        help="Aligns the test-side phi motor with the end-switch.")

    # Test Theta Options
    opt_parser.add_option(
        "--setTestTheta",
        type="float",
        action="store",
        dest="test_theta",
        default=None,
        help=
        "Sets the test-side theta angle to the specified angle. Must be in degrees "
        "and between -180 and 180 degrees.")
    opt_parser.add_option(
        "--zeroTestTheta",
        action="store_true",
        dest="zero_test_theta",
        default=False,
        help="Sets the current test-side theta angle to be the zero reference."
    )
    opt_parser.add_option(
        "--alignTestTheta",
        action="store_true",
        dest="align_test_theta",
        default=False,
        help="Aligns the test-side test motor with the end-switch.")

    # Probe Theta Options
    opt_parser.add_option(
        "--setProbePhi",
        type="float",
        action="store",
        dest="probe_phi",
        default=None,
        help=
        "Sets the probe-side phi angle to the specified angle. Must be in degrees "
        "and between -180 and 180 degrees.")
    opt_parser.add_option(
        "--zeroProbePhi",
        action="store_true",
        dest="zero_probe_phi",
        default=False,
        help="Sets the current probe-side phi angle to be the zero reference.")
    opt_parser.add_option(
        "--alignProbePhi",
        action="store_true",
        dest="align_probe_phi",
        default=False,
        help="Aligns the probe-side phi motor with the end-switch.")

    # Options determining how the motor will rotate
    opt_parser.add_option("--direction",
                          action="store",
                          dest="direction",
                          default=None,
                          help="The direction in which motor should rotate.")
    opt_parser.add_option(
        "--gradualAcceleration",
        action="store_true",
        dest="grad_accel",
        default=None,
        help=
        "Gradually accelerate the motor to its maximum frequency. Recommended for test-theta motor."
    )
    opt_parser.add_option(
        "--jumpAcceleration",
        action="store_false",
        dest="grad_accel",
        help=
        "Instantly accelerate the motor to its maximum frequency. Recommended for test-phi and probe-phi motors."
    )
    opt_parser.add_option(
        "--incremental",
        action="store_true",
        dest="incremental",
        default=False,
        help=
        "Whether input angle should be interpreted as absolute or relative to current angle."
    )

    # Check to make sure a config file was entered with the -c
    index = -1
    for i in range(len(sys.argv)):
        if sys.argv[i] == "-c" or sys.argv[i] == "--config":
            index = i + 1

    if index >= len(sys.argv) or index > 0 and opt_parser.has_option(
            sys.argv[index]):
        sys.argv.insert(index, None)

    # Parse command line
    (options, args) = opt_parser.parse_args()
    # print(options)

    # Check for single mode
    if options.test_phi != None or options.zero_test_phi or options.align_test_phi or \
            options.test_theta != None or options.zero_test_theta or options.align_test_theta \
            or options.probe_phi != None or options.zero_probe_phi or options.align_probe_phi:
        if options.run_type == 'f':
            options.run_type = 's'
        else:
            options.run_type = 'e'

    # Error Checking
    if options.run_type == "e":
        util.printf(
            curr_phase, "Error",
            "Cannot simultaneously run the alignment routine only and run the system with out "
            "the alignment routine. See usage for more information on command line options."
        )
        opt_parser.print_help()
        return False

    # Config file checks
    if options.cfg is None:
        util.printf(
            curr_phase, "Error",
            f"Configuration file flag detected but no configuration was detected. See usage "
            f"for more information on command line options. ")
        opt_parser.print_help()
        return False

    num_modes = int(options.cfg != '') + int(options.run_type == 'a') + int(options.run_type == 's') + \
                int(options.calibrate) + int(options.plot)

    if num_modes == 0:
        util.printf(
            curr_phase, "Error",
            "Cannot configure system as no command lines arguments were inputted."
            " See usage for more information on command line options. ")
        opt_parser.print_help()
        return False
    if num_modes > 1:
        util.printf(
            curr_phase, "Error",
            "Mutually-exclusive options specified. Cannot simultaneously run the "
            "calibration routine and the run the full run the system. See usage for more "
            "information on command line options.")
        opt_parser.print_help()
        return False
    if options.calibrate:
        options.run_type = "c"

    if options.plot:
        options.run_type = "p"
        if options.data_file == '':
            util.printf(
                curr_phase, "Error",
                f"Plotting requested but no input data file was entered."
                f" See usage for more information on command line options.")
            opt_parser.print_help()
            return False

        if options.data_file == '' or not options.data_file.endswith(".csv"):
            util.printf(
                curr_phase, "Error",
                f"The input data file entered '{options.data_file}' is not a csv file. "
                f" See usage for more information on command line options.")
            opt_parser.print_help()
            return False

        if options.plot_type == '':
            util.printf(
                curr_phase, "Error",
                f"Plotting requested but no plot type was specified. "
                f" See usage for more information on command line options.")
            opt_parser.print_help()
            return False

        if options.plot_type not in parser.ALLOWED_PLOT_TYPES:
            util.printf(
                curr_phase, "Error",
                f"Plotting requested but invalid plot type {options.plot_type} was specified. "
                f"Plot type must one of the following {parser.ALLOWED_PLOT_TYPES}"
                f" See usage for more information on command line options.")
            opt_parser.print_help()
            return False

        if options.plot_type == "cutPhi" and options.plot_phi == 200:
            util.printf(
                curr_phase, "Error",
                f"Phi cut plot requested but no phi angle was specified. "
                f" See usage for more information on command line options.")
            opt_parser.print_help()
            return False
        elif options.plot_type == "cutTheta" and options.plot_theta == 200:
            util.printf(
                curr_phase, "Error",
                f"Theta cut plot requested but no theta angle was specified. "
                f" See usage for more information on command line options.")
            opt_parser.print_help()
            return False

        if 'MHz' in options.plot_freq:
            options.plot_freq = 1e6 * float(options.plot_freq[:-3])
        elif 'GHz' in options.plot_freq:
            options.plot_freq = 1e9 * float(options.plot_freq[:-3])
        elif 'Hz' in options.plot_freq:
            options.plot_freq = float(options.plot_freq[:-3])
        else:
            util.printf(
                curr_phase, "Error",
                f"Plotting requested but invalid plot frequency {options.plot_freq} was specified. "
                f"Plot type must be in units of Hz, MHz, or GHz (e.g. 10GHz or \"10 GHz\")."
                f" See usage for more information on command line options.")
            opt_parser.print_help()
            return False

    if options.cfg != '' and not options.cfg.endswith(".json"):
        util.printf(
            curr_phase, "Error",
            f"The configuration file entered '{options.cfg}' is not a JSON file. "
            f" See the User Manual for more information on configuration files and "
            f"usage for more information on command line options.")
        opt_parser.print_help()
        return False

    return options
Пример #26
0
class CommandLineParser(object):

    # Defines what --regular means
    REGULAR_CMD = [
        'sslv2', 'sslv3', 'tlsv1', 'tlsv1_1', 'tlsv1_2', 'reneg', 'resum',
        'certinfo_basic', 'http_get', 'hide_rejected_ciphers', 'compression',
        'heartbleed', 'openssl_ccs', 'fallback'
    ]
    SSLYZE_USAGE = 'usage: %prog [options] target1.com target2.com:443 target3.com:443{ip} etc...'

    # StartTLS options
    START_TLS_PROTOCOLS = [
        'smtp', 'xmpp', 'xmpp_server', 'pop3', 'ftp', 'imap', 'ldap', 'rdp',
        'postgres', 'auto'
    ]
    START_TLS_USAGE = 'STARTTLS should be one of: {}. The \'auto\' option will cause SSLyze to deduce the protocol ' \
                      '(ftp, imap, etc.) from the supplied port number, ' \
                      'for each target servers.'.format(' , '.join(START_TLS_PROTOCOLS))

    # Mapping of StartTls protocols and ports; useful for starttls=auto
    STARTTLS_PROTOCOL_DICT = {
        'smtp': TlsWrappedProtocolEnum.STARTTLS_SMTP,
        587: TlsWrappedProtocolEnum.STARTTLS_SMTP,
        25: TlsWrappedProtocolEnum.STARTTLS_SMTP,
        'xmpp': TlsWrappedProtocolEnum.STARTTLS_XMPP,
        5222: TlsWrappedProtocolEnum.STARTTLS_XMPP,
        'xmpp_server': TlsWrappedProtocolEnum.STARTTLS_XMPP_SERVER,
        5269: TlsWrappedProtocolEnum.STARTTLS_XMPP_SERVER,
        'pop3': TlsWrappedProtocolEnum.STARTTLS_POP3,
        109: TlsWrappedProtocolEnum.STARTTLS_POP3,
        110: TlsWrappedProtocolEnum.STARTTLS_POP3,
        'imap': TlsWrappedProtocolEnum.STARTTLS_IMAP,
        143: TlsWrappedProtocolEnum.STARTTLS_IMAP,
        220: TlsWrappedProtocolEnum.STARTTLS_IMAP,
        'ftp': TlsWrappedProtocolEnum.STARTTLS_FTP,
        21: TlsWrappedProtocolEnum.STARTTLS_FTP,
        'ldap': TlsWrappedProtocolEnum.STARTTLS_LDAP,
        3268: TlsWrappedProtocolEnum.STARTTLS_LDAP,
        389: TlsWrappedProtocolEnum.STARTTLS_LDAP,
        'rdp': TlsWrappedProtocolEnum.STARTTLS_RDP,
        3389: TlsWrappedProtocolEnum.STARTTLS_RDP,
        'postgres': TlsWrappedProtocolEnum.STARTTLS_POSTGRES,
        5432: TlsWrappedProtocolEnum.STARTTLS_POSTGRES
    }

    def __init__(self, available_plugins, sslyze_version):
        """Generates SSLyze's command line parser.
        """

        self._parser = OptionParser(version=sslyze_version,
                                    usage=self.SSLYZE_USAGE)

        # Add generic command line options to the parser
        self._add_default_options()

        # Add plugin-specific options to the parser
        self._add_plugin_options(available_plugins)

        # Add the --regular command line parameter as a shortcut if possible
        regular_help = 'Regular HTTPS scan; shortcut for --{}'.format(
            ' --'.join(self.REGULAR_CMD))
        self._parser.add_option('--regular',
                                action="store_true",
                                dest=None,
                                help=regular_help)

    def parse_command_line(self):
        """Parses the command line used to launch SSLyze.
        """

        (args_command_list, args_target_list) = self._parser.parse_args()

        # Handle the --targets_in command line and fill args_target_list
        if args_command_list.targets_in:
            if args_target_list:
                raise CommandLineParsingError(
                    "Cannot use --targets_list and specify targets within the command line."
                )

            try:  # Read targets from a file
                with open(args_command_list.targets_in) as f:
                    for target in f.readlines():
                        if target.strip():  # Ignore empty lines
                            if not target.startswith(
                                    '#'):  # Ignore comment lines
                                args_target_list.append(target.strip())
            except IOError:
                raise CommandLineParsingError(
                    "Can't read targets from input file '{}.".format(
                        args_command_list.targets_in))

        if not args_target_list:
            raise CommandLineParsingError('No targets to scan.')

        # Handle the --regular command line parameter as a shortcut
        if self._parser.has_option('--regular'):
            if getattr(args_command_list, 'regular'):
                setattr(args_command_list, 'regular', False)
                for cmd in self.REGULAR_CMD:
                    setattr(args_command_list, cmd, True)

        # Sanity checks on the command line options
        # Prevent --quiet and --xml_out -
        if args_command_list.xml_file and args_command_list.xml_file == '-' and args_command_list.quiet:
            raise CommandLineParsingError(
                'Cannot use --quiet with --xml_out -.')

        # Prevent --quiet and --json_out -
        if args_command_list.json_file and args_command_list.json_file == '-' and args_command_list.quiet:
            raise CommandLineParsingError(
                'Cannot use --quiet with --json_out -.')

        # Prevent --xml_out - and --json_out -
        if args_command_list.json_file and args_command_list.json_file == '-' \
                and args_command_list.xml_file and args_command_list.xml_file == '-':
            raise CommandLineParsingError(
                'Cannot use --xml_out - with --json_out -.')

        # Sanity checks on the client cert options
        client_auth_creds = None
        if bool(args_command_list.cert) ^ bool(args_command_list.key):
            raise CommandLineParsingError(
                'No private key or certificate file were given. See --cert and --key.'
            )

        elif args_command_list.cert:
            # Private key formats
            if args_command_list.keyform == 'DER':
                key_type = SSL_FILETYPE_ASN1
            elif args_command_list.keyform == 'PEM':
                key_type = SSL_FILETYPE_PEM
            else:
                raise CommandLineParsingError(
                    '--keyform should be DER or PEM.')

            # Let's try to open the cert and key files
            try:
                client_auth_creds = ClientAuthenticationCredentials(
                    args_command_list.cert, args_command_list.key, key_type,
                    args_command_list.keypass)
            except ValueError as e:
                raise CommandLineParsingError(
                    'Invalid client authentication settings: {}.'.format(e[0]))

        # HTTP CONNECT proxy
        http_tunneling_settings = None
        if args_command_list.https_tunnel:
            try:
                http_tunneling_settings = HttpConnectTunnelingSettings.from_url(
                    args_command_list.https_tunnel)
            except ValueError as e:
                raise CommandLineParsingError(
                    'Invalid proxy URL for --https_tunnel: {}.'.format(e[0]))

        # STARTTLS
        tls_wrapped_protocol = TlsWrappedProtocolEnum.PLAIN_TLS
        if args_command_list.starttls:
            if args_command_list.starttls not in self.START_TLS_PROTOCOLS:
                raise CommandLineParsingError(self.START_TLS_USAGE)
            else:
                # StartTLS was specified
                if args_command_list.starttls in self.STARTTLS_PROTOCOL_DICT.keys(
                ):
                    # Protocol was given in the command line
                    tls_wrapped_protocol = self.STARTTLS_PROTOCOL_DICT[
                        args_command_list.starttls]

        # Number of connection retries
        if args_command_list.nb_retries < 1:
            raise CommandLineParsingError(
                'Cannot have a number smaller than 1 for --nb_retries.')

        # Create the server connectivity info for each specifed servers
        # A limitation when using the command line is that only one client_auth_credentials and http_tunneling_settings
        # can be specified, for all the servers to scan
        good_server_list = []
        bad_server_list = []
        for server_string in args_target_list:
            # Support unicode domains
            server_string = unicode(server_string, 'utf-8')
            try:
                good_server_list.append(
                    ServerConnectivityInfo.from_command_line(
                        server_string=server_string,
                        tls_wrapped_protocol=tls_wrapped_protocol,
                        tls_server_name_indication=args_command_list.sni,
                        xmpp_to_hostname=args_command_list.xmpp_to,
                        client_auth_credentials=client_auth_creds,
                        http_tunneling_settings=http_tunneling_settings))
            except ServerConnectivityError as e:
                # Will happen for example if the DNS lookup failed or the server string is malformed
                bad_server_list.append((server_string, e))
            except ValueError as e:
                # Will happen for example if xmpp_to is specified for a non-XMPP connection
                raise CommandLineParsingError(e[0])

        # Command line hacks
        # Handle --starttls=auto now that we parsed the server strings
        if args_command_list.starttls == 'auto':
            for server_info in good_server_list:
                # We use the port number to deduce the protocol
                if server_info.port in self.STARTTLS_PROTOCOL_DICT.keys():
                    server_info.tls_wrapped_protocol = self.STARTTLS_PROTOCOL_DICT[
                        server_info.port]

        # Handle --http_get now that we parsed the server strings
        # Doing it here is hacky as the option is defined within PluginOpenSSLCipherSuites
        if args_command_list.http_get:
            for server_info in good_server_list:
                if server_info.port == 443:
                    server_info.tls_wrapped_protocol = TlsWrappedProtocolEnum.HTTPS

        return good_server_list, bad_server_list, args_command_list

    def _add_default_options(self):
        """
        Adds default command line options to the parser.
        """

        # Client certificate options
        clientcert_group = OptionGroup(self._parser,
                                       'Client certificate support', '')
        clientcert_group.add_option(
            '--cert',
            help=
            'Client certificate chain filename. The certificates must be in PEM format and must be sorted '
            'starting with the subject\'s client certificate, followed by intermediate CA certificates if '
            'applicable.',
            dest='cert')
        clientcert_group.add_option('--key',
                                    help='Client private key filename.',
                                    dest='key')
        clientcert_group.add_option(
            '--keyform',
            help='Client private key format. DER or PEM (default).',
            dest='keyform',
            default='PEM')
        clientcert_group.add_option('--pass',
                                    help='Client private key passphrase.',
                                    dest='keypass',
                                    default='')
        self._parser.add_option_group(clientcert_group)

        # XML output
        self._parser.add_option(
            '--xml_out',
            help=
            'Writes the scan results as an XML document to the file XML_FILE. If XML_FILE is set to "-", the XML '
            'output will instead be printed to stdout.',
            dest='xml_file',
            default=None)
        # JSON output
        self._parser.add_option(
            '--json_out',
            help=
            'Writes the scan results as a JSON document to the file JSON_FILE. If JSON_FILE is set to "-", the '
            'JSON output will instead be printed to stdout.',
            dest='json_file',
            default=None)
        # Read targets from input file
        self._parser.add_option(
            '--targets_in',
            help=
            'Reads the list of targets to scan from the file TARGETS_IN. It should contain one host:port per '
            'line.',
            dest='targets_in',
            default=None)
        # Timeout
        self._parser.add_option(
            '--timeout',
            help=
            'Sets the timeout value in seconds used for every socket connection made to the target server(s). '
            'Default is {}s.'.format(str(SSLConnection.NETWORK_TIMEOUT)),
            type='int',
            dest='timeout',
            default=SSLConnection.NETWORK_TIMEOUT)
        # Control connection retry attempts
        self._parser.add_option(
            '--nb_retries',
            help=
            'Sets the number retry attempts for all network connections initiated throughout the scan. Increase '
            'this value if you are getting a lot of timeout/connection errors when scanning a specific server. '
            'Decrease this value to increase the speed of the scans; results may however return connection errors.'
            ' Default is {} connection attempts.'.format(
                str(SSLConnection.NETWORK_MAX_RETRIES)),
            type='int',
            dest='nb_retries',
            default=SSLConnection.NETWORK_MAX_RETRIES)
        # HTTP CONNECT Proxy
        self._parser.add_option(
            '--https_tunnel',
            help=
            'Tunnels all traffic to the target server(s) through an HTTP CONNECT proxy. HTTP_TUNNEL should be the '
            'proxy\'s URL: \'http://*****:*****@HOST:PORT/\'. For proxies requiring authentication, only Basic '
            'Authentication is supported.',
            dest='https_tunnel',
            default=None)
        # STARTTLS
        self._parser.add_option(
            '--starttls',
            help=
            'Performs StartTLS handshakes when connecting to the target server(s). '
            + self.START_TLS_USAGE,
            dest='starttls',
            default=None)
        self._parser.add_option(
            '--xmpp_to',
            help=
            'Optional setting for STARTTLS XMPP. XMPP_TO should be the hostname to be put in the \'to\' attribute '
            'of the XMPP stream. Default is the server\'s hostname.',
            dest='xmpp_to',
            default=None)
        # Server Name Indication
        self._parser.add_option(
            '--sni',
            help=
            'Use Server Name Indication to specify the hostname to connect to.  Will only affect TLS 1.0+ '
            'connections.',
            dest='sni',
            default=None)
        # No text output
        self._parser.add_option(
            '--quiet',
            action="store_true",
            dest='quiet',
            help=
            'Do not output anything to stdout; useful when using --xml_out or --json_out.'
        )

    def _add_plugin_options(self, available_plugins):
        """Recovers the list of command line options implemented by the available plugins and adds them to the command
        line parser.
        """
        for plugin_class in available_plugins:
            plugin_desc = plugin_class.get_interface()

            # Add the current plugin's commands to the parser
            group = OptionGroup(self._parser, plugin_desc.title,
                                plugin_desc.description)
            for cmd in plugin_desc.get_commands():
                group.add_option(cmd)

            # Add the current plugin's options to the parser
            for option in plugin_desc.get_options():
                group.add_option(option)

            self._parser.add_option_group(group)
Пример #27
0
class TestOptionParser(BaseTest):
    def setUp(self):
        self.parser = OptionParser()
        self.parser.add_option("-v",
                               "--verbose",
                               "-n",
                               "--noisy",
                               action="store_true",
                               dest="verbose")
        self.parser.add_option("-q",
                               "--quiet",
                               "--silent",
                               action="store_false",
                               dest="verbose")

    def test_add_option_no_Option(self):
        self.assertTypeError(self.parser.add_option,
                             "not an Option instance: None", None)

    def test_add_option_invalid_arguments(self):
        self.assertTypeError(self.parser.add_option, "invalid arguments", None,
                             None)

    def test_get_option(self):
        opt1 = self.parser.get_option("-v")
        self.assert_(isinstance(opt1, Option))
        self.assertEqual(opt1._short_opts, ["-v", "-n"])
        self.assertEqual(opt1._long_opts, ["--verbose", "--noisy"])
        self.assertEqual(opt1.action, "store_true")
        self.assertEqual(opt1.dest, "verbose")

    def test_get_option_equals(self):
        opt1 = self.parser.get_option("-v")
        opt2 = self.parser.get_option("--verbose")
        opt3 = self.parser.get_option("-n")
        opt4 = self.parser.get_option("--noisy")
        self.assert_(opt1 is opt2 is opt3 is opt4)

    def test_has_option(self):
        self.assert_(self.parser.has_option("-v"))
        self.assert_(self.parser.has_option("--verbose"))

    def assert_removed(self):
        self.assert_(self.parser.get_option("-v") is None)
        self.assert_(self.parser.get_option("--verbose") is None)
        self.assert_(self.parser.get_option("-n") is None)
        self.assert_(self.parser.get_option("--noisy") is None)

        self.failIf(self.parser.has_option("-v"))
        self.failIf(self.parser.has_option("--verbose"))
        self.failIf(self.parser.has_option("-n"))
        self.failIf(self.parser.has_option("--noisy"))

        self.assert_(self.parser.has_option("-q"))
        self.assert_(self.parser.has_option("--silent"))

    def test_remove_short_opt(self):
        self.parser.remove_option("-n")
        self.assert_removed()

    def test_remove_long_opt(self):
        self.parser.remove_option("--verbose")
        self.assert_removed()

    def test_remove_nonexistent(self):
        self.assertRaises(self.parser.remove_option,
                          ValueError,
                          "no such option 'foo'",
                          funcargs=['foo'])
                    c += 1
        else:
            if options.output:
                filename = options.output
            else:
                filename = inputfile
            output = "%s.png" % (os.path.splitext(filename)[0])
            c = 1
            while os.path.exists(output):
                output = "%s_%i.png" % (os.path.splitext(filename)[0], c)
                c += 1

        parser = SimpleParser(inputfile)
        if options.solution:
            solution = options.solution
        elif parser.has_option("solution"):
            solution = parser.get_option("solution")
        else:
            solution = None
        
        wordlist = parser.get_questions()
        cwd = CrossWord(options.columns, options.rows, " ", 5000, wordlist)
        score = cwd.compute_crossword(best_of=options.bestof, force_solved=False)   
    
        tmplist = [w.word.lower() for w in cwd.placed_words]
        missing = [w.word for w in cwd.wordlist if w.word.lower() not in tmplist]
        if missing != []:
            print("Could not place some words. Probably your grid is too small. Sometimes setting \"--bestof\" to a higer value also help.")
            print("Words that could not be placed: '%s'" % missing)
    
        if options.stats:
Пример #29
0
class LogrotateOptParser(object):
    '''
    Class for parsing commandline options of Python logrotating.

    @author: Frank Brehm
    @contact: [email protected]
    '''

    #-------------------------------------------------------
    def __init__(
        self,
        prog='%prog',
        version=None,
        local_dir=None,
    ):
        '''
        Constructor.

        @param prog:      The name of the calling process (e.g. sys.argv[0])
        @type prog:       str
        @param version:   The version string to use
        @type version:    str
        @param local_dir: The directory, where the i18n-files (*.mo)
                          are located. If None, then system default
                          (/usr/share/locale) is used.
        @type local_dir:  str or None

        @return: None
        '''

        self.prog = prog
        '''
        @ivar: The name of the calling process
        @type: str
        '''

        self.version = version
        '''
        @ivar: The version string to use
        @type: str
        '''

        self.local_dir = local_dir
        '''
        @ivar: The directory, where the i18n-files (*.mo) are located.
        @type: str or None
        '''

        self.t = gettext.translation('pylogrotate', local_dir, fallback=True)
        '''
        @ivar: a gettext translation object
        @type: gettext.translation
        '''

        _ = self.t.lgettext

        self.description = _('Rotates, compresses and mails system logs.')
        '''
        @ivar: description of the program
        @type: str
        '''

        msg = _("%s [options] <configfile>")
        self.usage = msg % (prog)
        '''
        @ivar: the usage string in getopt help output
        @type: str
        '''
        self.usage += ('       %s [-h|-?|--help]\n' % (prog))
        self.usage += ('       %s --usage\n' % (prog))
        self.usage += ('       %s --version' % (prog))

        self.options = None
        '''
        @ivar: a dict with all given commandline options
               after calling getOpts()
        @type: dict or None
        '''

        self.args = None
        '''
        @ivar: a list with all commandline parameters, what are not options
        @type: list or None
        '''

        self.parsed = False
        '''
        @ivar: flag, whether the parsing was done
        @type: bool
        '''

        if version:
            self.version = version

        self.parser = OptionParser(
            prog=self.prog,
            version=self.version,
            description=self.description,
            usage=self.usage,
            conflict_handler="resolve",
        )
        '''
        @ivar: the working OptionParser Object
        @type: optparse.OptionParser
        '''

        self._add_options()

    #-------------------------------------------------------
    def _add_options(self):
        '''
        Private function to add all necessary options
        to the OptionParser object
        '''

        #print ""
        #print "Default system encoding:     »%s«." \
        #   % (sys.getdefaultencoding())
        #print "Default filesystem encoding: »%s«." \
        #   % (sys.getfilesystemencoding())
        #print ""

        _ = self.t.lgettext

        if self.parser.has_option('--help'):
            self.parser.remove_option('--help')

        if self.parser.has_option('--version'):
            self.parser.remove_option('--version')

        msg = _('Set this do simulate commands')
        self.parser.add_option(
            '--simulate',
            '--test',
            '-T',
            default=False,
            action='store_true',
            dest='test',
            help=to_unicode_or_bust(msg),
        )

        msg = _('Set the verbosity level')
        self.parser.add_option(
            '--verbose',
            '-v',
            default=False,
            action='count',
            dest='verbose',
            help=to_unicode_or_bust(msg),
        )

        msg = _("Don't do anything, just test (implies -v and -T)")
        self.parser.add_option(
            '--debug',
            '-d',
            default=False,
            action='store_true',
            dest='debug',
            help=to_unicode_or_bust(msg),
        )

        msg = _("Force file rotation")
        self.parser.add_option(
            '--force',
            '-f',
            default=False,
            action='store_true',
            dest='force',
            help=to_unicode_or_bust(msg),
        )

        msg = _("Checks only the given configuration file and does " +
                "nothing. Conflicts with -f.")
        self.parser.add_option(
            '--config-check',
            '-c',
            default=False,
            action='store_true',
            dest='configcheck',
            help=to_unicode_or_bust(msg),
        )

        msg = _('Path of state file (different to configuration)')
        self.parser.add_option(
            '--state',
            '-s',
            dest="statefile",
            metavar='FILE',
            help=to_unicode_or_bust(msg),
        )

        msg = _('Path of PID file (different to configuration)')
        self.parser.add_option(
            '--pid-file',
            '-P',
            dest="pidfile",
            metavar='FILE',
            help=to_unicode_or_bust(msg),
        )

        msg = _("Command to send mail (instead of using SMTP or " +
                "the predefined sendmail command).")
        self.parser.add_option(
            '--mail',
            '-m',
            dest="mailcmd",
            metavar='CMD',
            help=to_unicode_or_bust(msg),
        )

        ######
        # Option group for common options

        group = OptionGroup(self.parser, _("Common options"))

        msg = _('Shows a help message and exit.')
        group.add_option(
            '-h',
            '-?',
            '--help',
            default=False,
            action='help',
            dest='help',
            help=to_unicode_or_bust(msg),
        )

        msg = _('Display brief usage message and exit.')
        group.add_option(
            '--usage',
            default=False,
            action='store_true',
            dest='usage',
            help=to_unicode_or_bust(msg),
        )

        msg = _('Shows the version number of the program and exit.')
        group.add_option(
            '-V',
            '--version',
            default=False,
            action='version',
            dest='version',
            help=to_unicode_or_bust(msg),
        )

        self.parser.add_option_group(group)

    #----------------------------------------------------------------------
    def getOpts(self):
        '''
        Wrapper function to OptionParser.parse_args().
        Sets self.options and self.args with the appropriate values.
        @return: None
        '''

        _ = self.t.lgettext

        if not self.parsed:
            self.options, self.args = self.parser.parse_args()
            self.parsed = True

        if self.options.usage:
            self.parser.print_usage()
            sys.exit(0)

        if self.options.force and self.options.configcheck:
            msg = _('Invalid usage of --force and --config-check.')
            raise LogrotateOptParserError(msg)

        if self.args is None or len(self.args) < 1:
            msg = _('No configuration file given.')
            raise LogrotateOptParserError(msg)

        if len(self.args) != 1:
            msg = _('Only one configuration file is allowed.')
            raise LogrotateOptParserError(msg)
Пример #30
0
def main():
    from optparse import OptionParser, OptionValueError

    parser = OptionParser(usage="usage: %prog [options] [projenv] ...", version="%%prog %s" % VERSION)

    auths = {}

    def _auth_callback(option, opt_str, value, parser, cls):
        info = value.split(",", 3)
        if len(info) != 3:
            raise OptionValueError("Incorrect number of parameters for %s" % option)

        env_name, filename, realm = info
        if env_name in auths:
            print >>sys.stderr, "Ignoring duplicate authentication option for " "project: %s" % env_name
        else:
            auths[env_name] = cls(os.path.abspath(filename), realm)

    def _validate_callback(option, opt_str, value, parser, valid_values):
        if value not in valid_values:
            raise OptionValueError("%s must be one of: %s, not %s" % (opt_str, "|".join(valid_values), value))
        setattr(parser.values, option.dest, value)

    parser.add_option(
        "-a",
        "--auth",
        action="callback",
        type="string",
        metavar="DIGESTAUTH",
        callback=_auth_callback,
        callback_args=(DigestAuthentication,),
        help="[projectdir],[htdigest_file],[realm]",
    )
    parser.add_option(
        "--basic-auth",
        action="callback",
        type="string",
        metavar="BASICAUTH",
        callback=_auth_callback,
        callback_args=(BasicAuthentication,),
        help="[projectdir],[htpasswd_file],[realm]",
    )

    parser.add_option("-p", "--port", action="store", type="int", dest="port", help="the port number to bind to")
    parser.add_option(
        "-b", "--hostname", action="store", dest="hostname", help="the host name or IP address to bind to"
    )
    parser.add_option(
        "--protocol",
        action="callback",
        type="string",
        dest="protocol",
        callback=_validate_callback,
        callback_args=(("http", "scgi", "ajp"),),
        help="http|scgi|ajp",
    )
    parser.add_option(
        "-e",
        "--env-parent-dir",
        action="store",
        dest="env_parent_dir",
        metavar="PARENTDIR",
        help="parent directory of the project environments",
    )
    parser.add_option(
        "--base-path", action="store", type="string", dest="base_path", help="base path"  # XXX call this url_base_path?
    )

    parser.add_option(
        "-r",
        "--auto-reload",
        action="store_true",
        dest="autoreload",
        help="restart automatically when sources are modified",
    )

    parser.add_option(
        "-s",
        "--single-env",
        action="store_true",
        dest="single_env",
        help="only serve a single " "project without the project list",
        default=False,
    )

    if os.name == "posix":
        parser.add_option(
            "-d", "--daemonize", action="store_true", dest="daemonize", help="run in the background as a daemon"
        )
        parser.add_option(
            "--pidfile", action="store", dest="pidfile", help="When daemonizing, file to which to write pid"
        )

    parser.set_defaults(port=None, hostname="", base_path="", daemonize=False, protocol="http")
    options, args = parser.parse_args()

    if not args and not options.env_parent_dir:
        parser.error("either the --env-parent-dir option or at least one " "environment must be specified")
    if options.single_env:
        if options.env_parent_dir:
            parser.error("the --single-env option cannot be used with " "--env-parent-dir")
        elif len(args) > 1:
            parser.error("the --single-env option cannot be used with " "more than one enviroment")

    if options.port is None:
        options.port = {"http": 80, "scgi": 4000, "ajp": 8009}[options.protocol]
    server_address = (options.hostname, options.port)

    # autoreload doesn't work when daemonized and using relative paths
    if options.daemonize and options.autoreload:
        for path in args + [options.env_parent_dir, options.pidfile]:
            if path and not os.path.isabs(path):
                parser.error(
                    '"%s" is not an absolute path.\n\n'
                    "when using both --auto-reload and --daemonize "
                    "all path arguments must be absolute" % path
                )

    # relative paths don't work when daemonized
    args = [os.path.abspath(a) for a in args]
    if options.env_parent_dir:
        options.env_parent_dir = os.path.abspath(options.env_parent_dir)
    if parser.has_option("pidfile") and options.pidfile:
        options.pidfile = os.path.abspath(options.pidfile)

    wsgi_app = TracEnvironMiddleware(dispatch_request, options.env_parent_dir, args, options.single_env)
    if auths:
        if options.single_env:
            project_name = os.path.basename(args[0])
            wsgi_app = AuthenticationMiddleware(wsgi_app, auths, project_name)
        else:
            wsgi_app = AuthenticationMiddleware(wsgi_app, auths)
    base_path = options.base_path.strip("/")
    if base_path:
        wsgi_app = BasePathMiddleware(wsgi_app, base_path)

    if options.protocol == "http":

        def serve():
            httpd = TracHTTPServer(server_address, wsgi_app, options.env_parent_dir, args)
            httpd.serve_forever()

    elif options.protocol in ("scgi", "ajp"):

        def serve():
            server_cls = __import__("flup.server.%s" % options.protocol, None, None, [""]).WSGIServer
            ret = server_cls(wsgi_app, bindAddress=server_address).run()
            sys.exit(ret and 42 or 0)  # if SIGHUP exit with status 42

    try:
        if os.name == "posix":
            if options.pidfile:
                options.pidfile = os.path.abspath(options.pidfile)
                if os.path.exists(options.pidfile):
                    pidfile = open(options.pidfile)
                    try:
                        pid = int(pidfile.read())
                    finally:
                        pidfile.close()

                    try:
                        # signal the process to see if it is still running
                        os.kill(pid, 0)
                    except OSError, e:
                        if e.errno != errno.ESRCH:
                            raise
                    else:
                        sys.exit("tracd is already running with pid %s" % pid)
                realserve = serve

                def serve():
                    try:
                        pidfile = open(options.pidfile, "w")
                        try:
                            pidfile.write(str(os.getpid()))
                        finally:
                            pidfile.close()
                        realserve()
                    finally:
                        if os.path.exists(options.pidfile):
                            os.remove(options.pidfile)

            if options.daemonize:
                daemon.daemonize()

        if options.autoreload:

            def modification_callback(file):
                print >>sys.stderr, "Detected modification of %s, restarting." % file

            autoreload.main(serve, modification_callback)
        else:
            serve()
Пример #31
0
class TreePlottingOptParser :
    def __init__(self) :
        from optparse import OptionParser
        self.p = OptionParser()
        # file steering
        self.p.add_option('--bkgs',type='string',default='',dest='bkgs',help='input files for bkg (csv)')
        self.p.add_option('--signal',type='string',default='',dest='signal',help='input files for signal (csv)')
        self.p.add_option('--data',type='string',default='',dest='data',help='input file for data (csv)')
        
        # can also be specified in the config file
        self.p.add_option('--fb',type='float',default=1,dest='fb',help='int luminosity (fb)')
        self.p.add_option('--treename',type='string',default='physics',dest='treename',help='Treename (physics, CollectionTree)')
        self.p.add_option('-v','--variables',type='string',default='',dest='variables',help='Variables (see Variables.cxx for names)')
        self.p.add_option('-c','--cuts',type='string',default='',dest='cuts',help='cut string')
        self.p.add_option('--weight',type='string',default='',dest='weight',help='Monte Carlo event weight')
        self.p.add_option('--weightscale',type='string',default='',dest='weightscale',help='(built-in) function for non-event weight (xs, feff, etc)')

        # point to config file
        self.p.add_option('--config',type='string',default='',dest='config',help='Input configuration file (python module)')

        # histogram limits - only really useful if you are plotting a single variable
        self.p.add_option('--limits',type='string',default='-1,-1,-1',dest='limits',help='Limits (only useful for single plot')

        # plot manipulation
        self.p.add_option('--ratio',action='store_true',default=False,dest='ratio',help='Plot as a ratio')
        self.p.add_option('--pull' ,action='store_true',default=False,dest='pull' ,help='Plot as a pull distribution')
        self.p.add_option('--poisson',action='store_true',default=False,dest='poisson',help='Poisson errors for data')
        self.p.add_option('--nostack',action='store_true',default=False,dest='nostack',help='do not stack')
        self.p.add_option('--normalize',action='store_true',default=False,dest='normalize',help='normalize')
        self.p.add_option('--showflows',action='store_true',default=False,dest='showflows',help='show overflows/underflows as first and last bin')
        self.p.add_option('--plottext',type='string',default='',dest='plottext',help='Additional plot text')

        # other options
        self.p.add_option('--batch',action='store_true',default=False,dest='batch',help='run in batch mode')
        self.p.add_option('--save',action='store_true',default=False,dest='save',help='save cans to pdf')
        self.p.add_option('--outdir',type='string',default='',dest='outdir',help='output directory')
        self.p.add_option('-l','--log',action='store_true',default=False,dest='log',help='log')
        self.p.add_option('--xAODInit',action='store_true',default=False,dest='xAODInit',help='run xAOD::Init()')
        self.p.add_option('--macro',type='string',default='',dest='macro',help='Load and run a macro')
        
    def parse_args(self) :
        import sys,os
        import ROOT
        import importlib
        #LoadRootCore()

        self.options,self.args = self.p.parse_args()

        ROOT.gROOT.SetBatch(self.options.batch)

        self.options.stack = not self.options.nostack

        if self.options.save and not self.options.outdir :
            self.options.outdir = os.getcwd()
        
        if self.options.signal and not '.root' in self.options.signal :
            dir = self.options.signal
            self.options.signal = ','.join('%s/%s'%(dir,a) for a in os.listdir(self.options.signal))

        if len(self.options.limits.split(',')) != 3 :
            print 'Error! Please specify --limits using 3 numbers in the format nbins,lowedge,highedge'
            sys.exit()

        self.options.variables = self.options.variables.split(',')
        self.options.plottext = self.options.plottext.split(',')


        # some defaults are not set in the option parser
        defaults = {'blindcut':[],
                    'truthcuts':[],
                    'mergesamples':dict(),
                    'colors':dict(),
                    'labels':dict(),
                    'histformat':dict(),
                    'usermodule':None,
                    'afterburner':None,
                    'customnormalize':None,
                    'variablemap':{},
                    }
        for k in defaults.keys() :
            setattr(self.options,k,defaults[k])




        # if you indicate 'HZY' then the function weightscaleHZY() will be used.
        if self.options.weightscale :
            print 'INFO: Using weightscale function weightscale%s(tree)'%(self.options.weightscale)
            self.options.weightscale = eval('weightscale%s'%(self.options.weightscale))
        else :
            def defaultweightscale(tfile) :
                return 1
            self.options.weightscale = defaultweightscale

        if self.options.fb <= 0 :
            self.options.fb = 1.

        if self.options.xAODInit :
            if not os.getenv('AtlasArea') :
                print 'Error! Specified --xAODInit but did not set up ATLAS! Exiting.'
                import sys; sys.exit()
            ROOT.xAOD.Init()

        # to get your current directory viewable by the code:
        sys.path.append(os.getcwd())
        # Read in options from config file:
        if self.options.config :
            usermodule = importlib.import_module(self.options.config.replace('.py',''))
            self.options.usermodule = usermodule

            for x in ['histformat','weight','weightscale','blindcut','truthcuts'
                      ,'treename','fb','colors','labels','mergesamples','bkgs','data','signal','plottext'
                      ,'afterburner','variablemap','customnormalize'] :
                if hasattr(usermodule,x) :
                    setattr(self.options,x,getattr(usermodule,x))

            if hasattr(usermodule,'cuts') :
                self.options.cuts = usermodule.cuts
                if len(self.options.cuts) > 1 :
                    for i,c in enumerate(self.options.cuts) :
                        self.options.cuts[i] = '('+c+')'

            if hasattr(usermodule,'variables') :
                self.options.variables = usermodule.variables

        # add .root to each background name.
        self.options.bkgs = ExpandWildcard(self.options.bkgs)
        self.options.bkgs = AddDotRoot(self.options.bkgs)
        self.options.signal = ExpandWildcard(self.options.signal)
        self.options.signal = AddDotRoot(self.options.signal)

        # add up multiple data files
        if self.options.data == 'all' :
            dirlist = os.listdir('.')
            datalist = []
            for i in dirlist :
                if (not '.root' in i) or (not 'data' in i) :
                    continue
                datalist.append(i)
            self.options.data = ','.join(datalist)

        self.options.data = ExpandWildcard(self.options.data)

        self.options.mergesamples['data'] = []
        for a in self.options.data.split(',') :
            if not a : continue
            self.options.mergesamples['data'].append(a.replace('.root',''))
        self.options.data = AddDotRoot(self.options.data)

        if self.p.has_option('--bkgs') :
            if (not self.options.bkgs) and (not self.options.signal) and (not self.options.data) :
                print 'No --bkgs, --signal, or --data specified. Exiting.'
                SafeExit(self.options.xAODInit)

        self.options.xlabel = dict()
        self.options.rebin = dict()

        # turn limits into variable-specific values
        tmp_limits = self.options.limits
        self.options.limits = dict()

        # Prepare stuff related to the variables.
        for v in self.options.variables + self.options.variablemap.values() :
            if v == '' : continue
            if v in self.options.histformat.keys() :
                if len(self.options.histformat[v]) < 4 :
                    self.options.histformat[v].append(v)
            else :
                n,low,high = tmp_limits.split(',')
                self.options.histformat[v] = [int(n),float(low),float(high),v]
            
            # set limits and xlabel:
            self.options.limits[v] = self.options.histformat[v][:3]
            self.options.xlabel[v] = self.options.histformat[v][3]

            if hasattr(self.options.usermodule,'rebin') and v in self.options.usermodule.rebin.keys() :
                self.options.rebin[v] = self.options.usermodule.rebin[v]
            

        # scripts will be looking for a python list of cuts
        if type(self.options.cuts) == type('') :
            self.options.cuts = [self.options.cuts]

        return self.options,self.args
Пример #32
0
def main(startstring):
    if not gottrac:
        rlog(100, 'tracserver', 'trac is not installed')
        return
    global httpd
    from optparse import OptionParser, OptionValueError
    parser = OptionParser(usage='usage: %prog [options] [projenv] ...',
                          version='%%prog %s' % VERSION)
    auths = {}

    def _auth_callback(option, opt_str, value, parser, cls):
        info = value.split(',', 3)
        if len(info) != 3:
            raise OptionValueError("Incorrect number of parameters for %s" %
                                   option)

        env_name, filename, realm = info
        auths[env_name] = cls(os.path.abspath(filename), realm)

    def _validate_callback(option, opt_str, value, parser, valid_values):
        if value not in valid_values:
            raise OptionValueError('%s must be one of: %s, not %s' %
                                   (opt_str, '|'.join(valid_values), value))
        setattr(parser.values, option.dest, value)

    parser.add_option('-a',
                      '--auth',
                      action='callback',
                      type='string',
                      metavar='DIGESTAUTH',
                      callback=_auth_callback,
                      callback_args=(DigestAuthentication, ),
                      help='[projectdir],[htdigest_file],[realm]')
    parser.add_option('--basic-auth',
                      action='callback',
                      type='string',
                      metavar='BASICAUTH',
                      callback=_auth_callback,
                      callback_args=(BasicAuthentication, ),
                      help='[projectdir],[htpasswd_file],[realm]')

    parser.add_option('-p',
                      '--port',
                      action='store',
                      type='int',
                      dest='port',
                      help='the port number to bind to')
    parser.add_option('-b',
                      '--hostname',
                      action='store',
                      dest='hostname',
                      help='the host name or IP address to bind to')
    parser.add_option('--protocol',
                      action='callback',
                      type="string",
                      dest='protocol',
                      callback=_validate_callback,
                      callback_args=(('http', 'scgi', 'ajp', 'fcgi'), ),
                      help='http|scgi|ajp|fcgi')
    parser.add_option('-e',
                      '--env-parent-dir',
                      action='store',
                      dest='env_parent_dir',
                      metavar='PARENTDIR',
                      help='parent directory of the project environments')
    parser.add_option(
        '--base-path',
        action='store',
        type='string',  # XXX call this url_base_path?
        dest='base_path',
        help='the initial portion of the request URL\'s "path"')

    parser.add_option('-r',
                      '--auto-reload',
                      action='store_true',
                      dest='autoreload',
                      help='restart automatically when sources are modified')

    parser.add_option('-s',
                      '--single-env',
                      action='store_true',
                      dest='single_env',
                      help='only serve a single '
                      'project without the project list',
                      default=False)

    if os.name == 'posix':
        parser.add_option('-d',
                          '--daemonize',
                          action='store_true',
                          dest='daemonize',
                          help='run in the background as a daemon')
        parser.add_option('--pidfile',
                          action='store',
                          dest='pidfile',
                          help='When daemonizing, file to which to write pid')
        parser.add_option('--umask',
                          action='store',
                          type='int',
                          dest='umask',
                          metavar='MASK',
                          help='When daemonizing, file mode creation mask '
                          'to use (default 022)')

    parser.set_defaults(port=None,
                        hostname='',
                        base_path='',
                        daemonize=False,
                        protocol='http',
                        umask=022)
    options, args = parser.parse_args(startstring.split())
    if not args and not options.env_parent_dir:
        parser.error('either the --env-parent-dir option or at least one '
                     'environment must be specified')
    if options.single_env:
        if options.env_parent_dir:
            parser.error('the --single-env option cannot be used with '
                         '--env-parent-dir')
        elif len(args) > 1:
            parser.error('the --single-env option cannot be used with '
                         'more than one enviroment')
    if options.daemonize and options.autoreload:
        parser.error('the --auto-reload option cannot be used with '
                     '--daemonize')

    if options.port is None:
        options.port = {
            'http': 80,
            'scgi': 4000,
            'ajp': 8009,
            'fcgi': 8000,
        }[options.protocol]
    server_address = (options.hostname, options.port)

    # relative paths don't work when daemonized
    args = [os.path.abspath(a) for a in args]
    if options.env_parent_dir:
        options.env_parent_dir = os.path.abspath(options.env_parent_dir)
    if parser.has_option('pidfile') and options.pidfile:
        options.pidfile = os.path.abspath(options.pidfile)

    wsgi_app = TracEnvironMiddleware(dispatch_request, options.env_parent_dir,
                                     args, options.single_env)
    if auths:
        if options.single_env:
            project_name = os.path.basename(args[0])
            wsgi_app = AuthenticationMiddleware(wsgi_app, auths, project_name)
        else:
            wsgi_app = AuthenticationMiddleware(wsgi_app, auths)
    base_path = options.base_path.strip('/')
    if base_path:
        wsgi_app = BasePathMiddleware(wsgi_app, base_path)

    try:
        httpd = TracHTTPServer(server_address, wsgi_app,
                               options.env_parent_dir, args)
    except socket.error, ex:
        if 'already in use' in str(ex):
            rlog(10, 'tserver', 'server is already running')
            return
Пример #33
0
class CommandLineParser():
    
    # Defines what --regular means
    REGULAR_CMD = ['sslv2', 'sslv3', 'tlsv1', 'reneg', 'resum', 'certinfo', 
                      'http_get', 'hide_rejected_ciphers', 'compression', 
                      'tlsv1_1', 'tlsv1_2']
    SSLYZE_USAGE = 'usage: %prog [options] target1.com target2.com:443 etc...'
    
    
    def __init__(self, available_plugins, sslyze_version, timeout):
        """
        Generates SSLyze's command line parser.
        """

        self._parser = OptionParser(version=sslyze_version,
                                    usage=self.SSLYZE_USAGE)
    
        # Add generic command line options to the parser
        self._add_default_options(timeout)
    
        # Add plugin-specific options to the parser
        self._add_plugin_options(available_plugins)
    
        # Add the --regular command line parameter as a shortcut if possible
        regular_help = 'Regular HTTPS scan; shortcut for'
        for cmd in self.REGULAR_CMD:
            regular_help += ' --' + cmd
            if (self._parser.has_option('--' + cmd) == False):
                return
        
        self._parser.add_option('--regular', action="store_true", dest=None,
                    help=regular_help)
                
        
    def parse_command_line(self):
        """
        Parses the command line used to launch SSLyze.
        """
    
        (args_command_list, args_target_list) = self._parser.parse_args()
    
        # Handle the --targets_in command line and fill args_target_list
        if args_command_list.targets_in:
            if args_target_list:
                raise CommandLineParsingError("Cannot use --targets_list and specify targets within the command line.")
                
            try: # Read targets from a file
                with open(args_command_list.targets_in) as f:
                    for target in f.readlines():
                        if target.strip(): # Ignore empty lines
                            if not target.startswith('#'): # Ignore comment lines
                                args_target_list.append(target.strip())
            except IOError:
                raise CommandLineParsingError("Can't read targets from input file '%s'." %  args_command_list.targets_in)
    
        if args_target_list == []:
            raise CommandLineParsingError('No targets to scan.')
    
        # Handle the --regular command line parameter as a shortcut
        if self._parser.has_option('--regular'):
            if getattr(args_command_list, 'regular'):
                setattr(args_command_list, 'regular', False)
                for cmd in self.REGULAR_CMD:
                    setattr(args_command_list, cmd, True)
                setattr(args_command_list, 'certinfo', 'basic') # Special case
                
        # Create the shared_settings object from looking at the command line
        shared_settings = self._process_parsing_results(args_command_list)
        
        return (args_command_list, args_target_list, shared_settings)


    def _add_default_options(self, timeout):
        """
        Adds default command line options to the parser.
        """
        
        # Client certificate options
        clientcert_group = OptionGroup(self._parser, 
            'Client certificate support', '')
        clientcert_group.add_option(
            '--cert',
            help='Client certificate filename.',
            dest='cert')
        clientcert_group.add_option(
            '--certform',
            help= 'Client certificate format. DER or PEM (default).',
            dest='certform',
            default='PEM')
        clientcert_group.add_option(
            '--key',
            help= 'Client private key filename.',
            dest='key')
        clientcert_group.add_option(
            '--keyform',
            help= 'Client private key format. DER or PEM (default).',
            dest='keyform',
            default='PEM')
        clientcert_group.add_option(
            '--pass',
            help= 'Client private key passphrase.',
            dest='keypass')
        self._parser.add_option_group(clientcert_group)
    
        # XML output
        self._parser.add_option(
            '--xml_out',
            help= ('Writes the scan results as an XML document to the file XML_FILE.'),
            dest='xml_file',
            default=None)
    
        # Read targets from input file
        self._parser.add_option(
            '--targets_in',
            help= ('Reads the list of targets to scan from the file TARGETS_IN. It should contain one host:port per line.'),
            dest='targets_in',
            default=None)
    
        # Timeout
        self._parser.add_option(
            '--timeout',
            help= (
                'Sets the timeout value in seconds used for every socket '
                'connection made to the target server(s). Default is 5s.'),
            type='int',
            dest='timeout',
            default=timeout)

    
        # Number of processes.
        self._parser.add_option(
            '--max_processes',
            help= (
                'Sets the maximum number of concurrent processes used '
                ' for scanning. Default is 5 processes.'),
            type='int',
            dest='processes',
            default=timeout)

    
        # Verbosity
        self._parser.add_option(
            '--verbosity',
            help= (
                'Increases the verbosity of the program. '
                'Usable values in the range 0..3. Default is 0.'),
            type='int',
            dest='verbosity',
            default=0)
    
        
        # HTTP CONNECT Proxy
        self._parser.add_option(
            '--https_tunnel',
            help= (
                'Sets an HTTP CONNECT proxy to tunnel SSL traffic to the target '
                'server(s). HTTP_TUNNEL should be \'host:port\'. ' 
                'Requires Python 2.7'),
            dest='https_tunnel',
            default=None)
        
        # STARTTLS
        self._parser.add_option(
            '--starttls',
            help= (
                'Identifies the target server(s) protocols (FTP, SMTP, XMPP etc) '
                'and scans the server(s) using STARTTLS. '
                'STARTTLS should be \'ftp\', \'imap\', \'ldap\', '
                '\'pop3\', \'smtp\' or \'xmpp\'. '
                'Alternatively \'auto\' can be given and the protocol will be '
                'selected based on the given port number.'),
            dest='starttls',
            default=None)
    
        self._parser.add_option(
            '--xmpp_to',
            help= (
                'Optional setting for STARTTLS XMPP. '
                ' XMPP_TO should be the hostname to be put in the \'to\' attribute '
                'of the XMPP stream. Default is the server\'s hostname.'),
            dest='xmpp_to',
            default=None)
        
        # Server Name Indication
        self._parser.add_option(
            '--sni',
            help= (
                'Use Server Name Indication to specify the hostname to connect to.'
                ' Will only affect TLS 1.0+ connections.'),
            dest='sni',
            default=None)

    def _add_plugin_options(self, available_plugins):
        """
        Recovers the list of command line options implemented by the available
        plugins and adds them to the command line parser.
        """
        
        for plugin_class in available_plugins:
            plugin_desc = plugin_class.get_interface()
    
            # Add the current plugin's commands to the parser
            group = OptionGroup(self._parser, plugin_desc.title,\
                                plugin_desc.description)
            for cmd in plugin_desc.get_commands():
                    group.add_option(cmd)

            # Add the current plugin's options to the parser
            for option in plugin_desc.get_options():
                    group.add_option(option)

            self._parser.add_option_group(group)


    def _process_parsing_results(self, args_command_list):
        """
        Performs various sanity checks on the command line that was used to 
        launch SSLyze.
        Returns the shared_settings object to be fed to plugins.
        """
        
        shared_settings = {}
        # Sanity checks on the client cert options
        if bool(args_command_list.cert) ^ bool(args_command_list.key):
            raise CommandLineParsingError('No private key or certificate file were given. See --cert and --key.')
        
        # Let's try to open the cert and key files
        if args_command_list.cert:
            try:
                open(args_command_list.cert,"r")
            except:
                raise CommandLineParsingError('Could not open the client certificate file "' + str(args_command_list.cert) + '".')

        if args_command_list.key:    
            try:
                open(args_command_list.key,"r")
            except:
                raise CommandLineParsingError('Could not open the client private key file "' + str(args_command_list.key) + '"')
    
        # Parse client cert options
        if args_command_list.certform not in ['DER', 'PEM']:
            raise CommandLineParsingError('--certform should be DER or PEM.')
    
        if args_command_list.keyform not in ['DER', 'PEM']:
            raise CommandLineParsingError('--keyform should be DER or PEM.')
    
            
        # HTTP CONNECT proxy
        if args_command_list.https_tunnel:
            if '2.7.' not in platform.python_version(): # Python 2.7 only
                raise CommandLineParsingError(
                    '--https_tunnel requires Python 2.7.X. '
                    'Current version is ' + platform.python_version() + '.')
                
            try: # Need to parse the proxy host:port string now
                proxy_test = SSLServerTester(args_command_list.https_tunnel)
                shared_settings['https_tunnel_host'] = proxy_test.get_target()[0]
                shared_settings['https_tunnel_port'] = proxy_test.get_target()[2]
            except InvalidTargetError:
                raise CommandLineParsingError(
                    'Not a valid host/port for --https_tunnel'
                    ', discarding all tasks.')
                
        else:
            shared_settings['https_tunnel_host'] = None
            shared_settings['https_tunnel_port'] = None
            
        # STARTTLS
        if args_command_list.starttls not in [None,'auto', 'ftp', 'imap', 'ldap', 'pop3', 'smtp','xmpp']:
            raise CommandLineParsingError(
                '--starttls should be \'smtp\', \'xmpp\' or \'auto\'.')
        
        if args_command_list.starttls and args_command_list.https_tunnel:
            raise CommandLineParsingError(
                'Cannot have --https_tunnel and --starttls at the same time.')   
        
        # All good, let's save the data    
        for key, value in args_command_list.__dict__.iteritems():
            shared_settings[key] = value
    
        return shared_settings
Пример #34
0
def run():
    parser = OptionParser()
    parser.add_option("-d", "--database", dest="database", default="deska_dev",
                      help="Name of the database to use", metavar="DB")
    parser.add_option("-U", "--username", dest="username",
                      help="User to connect to the DB", metavar="USER")
    parser.add_option("--logfile", dest="logfile", default="deska_server.log",
                      help="File name of the debug log")
    parser.add_option("--log-stderr", dest="log_stderr", action="store_true",
                      default=False, help="Log to standard error")

    parser.add_option("--cfggen-backend", dest="cfggenBackend", metavar="METHOD",
                      default="error", help=
                          "Configuration method to use: error (throw errors upon "
                          "using the configuration generators), fake (just do "
                          "nothing, but do not throw errors) or git (work with a "
                          "git repository)")
    parser.add_option("--cfggen-script-path", dest="cfggenScriptPath", default=None,
                      metavar="PATH", help="Path to use when looking for the actual "
                          "executables used for generating configuration")
    parser.add_option("--cfggen-git-repository", dest="cfggenGitRepo", default=None,
                      metavar="PATH", help="Path of a git repository to use. Git "
                          "will call `git push` from this repository, so this cannot "
                          "be the master repo.")
    parser.add_option("--cfggen-git-workdir", dest="cfggenGitWorkdir", default=None,
                      metavar="PATH", help="Path to use for storing git working "
                        "directories for each changeset")

    (options, args) = parser.parse_args()
    # file the variables from environment
    if not parser.has_option("database") and os.environ.has_key("DESKA_DB"):
        options.database = os.environ["DESKA_DB"]
    if not parser.has_option("username") and os.environ.has_key("DESKA_USER"):
        options.username = os.environ["DESKA_USER"]
    if not parser.has_option("cfggenBackend") and os.environ.has_key("DESKA_CFGGEN_BACKEND"):
        options.cfggenBackend = os.environ["DESKA_CFGGEN_BACKEND"]
    if not parser.has_option("cfggenScriptPath") and os.environ.has_key("DESKA_CFGGEN_SCRIPTS"):
        options.cfggenScriptPath = os.environ["DESKA_CFGGEN_SCRIPTS"]
    if not parser.has_option("cfggenGitRepo") and os.environ.has_key("DESKA_CFGGEN_GIT_PRIMARY_CLONE"):
        options.cfggenGitRepo = os.environ["DESKA_CFGGEN_GIT_PRIMARY_CLONE"]
    if not parser.has_option("cfggenGitWorkdir") and os.environ.has_key("DESKA_CFGGEN_GIT_WC"):
        options.cfggenGitWorkdir = os.environ["DESKA_CFGGEN_GIT_WC"]
    if (options.log_stderr and options.logfile):
        # basicConfig() won't add duplicate loggers
        parser.error("Cannot log to both file and stderr -- too lazy")
    if options.cfggenBackend not in ("error", "fake", "git"):
        parser.error("Unsupported backend for configuration generators")

    logformat_pid = "%(levelname)s:%(name)s:%(process)s:%(message)s"
    if options.logfile:
        logging.basicConfig(filename = options.logfile, level=logging.DEBUG, format=logformat_pid)
    elif options.log_stderr:
        logging.basicConfig(stream = sys.stderr, level=logging.DEBUG, format=logformat_pid)
    else:
        logging.basicConfig(stream = sys.stderr, level=logging.CRITICAL, format=logformat_pid)

    logging.debug("starting deska server")

    dbargs = {}
    if options.database:
        dbargs["database"] = options.database
    if options.username:
        dbargs["user"] = options.username

    # Redirecting the stdout to stderr. This is required in order to support the
    # GIT_PYTHON_TRACE which blindly uses `print` for its debug output (and
    # clobbers our precious DBAPI communication that way).
    # Do NOT ever try to capture stderr this way, this will lead to infinite loops.
    orig_stdout = sys.stdout
    sys.stdout = StreamLogger()

    try:
        # Make sure that Ctrl-C on the remote side won't ever propagate to us, so that
        # we don't have to deal with KeyboardInterrupt exception
        os.setsid()
    except OSError, e:
        if e.errno == errno.EPERM:
            # we're already a session leader -> do nothing
            pass
        else:
            raise
Пример #35
0
def parse_opts(tmpcmdline, silent=False):
	myaction=None
	myopts = {}
	myfiles=[]

	global options, shortmapping

	actions = frozenset([
		"clean", "config", "depclean", "help",
		"info", "list-sets", "metadata",
		"prune", "regen",  "search",
		"sync",  "unmerge", "version",
	])

	longopt_aliases = {"--cols":"--columns", "--skip-first":"--skipfirst"}
	argument_options = {
		"--accept-properties": {
			"help":"temporarily override ACCEPT_PROPERTIES",
			"action":"store"
		},

		"--backtrack": {

			"help"   : "Specifies how many times to backtrack if dependency " + \
				"calculation fails ",

			"action" : "store"
		},

		"--config-root": {
			"help":"specify the location for portage configuration files",
			"action":"store"
		},
		"--color": {
			"help":"enable or disable color output",
			"type":"choice",
			"choices":("y", "n")
		},

		"--complete-graph": {
			"help"    : "completely account for all known dependencies",
			"type"    : "choice",
			"choices" : ("True", "n")
		},

		"--deep": {

			"shortopt" : "-D",

			"help"   : "Specifies how deep to recurse into dependencies " + \
				"of packages given as arguments. If no argument is given, " + \
				"depth is unlimited. Default behavior is to skip " + \
				"dependencies of installed packages.",

			"action" : "store"
		},

		"--deselect": {
			"help"    : "remove atoms/sets from the world file",
			"type"    : "choice",
			"choices" : ("True", "n")
		},

		"--exclude": {
			"help"   :"A space separated list of package names or slot atoms. " + \
				"Emerge won't  install any ebuild or binary package that " + \
				"matches any of the given package atoms.",

			"action" : "append"
		},

		"--fail-clean": {
			"help"    : "clean temp files after build failure",
			"type"    : "choice",
			"choices" : ("True", "n")
		},

		"--jobs": {

			"shortopt" : "-j",

			"help"   : "Specifies the number of packages to build " + \
				"simultaneously.",

			"action" : "store"
		},

		"--keep-going": {
			"help"    : "continue as much as possible after an error",
			"type"    : "choice",
			"choices" : ("True", "n")
		},

		"--load-average": {

			"help"   :"Specifies that no new builds should be started " + \
				"if there are other builds running and the load average " + \
				"is at least LOAD (a floating-point number).",

			"action" : "store"
		},

		"--with-bdeps": {
			"help":"include unnecessary build time dependencies",
			"type":"choice",
			"choices":("y", "n")
		},
		"--reinstall": {
			"help":"specify conditions to trigger package reinstallation",
			"type":"choice",
			"choices":["changed-use"]
		},

		"--binpkg-respect-use": {
			"help"    : "discard binary packages if their use flags \
				don't match the current configuration",
			"type"    : "choice",
			"choices" : ("True", "y", "n")
		},

		"--getbinpkg": {
			"shortopt" : "-g",
			"help"     : "fetch binary packages",
			"type"     : "choice",
			"choices"  : ("True", "n")
		},

		"--getbinpkgonly": {
			"shortopt" : "-G",
			"help"     : "fetch binary packages only",
			"type"     : "choice",
			"choices"  : ("True", "n")
		},

		"--rebuilt-binaries": {
			"help"     : "replace installed packages with binary " + \
			             "packages that have been rebuilt",
			"type"     : "choice",
			"choices"  : ("True", "n")
		},
		
		"--rebuilt-binaries-timestamp": {
			"help"   : "use only binaries that are newer than this " + \
			           "timestamp for --rebuilt-binaries",
			"action" : "store"
		},

		"--root": {
		 "help"   : "specify the target root filesystem for merging packages",
		 "action" : "store"
		},

		"--root-deps": {
			"help"    : "modify interpretation of depedencies",
			"type"    : "choice",
			"choices" :("True", "rdeps")
		},

		"--select": {
			"help"    : "add specified packages to the world set " + \
			            "(inverse of --oneshot)",
			"type"    : "choice",
			"choices" : ("True", "n")
		},

		"--selective": {
			"help"    : "similar to the --noreplace but does not take " + \
			            "precedence over options such as --newuse",
			"type"    : "choice",
			"choices" : ("True", "n")
		},

		"--use-ebuild-visibility": {
			"help"     : "use unbuilt ebuild metadata for visibility checks on built packages",
			"type"     : "choice",
			"choices"  : ("True", "n")
		},

		"--usepkg": {
			"shortopt" : "-k",
			"help"     : "use binary packages",
			"type"     : "choice",
			"choices"  : ("True", "n")
		},

		"--usepkgonly": {
			"shortopt" : "-K",
			"help"     : "use only binary packages",
			"type"     : "choice",
			"choices"  : ("True", "n")
		},

	}

	from optparse import OptionParser
	parser = OptionParser()
	if parser.has_option("--help"):
		parser.remove_option("--help")

	for action_opt in actions:
		parser.add_option("--" + action_opt, action="store_true",
			dest=action_opt.replace("-", "_"), default=False)
	for myopt in options:
		parser.add_option(myopt, action="store_true",
			dest=myopt.lstrip("--").replace("-", "_"), default=False)
	for shortopt, longopt in shortmapping.items():
		parser.add_option("-" + shortopt, action="store_true",
			dest=longopt.lstrip("--").replace("-", "_"), default=False)
	for myalias, myopt in longopt_aliases.items():
		parser.add_option(myalias, action="store_true",
			dest=myopt.lstrip("--").replace("-", "_"), default=False)

	for myopt, kwargs in argument_options.items():
		shortopt = kwargs.pop("shortopt", None)
		args = [myopt]
		if shortopt is not None:
			args.append(shortopt)
		parser.add_option(dest=myopt.lstrip("--").replace("-", "_"),
			*args, **kwargs)

	tmpcmdline = insert_optional_args(tmpcmdline)

	myoptions, myargs = parser.parse_args(args=tmpcmdline)

	if myoptions.changed_use is not False:
		myoptions.reinstall = "changed-use"
		myoptions.changed_use = False

	if myoptions.deselect == "True":
		myoptions.deselect = True

	if myoptions.binpkg_respect_use in ("y", "True",):
		myoptions.binpkg_respect_use = True
	else:
		myoptions.binpkg_respect_use = None

	if myoptions.complete_graph in ("y", "True",):
		myoptions.complete_graph = True
	else:
		myoptions.complete_graph = None

	if myoptions.exclude:
		exclude = []
		bad_atoms = []
		for x in ' '.join(myoptions.exclude).split():
			bad_atom = False
			try:
				atom = portage.dep.Atom(x)
			except portage.exception.InvalidAtom:
				try:
					atom = portage.dep.Atom("null/"+x)
				except portage.exception.InvalidAtom:
					bad_atom = True
			
			if bad_atom:
				bad_atoms.append(x)
			else:
				if atom.operator or atom.blocker or atom.use:
					bad_atoms.append(x)
				else:
					exclude.append(atom)

		if bad_atoms and not silent:
			parser.error("Invalid Atom(s) in --exclude parameter: '%s' (only package names and slot atoms allowed)\n" % \
				(",".join(bad_atoms),))

	if myoptions.fail_clean == "True":
		myoptions.fail_clean = True

	if myoptions.getbinpkg in ("True",):
		myoptions.getbinpkg = True
	else:
		myoptions.getbinpkg = None

	if myoptions.getbinpkgonly in ("True",):
		myoptions.getbinpkgonly = True
	else:
		myoptions.getbinpkgonly = None

	if myoptions.keep_going in ("True",):
		myoptions.keep_going = True
	else:
		myoptions.keep_going = None

	if myoptions.rebuilt_binaries in ("True",):
		myoptions.rebuilt_binaries = True

	if myoptions.root_deps == "True":
		myoptions.root_deps = True

	if myoptions.select == "True":
		myoptions.select = True
		myoptions.oneshot = False
	elif myoptions.select == "n":
		myoptions.oneshot = True

	if myoptions.selective == "True":
		myoptions.selective = True

	if myoptions.backtrack is not None:

		try:
			backtrack = int(myoptions.backtrack)
		except (OverflowError, ValueError):
			backtrack = -1

		if backtrack < 0:
			backtrack = None
			if not silent:
				parser.error("Invalid --backtrack parameter: '%s'\n" % \
					(myoptions.backtrack,))

		myoptions.backtrack = backtrack

	if myoptions.deep is not None:
		deep = None
		if myoptions.deep == "True":
			deep = True
		else:
			try:
				deep = int(myoptions.deep)
			except (OverflowError, ValueError):
				deep = -1

		if deep is not True and deep < 0:
			deep = None
			if not silent:
				parser.error("Invalid --deep parameter: '%s'\n" % \
					(myoptions.deep,))

		myoptions.deep = deep

	if myoptions.jobs:
		jobs = None
		if myoptions.jobs == "True":
			jobs = True
		else:
			try:
				jobs = int(myoptions.jobs)
			except ValueError:
				jobs = -1

		if jobs is not True and \
			jobs < 1:
			jobs = None
			if not silent:
				parser.error("Invalid --jobs parameter: '%s'\n" % \
					(myoptions.jobs,))

		myoptions.jobs = jobs

	if myoptions.load_average:
		try:
			load_average = float(myoptions.load_average)
		except ValueError:
			load_average = 0.0

		if load_average <= 0.0:
			load_average = None
			if not silent:
				parser.error("Invalid --load-average parameter: '%s'\n" % \
					(myoptions.load_average,))

		myoptions.load_average = load_average
	
	if myoptions.rebuilt_binaries_timestamp:
		try:
			rebuilt_binaries_timestamp = int(myoptions.rebuilt_binaries_timestamp)
		except ValueError:
			rebuilt_binaries_timestamp = -1

		if rebuilt_binaries_timestamp < 0:
			rebuilt_binaries_timestamp = 0
			if not silent:
				parser.error("Invalid --rebuilt-binaries-timestamp parameter: '%s'\n" % \
					(myoptions.rebuilt_binaries_timestamp,))

		myoptions.rebuilt_binaries_timestamp = rebuilt_binaries_timestamp

	if myoptions.use_ebuild_visibility in ("True",):
		myoptions.use_ebuild_visibility = True
	else:
		myoptions.use_ebuild_visibility = None

	if myoptions.usepkg in ("True",):
		myoptions.usepkg = True
	else:
		myoptions.usepkg = None

	if myoptions.usepkgonly in ("True",):
		myoptions.usepkgonly = True
	else:
		myoptions.usepkgonly = None

	for myopt in options:
		v = getattr(myoptions, myopt.lstrip("--").replace("-", "_"))
		if v:
			myopts[myopt] = True

	for myopt in argument_options:
		v = getattr(myoptions, myopt.lstrip("--").replace("-", "_"), None)
		if v is not None:
			myopts[myopt] = v

	if myoptions.searchdesc:
		myoptions.search = True

	for action_opt in actions:
		v = getattr(myoptions, action_opt.replace("-", "_"))
		if v:
			if myaction:
				multiple_actions(myaction, action_opt)
				sys.exit(1)
			myaction = action_opt

	if myaction is None and myoptions.deselect is True:
		myaction = 'deselect'

	if myargs and sys.hexversion < 0x3000000 and \
		not isinstance(myargs[0], unicode):
		for i in range(len(myargs)):
			myargs[i] = portage._unicode_decode(myargs[i])

	myfiles += myargs

	return myaction, myopts, myfiles
Пример #36
0
def main():
    from optparse import OptionParser, OptionValueError
    parser = OptionParser(usage='usage: %prog [options] [projenv] ...',
                          version='%%prog %s' % VERSION)

    auths = {}
    def _auth_callback(option, opt_str, value, parser, cls):
        info = value.split(',', 3)
        if len(info) != 3:
            raise OptionValueError("Incorrect number of parameters for %s"
                                   % option)

        env_name, filename, realm = info
        if env_name in auths:
            print >> sys.stderr, 'Ignoring duplicate authentication option ' \
                                 'for project: %s' % env_name
        else:
            auths[env_name] = cls(os.path.abspath(filename), realm)

    def _validate_callback(option, opt_str, value, parser, valid_values):
        if value not in valid_values:
            raise OptionValueError('%s must be one of: %s, not %s'
                                   % (opt_str, '|'.join(valid_values), value))
        setattr(parser.values, option.dest, value)

    def _octal(option, opt_str, value, parser):
        try:
            setattr(parser.values, option.dest, int(value, 8))
        except ValueError:
            raise OptionValueError('Invalid octal umask value: %r' % value)

    parser.add_option('-a', '--auth', action='callback', type='string',
                      metavar='DIGESTAUTH', callback=_auth_callback,
                      callback_args=(DigestAuthentication,),
                      help='[projectdir],[htdigest_file],[realm]')
    parser.add_option('--basic-auth', action='callback', type='string',
                      metavar='BASICAUTH', callback=_auth_callback,
                      callback_args=(BasicAuthentication,),
                      help='[projectdir],[htpasswd_file],[realm]')

    parser.add_option('-p', '--port', action='store', type='int', dest='port',
                      help='the port number to bind to')
    parser.add_option('-b', '--hostname', action='store', dest='hostname',
                      help='the host name or IP address to bind to')
    parser.add_option('--protocol', action='callback', type="string",
                      dest='protocol', callback=_validate_callback,
                      callback_args=(('http', 'scgi', 'ajp', 'fcgi'),),
                      help='http|scgi|ajp|fcgi')
    parser.add_option('-q', '--unquote', action='store_true',
                      dest='unquote',
                      help='unquote PATH_INFO (may be needed when using ajp)')
    parser.add_option('--http10', action='store_false', dest='http11',
                      help='use HTTP/1.0 protocol version instead of HTTP/1.1')
    parser.add_option('--http11', action='store_true', dest='http11',
                      help='use HTTP/1.1 protocol version (default)')
    parser.add_option('-e', '--env-parent-dir', action='store',
                      dest='env_parent_dir', metavar='PARENTDIR',
                      help='parent directory of the project environments')
    parser.add_option('--base-path', action='store', type='string', # XXX call this url_base_path?
                      dest='base_path',
                      help='the initial portion of the request URL\'s "path"')

    parser.add_option('-r', '--auto-reload', action='store_true',
                      dest='autoreload',
                      help='restart automatically when sources are modified')

    parser.add_option('-s', '--single-env', action='store_true',
                      dest='single_env', help='only serve a single '
                      'project without the project list', default=False)

    if os.name == 'posix':
        parser.add_option('-d', '--daemonize', action='store_true',
                          dest='daemonize',
                          help='run in the background as a daemon')
        parser.add_option('--pidfile', action='store',
                          dest='pidfile',
                          help='when daemonizing, file to which to write pid')
        parser.add_option('--umask', action='callback', type='string',
                          dest='umask', metavar='MASK', callback=_octal,
                          help='when daemonizing, file mode creation mask '
                          'to use, in octal notation (default 022)')

        try:
            import grp, pwd
            
            def _group(option, opt_str, value, parser):
                try:
                    value = int(value)
                except ValueError:
                    try:
                        value = grp.getgrnam(value)[2]
                    except KeyError:
                        raise OptionValueError('group not found: %r' % value)
                setattr(parser.values, option.dest, value)

            def _user(option, opt_str, value, parser):
                try:
                    value = int(value)
                except ValueError:
                    try:
                        value = pwd.getpwnam(value)[2]
                    except KeyError:
                        raise OptionValueError('user not found: %r' % value)
                setattr(parser.values, option.dest, value)
            
            parser.add_option('--group', action='callback', type='string',
                              dest='group', metavar='GROUP', callback=_group,
                              help='the group to run as')
            parser.add_option('--user', action='callback', type='string',
                              dest='user', metavar='USER', callback=_user,
                              help='the user to run as')
        except ImportError:
            pass

    parser.set_defaults(port=None, hostname='', base_path='', daemonize=False,
                        protocol='http', http11=True, umask=022, user=None,
                        group=None)
    options, args = parser.parse_args()

    if not args and not options.env_parent_dir:
        parser.error('either the --env-parent-dir option or at least one '
                     'environment must be specified')
    if options.single_env:
        if options.env_parent_dir:
            parser.error('the --single-env option cannot be used with '
                         '--env-parent-dir')
        elif len(args) > 1:
            parser.error('the --single-env option cannot be used with '
                         'more than one enviroment')
    if options.daemonize and options.autoreload:
        parser.error('the --auto-reload option cannot be used with '
                     '--daemonize')

    if options.port is None:
        options.port = {
            'http': 80,
            'scgi': 4000,
            'ajp': 8009,
            'fcgi': 8000,
        }[options.protocol]
    server_address = (options.hostname, options.port)

    # relative paths don't work when daemonized
    args = [os.path.abspath(a) for a in args]
    if options.env_parent_dir:
        options.env_parent_dir = os.path.abspath(options.env_parent_dir)
    if parser.has_option('pidfile') and options.pidfile:
        options.pidfile = os.path.abspath(options.pidfile)

    wsgi_app = TracEnvironMiddleware(dispatch_request,
                                     options.env_parent_dir, args,
                                     options.single_env)
    if auths:
        if options.single_env:
            project_name = os.path.basename(args[0])
            wsgi_app = AuthenticationMiddleware(wsgi_app, auths, project_name)
        else:
            wsgi_app = AuthenticationMiddleware(wsgi_app, auths)
    base_path = options.base_path.strip('/')
    if base_path:
        wsgi_app = BasePathMiddleware(wsgi_app, base_path)

    if options.protocol == 'http':
        def serve():
            addr, port = server_address
            if not addr or addr == '0.0.0.0':
                loc = '0.0.0.0:%s view at http://127.0.0.1:%s/%s' \
                       % (port, port, base_path)
            else:
                loc = 'http://%s:%s/%s' % (addr, port, base_path)

            try:
                httpd = TracHTTPServer(server_address, wsgi_app,
                                       options.env_parent_dir, args,
                                       use_http_11=options.http11)
            except socket.error, e:
                print 'Error starting Trac server on %s' % loc
                print e.strerror
                sys.exit(1)

            print 'Server starting in PID %i.' % os.getpid()
            print 'Serving on %s' % loc
            if options.http11:
                print 'Using HTTP/1.1 protocol version'
            httpd.serve_forever()
Пример #37
0
def main():
    from optparse import OptionParser, OptionValueError
    parser = OptionParser(usage='usage: %prog [options] [projenv] ...',
                          version='%%prog %s' % VERSION)

    auths = {}
    def _auth_callback(option, opt_str, value, parser, cls):
        info = value.split(',', 3)
        if len(info) != 3:
            raise OptionValueError("Incorrect number of parameters for %s"
                                   % option)

        env_name, filename, realm = info
        if env_name in auths:
            print >> sys.stderr, 'Ignoring duplicate authentication option ' \
                                 'for project: %s' % env_name
        else:
            auths[env_name] = cls(os.path.abspath(filename), realm)

    def _validate_callback(option, opt_str, value, parser, valid_values):
        if value not in valid_values:
            raise OptionValueError('%s must be one of: %s, not %s'
                                   % (opt_str, '|'.join(valid_values), value))
        setattr(parser.values, option.dest, value)

    def _octal(option, opt_str, value, parser):
        try:
            setattr(parser.values, option.dest, int(value, 8))
        except ValueError:
            raise OptionValueError('Invalid octal umask value: %r' % value)
    
    parser.add_option('-a', '--auth', action='callback', type='string',
                      metavar='DIGESTAUTH', callback=_auth_callback,
                      callback_args=(DigestAuthentication,),
                      help='[projectdir],[htdigest_file],[realm]')
    parser.add_option('--basic-auth', action='callback', type='string',
                      metavar='BASICAUTH', callback=_auth_callback,
                      callback_args=(BasicAuthentication,),
                      help='[projectdir],[htpasswd_file],[realm]')

    parser.add_option('-p', '--port', action='store', type='int', dest='port',
                      help='the port number to bind to')
    parser.add_option('-b', '--hostname', action='store', dest='hostname',
                      help='the host name or IP address to bind to')
    parser.add_option('--protocol', action='callback', type="string",
                      dest='protocol', callback=_validate_callback,
                      callback_args=(('http', 'scgi', 'ajp', 'fcgi'),),
                      help='http|scgi|ajp|fcgi')
    parser.add_option('-q', '--unquote', action='store_true',
                      dest='unquote',
                      help='unquote PATH_INFO (may be needed when using ajp)')
    parser.add_option('--http10', action='store_false', dest='http11',
                      help='use HTTP/1.0 protocol version instead of HTTP/1.1')
    parser.add_option('--http11', action='store_true', dest='http11',
                      help='use HTTP/1.1 protocol version (default)')
    parser.add_option('-e', '--env-parent-dir', action='store',
                      dest='env_parent_dir', metavar='PARENTDIR',
                      help='parent directory of the project environments')
    parser.add_option('--base-path', action='store', type='string', # XXX call this url_base_path?
                      dest='base_path',
                      help='the initial portion of the request URL\'s "path"')

    parser.add_option('-r', '--auto-reload', action='store_true',
                      dest='autoreload',
                      help='restart automatically when sources are modified')

    parser.add_option('-s', '--single-env', action='store_true',
                      dest='single_env', help='only serve a single '
                      'project without the project list', default=False)

    if os.name == 'posix':
        parser.add_option('-d', '--daemonize', action='store_true',
                          dest='daemonize',
                          help='run in the background as a daemon')
        parser.add_option('--pidfile', action='store',
                          dest='pidfile',
                          help='When daemonizing, file to which to write pid')
        parser.add_option('--umask', action='callback', type='string',
                          dest='umask', metavar='MASK', callback=_octal,
                          help='When daemonizing, file mode creation mask '
                          'to use, in octal notation (default 022)')

    parser.set_defaults(port=None, hostname='', base_path='', daemonize=False,
                        protocol='http', http11=True, umask=022)
    options, args = parser.parse_args()

    if not args and not options.env_parent_dir:
        parser.error('either the --env-parent-dir option or at least one '
                     'environment must be specified')
    if options.single_env:
        if options.env_parent_dir:
            parser.error('the --single-env option cannot be used with '
                         '--env-parent-dir')
        elif len(args) > 1:
            parser.error('the --single-env option cannot be used with '
                         'more than one enviroment')
    if options.daemonize and options.autoreload:
        parser.error('the --auto-reload option cannot be used with '
                     '--daemonize')

    if options.port is None:
        options.port = {
            'http': 80,
            'scgi': 4000,
            'ajp': 8009,
            'fcgi': 8000,
        }[options.protocol]
    server_address = (options.hostname, options.port)

    # relative paths don't work when daemonized
    args = [os.path.abspath(a) for a in args]
    if options.env_parent_dir:
        options.env_parent_dir = os.path.abspath(options.env_parent_dir)
    if parser.has_option('pidfile') and options.pidfile:
        options.pidfile = os.path.abspath(options.pidfile)

    wsgi_app = TracEnvironMiddleware(dispatch_request,
                                     options.env_parent_dir, args,
                                     options.single_env)
    if auths:
        if options.single_env:
            project_name = os.path.basename(args[0])
            wsgi_app = AuthenticationMiddleware(wsgi_app, auths, project_name)
        else:
            wsgi_app = AuthenticationMiddleware(wsgi_app, auths)
    base_path = options.base_path.strip('/')
    if base_path:
        wsgi_app = BasePathMiddleware(wsgi_app, base_path)

    if options.protocol == 'http':
        def serve():
            httpd = TracHTTPServer(server_address, wsgi_app,
                                   options.env_parent_dir, args,
                                   use_http_11=options.http11)

            print 'Server starting in PID %i.' % os.getpid()
            addr, port = server_address
            if not addr or addr == '0.0.0.0':
                print 'Serving on 0.0.0.0:%s view at http://127.0.0.1:%s/%s' \
                       % (port, port, base_path)
            else:
                print 'Serving on http://%s:%s/%s' % (addr, port, base_path)
            if options.http11:
                print 'Using HTTP/1.1 protocol version'
            httpd.serve_forever()
    elif options.protocol in ('scgi', 'ajp', 'fcgi'):
        def serve():
            server_cls = __import__('flup.server.%s' % options.protocol,
                                    None, None, ['']).WSGIServer
            flup_app = wsgi_app
            if options.unquote:
                from trac.web.fcgi_frontend import FlupMiddleware
                flup_app = FlupMiddleware(flup_app)
            ret = server_cls(flup_app, bindAddress=server_address).run()
            sys.exit(ret and 42 or 0) # if SIGHUP exit with status 42

    try:
        if options.daemonize:
            daemon.daemonize(pidfile=options.pidfile, progname='tracd',
                             umask=options.umask)

        if options.autoreload:
            def modification_callback(file):
                print >> sys.stderr, 'Detected modification of %s, ' \
                                     'restarting.' % file
            autoreload.main(serve, modification_callback)
        else:
            serve()

    except OSError:
        sys.exit(1)
    except KeyboardInterrupt:
        pass
Пример #38
0
def main():

    usage = "usage: %prog config_file.ini"
    parser = OptionParser(usage=usage)
    (cmd_opt, args) = parser.parse_args()

    if len(args) == 1:
        config_files = [args[0]]
    else:
        config_files = ["download_ta_bdys.ini"]

    parser = SafeConfigParser()
    found = parser.read(config_files)
    if not found:
        sys.exit("Could not load config " + config_files[0])

    # set up logging
    logging.config.fileConfig(config_files[0], defaults={"hostname": socket.gethostname()})
    logger = logging.getLogger()

    logger.info("Starting download TA boundaries")

    db_host = None
    db_rolename = None
    db_port = None
    db_user = None
    db_pass = None
    db_schema = "public"
    layer_name = None
    layer_geom_column = None
    layer_output_srid = 4167
    create_grid = False
    grid_res = 0.05
    shift_geometry = False

    base_uri = parser.get("source", "base_uri")
    db_name = parser.get("database", "name")
    db_schema = parser.get("database", "schema")

    if parser.has_option("database", "rolename"):
        db_rolename = parser.get("database", "rolename")
    if parser.has_option("database", "host"):
        db_host = parser.get("database", "host")
    if parser.has_option("database", "port"):
        db_port = parser.get("database", "port")
    if parser.has_option("database", "user"):
        db_user = parser.get("database", "user")
    if parser.has_option("database", "password"):
        db_pass = parser.get("database", "password")

    layer_name = parser.get("layer", "name")
    layer_geom_column = parser.get("layer", "geom_column")
    if parser.has_option("layer", "output_srid"):
        layer_output_srid = parser.getint("layer", "output_srid")
    if parser.has_option("layer", "create_grid"):
        create_grid = parser.getboolean("layer", "create_grid")
    if parser.has_option("layer", "grid_res"):
        grid_res = parser.getfloat("layer", "grid_res")
    if parser.has_option("layer", "shift_geometry"):
        shift_geometry = parser.getboolean("layer", "shift_geometry")

    try:
        output_srs = osr.SpatialReference()
        output_srs.ImportFromEPSG(layer_output_srid)
    except:
        logger.fatal("Output SRID %s is not valid" % (layer_output_srid))
        sys.exit(1)

    if create_grid and not grid_res > 0:
        logger.fatal("Grid resolution must be greater than 0")
        sys.exit(1)

    #
    # Determine TA layer and its year from REST service
    #

    logger.debug(base_uri + "?f=json")
    response = urllib2.urlopen(base_uri + "?f=json")
    capabilities = json.load(response)

    latest_service = None
    latest_year = None
    p = re.compile("((\d{4})\_Geographies)$", flags=re.UNICODE)
    for service in capabilities["services"]:
        m = p.search(service["name"])
        if m:
            if not latest_year or m.group(2) > latest_year:
                latest_year = int(m.group(2))
                latest_service = m.group(1)

    logger.debug(base_uri + "/" + latest_service + "/MapServer?f=json")
    response = urllib2.urlopen(base_uri + "/" + latest_service + "/MapServer?f=json")
    capabilities = json.load(response)

    ta_layer = None
    p = re.compile("^Territorial\sAuthorities\s\d{4}$", flags=re.UNICODE)
    for layer in capabilities["layers"]:
        m = p.search(layer["name"])
        if m:
            ta_layer = layer
            break

    if not ta_layer:
        logger.fatal("Could not find the TA layer in " + base_uri)
        sys.exit(1)

    feature_url = (
        base_uri
        + "/"
        + latest_service
        + "/MapServer/"
        + str(ta_layer["id"])
        + "/query?f=json&where=1=1&returnGeometry=true&outSR="
        + str(layer_output_srid)
    )

    geojson_drv = ogr.GetDriverByName("GeoJSON")
    if geojson_drv is None:
        logger.fatal("Could not load the OGR GeoJSON driver")
        sys.exit(1)

    #
    # Connect to the PostgreSQL database
    #

    pg_drv = ogr.GetDriverByName("PostgreSQL")
    if pg_drv is None:
        logger.fatal("Could not load the OGR PostgreSQL driver")
        sys.exit(1)

    pg_uri = "PG:dbname=" + db_name
    if db_host:
        pg_uri = pg_uri + " host=" + db_host
    if db_port:
        pg_uri = pg_uri + " port=" + db_port
    if db_user:
        pg_uri = pg_uri + " user="******" password="******"Can't open PG output database: " + str(e))
        sys.exit(1)
Пример #39
0
class CommandLineParser:

    # Defines what --regular means
    REGULAR_CMD = [
        "sslv2",
        "sslv3",
        "tlsv1",
        "tlsv1_1",
        "tlsv1_2",
        "tlsv1_3",
        "reneg",
        "resum",
        "certinfo",
        "http_get",
        "hide_rejected_ciphers",
        "compression",
        "heartbleed",
        "openssl_ccs",
        "fallback",
        "robot",
    ]
    SSLYZE_USAGE = "usage: %prog [options] target1.com target2.com:443 target3.com:443{ip} etc..."

    # StartTLS options
    START_TLS_PROTOCOLS = [
        "smtp", "xmpp", "xmpp_server", "pop3", "ftp", "imap", "ldap", "rdp",
        "postgres", "auto"
    ]

    START_TLS_USAGE = (
        "StartTLS should be one of: {}. The 'auto' option will cause SSLyze to deduce the protocol "
        "(ftp, imap, etc.) from the supplied port number, "
        "for each target servers.".format(" , ".join(START_TLS_PROTOCOLS)))

    # Mapping of StartTls protocols and ports; useful for starttls=auto
    STARTTLS_PROTOCOL_DICT = {
        "smtp": TlsWrappedProtocolEnum.STARTTLS_SMTP,
        587: TlsWrappedProtocolEnum.STARTTLS_SMTP,
        25: TlsWrappedProtocolEnum.STARTTLS_SMTP,
        "xmpp": TlsWrappedProtocolEnum.STARTTLS_XMPP,
        5222: TlsWrappedProtocolEnum.STARTTLS_XMPP,
        "xmpp_server": TlsWrappedProtocolEnum.STARTTLS_XMPP_SERVER,
        5269: TlsWrappedProtocolEnum.STARTTLS_XMPP_SERVER,
        "pop3": TlsWrappedProtocolEnum.STARTTLS_POP3,
        109: TlsWrappedProtocolEnum.STARTTLS_POP3,
        110: TlsWrappedProtocolEnum.STARTTLS_POP3,
        "imap": TlsWrappedProtocolEnum.STARTTLS_IMAP,
        143: TlsWrappedProtocolEnum.STARTTLS_IMAP,
        220: TlsWrappedProtocolEnum.STARTTLS_IMAP,
        "ftp": TlsWrappedProtocolEnum.STARTTLS_FTP,
        21: TlsWrappedProtocolEnum.STARTTLS_FTP,
        "ldap": TlsWrappedProtocolEnum.STARTTLS_LDAP,
        3268: TlsWrappedProtocolEnum.STARTTLS_LDAP,
        389: TlsWrappedProtocolEnum.STARTTLS_LDAP,
        "rdp": TlsWrappedProtocolEnum.STARTTLS_RDP,
        3389: TlsWrappedProtocolEnum.STARTTLS_RDP,
        "postgres": TlsWrappedProtocolEnum.STARTTLS_POSTGRES,
        5432: TlsWrappedProtocolEnum.STARTTLS_POSTGRES,
    }

    def __init__(self, available_plugins: Set[Type[Plugin]],
                 sslyze_version: str) -> None:
        """Generate SSLyze's command line parser.
        """
        self._parser = OptionParser(version=sslyze_version,
                                    usage=self.SSLYZE_USAGE)

        # Add generic command line options to the parser
        self._add_default_options()

        # Add plugin-specific options to the parser
        self._add_plugin_options(available_plugins)

        # Add the --regular command line parameter as a shortcut if possible
        regular_help = "Regular HTTPS scan; shortcut for --{}".format(
            " --".join(self.REGULAR_CMD))
        self._parser.add_option("--regular",
                                action="store_true",
                                dest=None,
                                help=regular_help)

    def parse_command_line(
        self
    ) -> Tuple[List[ServerConnectivityTester], List[ServerStringParsingError],
               Any]:
        """Parses the command line used to launch SSLyze.
        """
        (args_command_list, args_target_list) = self._parser.parse_args()

        if args_command_list.update_trust_stores:
            # Just update the trust stores and do nothing
            TrustStoresRepository.update_default()
            raise TrustStoresUpdateCompleted()

        # Handle the --targets_in command line and fill args_target_list
        if args_command_list.targets_in:
            if args_target_list:
                raise CommandLineParsingError(
                    "Cannot use --targets_list and specify targets within the command line."
                )

            try:  # Read targets from a file
                with open(args_command_list.targets_in) as f:
                    for target in f.readlines():
                        if target.strip():  # Ignore empty lines
                            if not target.startswith(
                                    "#"):  # Ignore comment lines
                                args_target_list.append(target.strip())
            except IOError:
                raise CommandLineParsingError(
                    "Can't read targets from input file '{}.".format(
                        args_command_list.targets_in))

        if not args_target_list:
            raise CommandLineParsingError("No targets to scan.")

        # Handle the --regular command line parameter as a shortcut
        if self._parser.has_option("--regular"):
            if getattr(args_command_list, "regular"):
                setattr(args_command_list, "regular", False)
                for cmd in self.REGULAR_CMD:
                    setattr(args_command_list, cmd, True)

        # Sanity checks on the command line options
        # Prevent --quiet and --xml_out -
        if args_command_list.xml_file and args_command_list.xml_file == "-" and args_command_list.quiet:
            raise CommandLineParsingError(
                "Cannot use --quiet with --xml_out -.")

        # Prevent --quiet and --json_out -
        if args_command_list.json_file and args_command_list.json_file == "-" and args_command_list.quiet:
            raise CommandLineParsingError(
                "Cannot use --quiet with --json_out -.")

        # Prevent --xml_out - and --json_out -
        if (args_command_list.json_file and args_command_list.json_file == "-"
                and args_command_list.xml_file
                and args_command_list.xml_file == "-"):
            raise CommandLineParsingError(
                "Cannot use --xml_out - with --json_out -.")

        # Sanity checks on the client cert options
        client_auth_creds = None
        if bool(args_command_list.cert) ^ bool(args_command_list.key):
            raise CommandLineParsingError(
                "No private key or certificate file were given. See --cert and --key."
            )

        elif args_command_list.cert:
            # Private key formats
            if args_command_list.keyform == "DER":
                key_type = OpenSslFileTypeEnum.ASN1
            elif args_command_list.keyform == "PEM":
                key_type = OpenSslFileTypeEnum.PEM
            else:
                raise CommandLineParsingError(
                    "--keyform should be DER or PEM.")

            # Let's try to open the cert and key files
            try:
                client_auth_creds = ClientAuthenticationCredentials(
                    args_command_list.cert, args_command_list.key, key_type,
                    args_command_list.keypass)
            except ValueError as e:
                raise CommandLineParsingError(
                    "Invalid client authentication settings: {}.".format(
                        e.args[0]))

        # HTTP CONNECT proxy
        http_tunneling_settings = None
        if args_command_list.https_tunnel:
            try:
                http_tunneling_settings = HttpConnectTunnelingSettings.from_url(
                    args_command_list.https_tunnel)
            except ValueError as e:
                raise CommandLineParsingError(
                    "Invalid proxy URL for --https_tunnel: {}.".format(
                        e.args[0]))

        # STARTTLS
        tls_wrapped_protocol = TlsWrappedProtocolEnum.PLAIN_TLS
        if args_command_list.starttls:
            if args_command_list.starttls not in self.START_TLS_PROTOCOLS:
                raise CommandLineParsingError(self.START_TLS_USAGE)
            else:
                # StartTLS was specified
                if args_command_list.starttls in self.STARTTLS_PROTOCOL_DICT.keys(
                ):
                    # Protocol was given in the command line
                    tls_wrapped_protocol = self.STARTTLS_PROTOCOL_DICT[
                        args_command_list.starttls]

        # Create the server connectivity tester for each specified servers
        # A limitation when using the command line is that only one client_auth_credentials and http_tunneling_settings
        # can be specified, for all the servers to scan
        good_server_list = []
        bad_server_list = []
        for server_string in args_target_list:
            try:
                hostname, ip_address, port = CommandLineServerStringParser.parse_server_string(
                    server_string)
            except ServerStringParsingError as e:
                # Will happen if the server string is malformed
                bad_server_list.append(e)
                continue

            try:
                # TODO(AD): Unicode hostnames may fail on Python2
                # hostname = hostname.decode('utf-8')
                server_info = ServerConnectivityTester(
                    hostname=hostname,
                    port=port,
                    ip_address=ip_address,
                    tls_wrapped_protocol=tls_wrapped_protocol,
                    tls_server_name_indication=args_command_list.sni,
                    xmpp_to_hostname=args_command_list.xmpp_to,
                    client_auth_credentials=client_auth_creds,
                    http_tunneling_settings=http_tunneling_settings,
                )
                good_server_list.append(server_info)
            except ValueError as e:
                # Will happen for example if xmpp_to is specified for a non-XMPP connection
                raise CommandLineParsingError(e.args[0])

        # Command line hacks
        # Handle --starttls=auto now that we parsed the server strings
        if args_command_list.starttls == "auto":
            for server_info in good_server_list:
                # We use the port number to deduce the protocol
                if server_info.port in self.STARTTLS_PROTOCOL_DICT.keys():
                    server_info.tls_wrapped_protocol = self.STARTTLS_PROTOCOL_DICT[
                        server_info.port]

        # Handle --http_get now that we parsed the server strings
        # Doing it here is hacky as the option is defined within PluginOpenSSLCipherSuites
        if args_command_list.http_get:
            for server_info in good_server_list:
                if server_info.port == 443:
                    server_info.tls_wrapped_protocol = TlsWrappedProtocolEnum.HTTPS

        return good_server_list, bad_server_list, args_command_list

    def _add_default_options(self) -> None:
        """Add default command line options to the parser.
        """
        # Updating the trust stores
        update_stores_group = OptionGroup(self._parser, "Trust stores options",
                                          "")
        update_stores_group.add_option(
            "--update_trust_stores",
            help=
            "Update the default trust stores used by SSLyze. The latest stores will be downloaded from "
            "https://github.com/nabla-c0d3/trust_stores_observatory. This option is meant to be used separately, "
            "and will silence any other command line option supplied to SSLyze.",
            dest="update_trust_stores",
            action="store_true",
        )
        self._parser.add_option_group(update_stores_group)

        # Client certificate options
        clientcert_group = OptionGroup(self._parser,
                                       "Client certificate options", "")
        clientcert_group.add_option(
            "--cert",
            help=
            "Client certificate chain filename. The certificates must be in PEM format and must be sorted "
            "starting with the subject's client certificate, followed by intermediate CA certificates if "
            "applicable.",
            dest="cert",
        )
        clientcert_group.add_option("--key",
                                    help="Client private key filename.",
                                    dest="key")
        clientcert_group.add_option(
            "--keyform",
            help="Client private key format. DER or PEM (default).",
            dest="keyform",
            default="PEM")
        clientcert_group.add_option("--pass",
                                    help="Client private key passphrase.",
                                    dest="keypass",
                                    default="")
        self._parser.add_option_group(clientcert_group)

        # Input / output
        output_group = OptionGroup(self._parser, "Input and output options",
                                   "")
        # XML output
        output_group.add_option(
            "--xml_out",
            help=
            'Write the scan results as an XML document to the file XML_FILE. If XML_FILE is set to "-", the XML '
            "output will instead be printed to stdout. The corresponding XML Schema Definition is available at "
            "./docs/xml_out.xsd",
            dest="xml_file",
            default=None,
        )
        # JSON output
        output_group.add_option(
            "--json_out",
            help=
            'Write the scan results as a JSON document to the file JSON_FILE. If JSON_FILE is set to "-", the '
            "JSON output will instead be printed to stdout. The resulting JSON file is a serialized version of "
            "the ScanResult objects described in SSLyze's Python API: the nodes and attributes will be the same. "
            "See https://nabla-c0d3.github.io/sslyze/documentation/available-scan-commands.html for more details.",
            dest="json_file",
            default=None,
        )
        # Read targets from input file
        output_group.add_option(
            "--targets_in",
            help=
            "Read the list of targets to scan from the file TARGETS_IN. It should contain one host:port per "
            "line.",
            dest="targets_in",
            default=None,
        )
        # No text output
        output_group.add_option(
            "--quiet",
            action="store_true",
            dest="quiet",
            help=
            "Do not output anything to stdout; useful when using --xml_out or --json_out.",
        )
        self._parser.add_option_group(output_group)

        # Connectivity option group
        connect_group = OptionGroup(self._parser, "Connectivity options", "")
        # Connection speed
        connect_group.add_option(
            "--slow_connection",
            help=
            "Greatly reduce the number of concurrent connections initiated by SSLyze. This will make the scans "
            "slower but more reliable if the connection between your host and the server is slow, or if the "
            "server cannot handle many concurrent connections. Enable this option if you are getting a lot of "
            "timeouts or errors.",
            action="store_true",
            dest="slow_connection",
        )
        # HTTP CONNECT Proxy
        connect_group.add_option(
            "--https_tunnel",
            help=
            "Tunnel all traffic to the target server(s) through an HTTP CONNECT proxy. HTTP_TUNNEL should be the "
            "proxy's URL: 'http://*****:*****@HOST:PORT/'. For proxies requiring authentication, only Basic "
            "Authentication is supported.",
            dest="https_tunnel",
            default=None,
        )
        # STARTTLS
        connect_group.add_option(
            "--starttls",
            help=
            "Perform a StartTLS handshake when connecting to the target server(s). "
            "{}".format(self.START_TLS_USAGE),
            dest="starttls",
            default=None,
        )
        connect_group.add_option(
            "--xmpp_to",
            help=
            "Optional setting for STARTTLS XMPP. XMPP_TO should be the hostname to be put in the 'to' "
            "attribute of the XMPP stream. Default is the server's hostname.",
            dest="xmpp_to",
            default=None,
        )
        # Server Name Indication
        connect_group.add_option(
            "--sni",
            help=
            "Use Server Name Indication to specify the hostname to connect to.  Will only affect TLS 1.0+ "
            "connections.",
            dest="sni",
            default=None,
        )
        self._parser.add_option_group(connect_group)

    def _add_plugin_options(self,
                            available_plugins: Set[Type[Plugin]]) -> None:
        """Recovers the list of command line options implemented by the available plugins and adds them to the command
        line parser.
        """
        for plugin_class in available_plugins:
            # Add the current plugin's commands to the parser
            group = OptionGroup(self._parser, plugin_class.get_title(),
                                plugin_class.get_description())
            for option in plugin_class.get_cli_option_group():
                group.add_option(option)
            self._parser.add_option_group(group)
Пример #40
0
def buildOptions(parser=None, usage=None):
    """
    Build a list of command-line options we will accept

    @param parser: optparse parser
    @type parser: optparse object
    @param usage: description of how to use the program
    @type usage: string
    @return: optparse parser
    @rtype: optparse object
    """

    # Default option values
    defaultUsername = os.environ.get("USER", "")
    defaultPassword = ""
    defaultLoginTries = 1
    defaultLoginTimeout = 10
    defaultCommandTimeout = 10
    defaultKeyPath = "~/.ssh/id_dsa"
    defaultConcurrentSessions = 10
    defaultSearchPath = []
    defaultExistanceTest = "test -f %s"

    if not usage:
        usage = "%prog [options] hostname[:port] command"

    if not parser:
        from optparse import OptionParser

        parser = OptionParser(usage=usage, )

    parser.add_option(
        "-u",
        "--user",
        dest="username",
        default=defaultUsername,
        help="Login username",
    )
    parser.add_option(
        "-P",
        "--password",
        dest="password",
        default=defaultPassword,
        help="Login password",
    )
    parser.add_option(
        "-t",
        "--loginTries",
        dest="loginTries",
        default=defaultLoginTries,
        type="int",
        help="Number of times to attempt to login",
    )
    parser.add_option(
        "-L",
        "--loginTimeout",
        dest="loginTimeout",
        type="float",
        default=defaultLoginTimeout,
        help="Timeout period (secs) to find login expect statments",
    )
    parser.add_option(
        "-T",
        "--commandTimeout",
        dest="commandTimeout",
        type="float",
        default=defaultCommandTimeout,
        help="Timeout period (secs) after issuing a command",
    )
    parser.add_option(
        "-K",
        "--keyPath",
        dest="keyPath",
        default=defaultKeyPath,
        help="Path to use when looking for SSH keys",
    )
    parser.add_option(
        "-S",
        "--concurrentSessions",
        dest="concurrentSessions",
        type="int",
        default=defaultConcurrentSessions,
        help="Allowable number of concurrent SSH sessions",
    )
    parser.add_option(
        "-s",
        "--searchPath",
        dest="searchPath",
        default=defaultSearchPath,
        help="Path to use when looking for commands",
    )
    parser.add_option(
        "-e",
        "--existenceTest",
        dest="existenceTest",
        default=defaultExistanceTest,
        help="How to check if a command is available or not",
    )
    if not parser.has_option("-v"):
        parser.add_option(
            "-v",
            "--logseverity",
            dest="logseverity",
            default=logging.INFO,
            type="int",
            help="Logging severity threshold",
        )
    return parser
Пример #41
0
class CommandLineParser():

    # Defines what --regular means
    REGULAR_CMD = [
        'sslv2', 'sslv3', 'tlsv1', 'tlsv1_1', 'tlsv1_2', 'reneg', 'resum',
        'certinfo', 'http_get', 'hide_rejected_ciphers', 'compression',
        'heartbleed'
    ]
    SSLYZE_USAGE = 'usage: %prog [options] target1.com target2.com:443 etc...'

    # StartTLS options
    START_TLS_PROTS = [
        'smtp', 'xmpp', 'pop3', 'ftp', 'imap', 'ldap', 'rdp', 'postgres',
        'auto'
    ]
    START_TLS_USAGE = 'STARTTLS should be one of: ' + str(START_TLS_PROTS) +  \
        '. The \'auto\' option will cause SSLyze to deduce the protocol' + \
        ' (ftp, imap, etc.) from the supplied port number, for each target servers.'

    # Default values
    DEFAULT_RETRY_ATTEMPTS = 4
    DEFAULT_TIMEOUT = 5

    def __init__(self, available_plugins, sslyze_version):
        """
        Generates SSLyze's command line parser.
        """

        self._parser = OptionParser(version=sslyze_version,
                                    usage=self.SSLYZE_USAGE)

        # Add generic command line options to the parser
        self._add_default_options()

        # Add plugin-specific options to the parser
        self._add_plugin_options(available_plugins)

        # Add the --regular command line parameter as a shortcut if possible
        regular_help = 'Regular HTTPS scan; shortcut for'
        for cmd in self.REGULAR_CMD:
            regular_help += ' --' + cmd
            if cmd == 'certinfo':  # gah
                regular_help += '=basic'

            if not self._parser.has_option('--' + cmd):
                return

        self._parser.add_option('--regular',
                                action="store_true",
                                dest=None,
                                help=regular_help)

    def parse_command_line(self):
        """
        Parses the command line used to launch SSLyze.
        """

        (args_command_list, args_target_list) = self._parser.parse_args()

        # Handle the --targets_in command line and fill args_target_list
        if args_command_list.targets_in:
            if args_target_list:
                raise CommandLineParsingError(
                    "Cannot use --targets_list and specify targets within the command line."
                )

            try:  # Read targets from a file
                with open(args_command_list.targets_in) as f:
                    for target in f.readlines():
                        if target.strip():  # Ignore empty lines
                            if not target.startswith(
                                    '#'):  # Ignore comment lines
                                args_target_list.append(target.strip())
            except IOError:
                raise CommandLineParsingError(
                    "Can't read targets from input file '%s'." %
                    args_command_list.targets_in)

        if not args_target_list:
            raise CommandLineParsingError('No targets to scan.')

        # Handle the --regular command line parameter as a shortcut
        if self._parser.has_option('--regular'):
            if getattr(args_command_list, 'regular'):
                setattr(args_command_list, 'regular', False)
                for cmd in self.REGULAR_CMD:
                    if cmd == "certinfo":
                        # Allow user to override certinfo when using --regular
                        if getattr(args_command_list, 'certinfo') is None:
                            setattr(args_command_list, 'certinfo',
                                    'basic')  # Special case
                    else:
                        setattr(args_command_list, cmd, True)

        # Create the shared_settings object from looking at the command line
        shared_settings = self._process_parsing_results(args_command_list)
        return args_command_list, args_target_list, shared_settings

    def _add_default_options(self):
        """
        Adds default command line options to the parser.
        """

        # Client certificate options
        clientcert_group = OptionGroup(self._parser,
                                       'Client certificate support', '')
        clientcert_group.add_option('--cert',
                                    help='Client certificate filename.',
                                    dest='cert')
        clientcert_group.add_option(
            '--certform',
            help='Client certificate format. DER or PEM (default).',
            dest='certform',
            default='PEM')
        clientcert_group.add_option('--key',
                                    help='Client private key filename.',
                                    dest='key')
        clientcert_group.add_option(
            '--keyform',
            help='Client private key format. DER or PEM (default).',
            dest='keyform',
            default='PEM')
        clientcert_group.add_option('--pass',
                                    help='Client private key passphrase.',
                                    dest='keypass',
                                    default='')
        self._parser.add_option_group(clientcert_group)

        # XML output
        self._parser.add_option(
            '--xml_out',
            help=
            'Writes the scan results as an XML document to the file XML_FILE.',
            dest='xml_file',
            default=None)

        # Read targets from input file
        self._parser.add_option(
            '--targets_in',
            help=
            'Reads the list of targets to scan from the file TARGETS_IN. It should contain one host:port per line.',
            dest='targets_in',
            default=None)

        # Timeout
        self._parser.add_option(
            '--timeout',
            help=('Sets the timeout value in seconds used for every socket '
                  'connection made to the target server(s). Default is ' +
                  str(self.DEFAULT_TIMEOUT) + 's.'),
            type='int',
            dest='timeout',
            default=self.DEFAULT_TIMEOUT)

        # Control connection retry attempts
        self._parser.add_option(
            '--nb_retries',
            help=(
                'Sets the number retry attempts for all network connections '
                'initiated throughout the scan. Increase this value if you are '
                'getting a lot of timeout/connection errors when scanning a '
                'specific server. Decrease this value to increase the speed '
                'of the scans; results may however return connection errors. '
                'Default is ' + str(self.DEFAULT_RETRY_ATTEMPTS) +
                ' connection attempts.'),
            type='int',
            dest='nb_retries',
            default=self.DEFAULT_RETRY_ATTEMPTS)

        # HTTP CONNECT Proxy
        self._parser.add_option(
            '--https_tunnel',
            help=(
                'Tunnels all traffic to the target server(s) through an HTTP '
                'CONNECT proxy. HTTP_TUNNEL should be the proxy\'s URL: '
                '\'http://*****:*****@HOST:PORT/\'. For proxies requiring '
                'authentication, only Basic Authentication is supported.'),
            dest='https_tunnel',
            default=None)

        # STARTTLS
        self._parser.add_option(
            '--starttls',
            help=('Performs StartTLS handshakes when connecting to the target '
                  'server(s). ' + self.START_TLS_USAGE),
            dest='starttls',
            default=None)

        self._parser.add_option(
            '--xmpp_to',
            help=
            ('Optional setting for STARTTLS XMPP. '
             ' XMPP_TO should be the hostname to be put in the \'to\' attribute '
             'of the XMPP stream. Default is the server\'s hostname.'),
            dest='xmpp_to',
            default=None)

        # Server Name Indication
        self._parser.add_option(
            '--sni',
            help=
            ('Use Server Name Indication to specify the hostname to connect to.'
             ' Will only affect TLS 1.0+ connections.'),
            dest='sni',
            default=None)

    def _add_plugin_options(self, available_plugins):
        """
        Recovers the list of command line options implemented by the available
        plugins and adds them to the command line parser.
        """

        for plugin_class in available_plugins:
            plugin_desc = plugin_class.get_interface()

            # Add the current plugin's commands to the parser
            group = OptionGroup(self._parser, plugin_desc.title,
                                plugin_desc.description)
            for cmd in plugin_desc.get_commands():
                group.add_option(cmd)

            # Add the current plugin's options to the parser
            for option in plugin_desc.get_options():
                group.add_option(option)

            self._parser.add_option_group(group)

    def _process_parsing_results(self, args_command_list):
        """
        Performs various sanity checks on the command line that was used to
        launch SSLyze.
        Returns the shared_settings object to be fed to plugins.
        """

        shared_settings = {}
        # Sanity checks on the client cert options
        if bool(args_command_list.cert) ^ bool(args_command_list.key):
            raise CommandLineParsingError(
                'No private key or certificate file were given. See --cert and --key.'
            )

        # Private key and cert formats
        if args_command_list.certform == 'DER':
            args_command_list.certform = SSL_FILETYPE_ASN1
        elif args_command_list.certform == 'PEM':
            args_command_list.certform = SSL_FILETYPE_PEM
        else:
            raise CommandLineParsingError('--certform should be DER or PEM.')

        if args_command_list.keyform == 'DER':
            args_command_list.keyform = SSL_FILETYPE_ASN1
        elif args_command_list.keyform == 'PEM':
            args_command_list.keyform = SSL_FILETYPE_PEM
        else:
            raise CommandLineParsingError('--keyform should be DER or PEM.')

        # Let's try to open the cert and key files
        if args_command_list.cert:
            try:
                open(args_command_list.cert, "r")
            except:
                raise CommandLineParsingError(
                    'Could not open the client certificate file "' +
                    str(args_command_list.cert) + '".')

        if args_command_list.key:
            try:
                open(args_command_list.key, "r")
            except:
                raise CommandLineParsingError(
                    'Could not open the client private key file "' +
                    str(args_command_list.key) + '"')

            # Try to load the cert and key in OpenSSL
            try:
                sslClient = SslClient()
                sslClient.use_private_key(args_command_list.cert,
                                          args_command_list.certform,
                                          args_command_list.key,
                                          args_command_list.keyform,
                                          args_command_list.keypass)
            except _nassl.OpenSSLError as e:
                if 'bad decrypt' in str(e.args):
                    raise CommandLineParsingError(
                        'Could not decrypt the private key. Wrong passphrase ?'
                    )
                raise CommandLineParsingError(
                    'Could not load the certificate or the private key. Passphrase needed ?'
                )

        # HTTP CONNECT proxy
        shared_settings['https_tunnel_host'] = None
        if args_command_list.https_tunnel:

            # Parse the proxy URL
            parsedUrl = urlparse(args_command_list.https_tunnel)

            if not parsedUrl.netloc:
                raise CommandLineParsingError(
                    'Invalid Proxy URL for --https_tunnel, discarding all tasks.'
                )

            if parsedUrl.scheme in 'http':
                defaultPort = 80
            elif parsedUrl.scheme in 'https':
                defaultPort = 443
            else:
                raise CommandLineParsingError(
                    'Invalid URL scheme for --https_tunnel, discarding all tasks.'
                )

            if not parsedUrl.hostname:
                raise CommandLineParsingError(
                    'Invalid Proxy URL for --https_tunnel, discarding all tasks.'
                )

            try:
                shared_settings[
                    'https_tunnel_port'] = parsedUrl.port if parsedUrl.port else defaultPort
            except ValueError:  # The supplied port was not a number
                raise CommandLineParsingError(
                    'Invalid Proxy URL for --https_tunnel, discarding all tasks.'
                )

            shared_settings['https_tunnel_host'] = parsedUrl.hostname
            shared_settings['https_tunnel_user'] = parsedUrl.username
            shared_settings['https_tunnel_password'] = parsedUrl.password

        # STARTTLS
        if args_command_list.starttls:
            if args_command_list.starttls not in self.START_TLS_PROTS:
                raise CommandLineParsingError(self.START_TLS_USAGE)

        if args_command_list.starttls and args_command_list.https_tunnel:
            raise CommandLineParsingError(
                'Cannot have --https_tunnel and --starttls at the same time.')

        # Number of connection retries
        if args_command_list.nb_retries < 1:
            raise CommandLineParsingError(
                'Cannot have a number smaller than 1 for --nb_retries.')

        # All good, let's save the data
        for key, value in args_command_list.__dict__.iteritems():
            shared_settings[key] = value

        return shared_settings
Пример #42
0
class CommandLineParser:

    # Defines what --regular means
    REGULAR_CMD = [
        'sslv2', 'sslv3', 'tlsv1', 'tlsv1_1', 'tlsv1_2', 'tlsv1_3', 'reneg', 'resum', 'certinfo', 'http_get',
        'hide_rejected_ciphers', 'compression', 'heartbleed', 'openssl_ccs', 'fallback', 'robot'
    ]
    SSLYZE_USAGE = 'usage: %prog [options] target1.com target2.com:443 target3.com:443{ip} etc...'

    # StartTLS options
    START_TLS_PROTOCOLS = [
        'smtp', 'xmpp', 'xmpp_server', 'pop3', 'ftp', 'imap', 'ldap', 'rdp', 'postgres', 'auto'
    ]

    START_TLS_USAGE = 'StartTLS should be one of: {}. The \'auto\' option will cause SSLyze to deduce the protocol ' \
                      '(ftp, imap, etc.) from the supplied port number, ' \
                      'for each target servers.'.format(' , '.join(START_TLS_PROTOCOLS))

    # Mapping of StartTls protocols and ports; useful for starttls=auto
    STARTTLS_PROTOCOL_DICT = {
        'smtp': TlsWrappedProtocolEnum.STARTTLS_SMTP,
        587: TlsWrappedProtocolEnum.STARTTLS_SMTP,
        25: TlsWrappedProtocolEnum.STARTTLS_SMTP,
        'xmpp': TlsWrappedProtocolEnum.STARTTLS_XMPP,
        5222: TlsWrappedProtocolEnum.STARTTLS_XMPP,
        'xmpp_server': TlsWrappedProtocolEnum.STARTTLS_XMPP_SERVER,
        5269: TlsWrappedProtocolEnum.STARTTLS_XMPP_SERVER,
        'pop3': TlsWrappedProtocolEnum.STARTTLS_POP3,
        109: TlsWrappedProtocolEnum.STARTTLS_POP3,
        110: TlsWrappedProtocolEnum.STARTTLS_POP3,
        'imap': TlsWrappedProtocolEnum.STARTTLS_IMAP,
        143: TlsWrappedProtocolEnum.STARTTLS_IMAP,
        220: TlsWrappedProtocolEnum.STARTTLS_IMAP,
        'ftp': TlsWrappedProtocolEnum.STARTTLS_FTP,
        21: TlsWrappedProtocolEnum.STARTTLS_FTP,
        'ldap': TlsWrappedProtocolEnum.STARTTLS_LDAP,
        3268: TlsWrappedProtocolEnum.STARTTLS_LDAP,
        389: TlsWrappedProtocolEnum.STARTTLS_LDAP,
        'rdp': TlsWrappedProtocolEnum.STARTTLS_RDP,
        3389: TlsWrappedProtocolEnum.STARTTLS_RDP,
        'postgres': TlsWrappedProtocolEnum.STARTTLS_POSTGRES,
        5432: TlsWrappedProtocolEnum.STARTTLS_POSTGRES
    }

    def __init__(self, available_plugins: Set[Type[Plugin]], sslyze_version: str) -> None:
        """Generate SSLyze's command line parser.
        """
        self._parser = OptionParser(version=sslyze_version, usage=self.SSLYZE_USAGE)

        # Add generic command line options to the parser
        self._add_default_options()

        # Add plugin-specific options to the parser
        self._add_plugin_options(available_plugins)

        # Add the --regular command line parameter as a shortcut if possible
        regular_help = 'Regular HTTPS scan; shortcut for --{}'.format(' --'.join(self.REGULAR_CMD))
        self._parser.add_option('--regular', action='store_true', dest=None, help=regular_help)

    def parse_command_line(self) -> Tuple[List[ServerConnectivityTester], List[ServerStringParsingError], Any]:
        """Parses the command line used to launch SSLyze.
        """
        (args_command_list, args_target_list) = self._parser.parse_args()

        if args_command_list.update_trust_stores:
            # Just update the trust stores and do nothing
            TrustStoresRepository.update_default()
            raise TrustStoresUpdateCompleted()

        # Handle the --targets_in command line and fill args_target_list
        if args_command_list.targets_in:
            if args_target_list:
                raise CommandLineParsingError('Cannot use --targets_list and specify targets within the command line.')

            try:  # Read targets from a file
                with open(args_command_list.targets_in) as f:
                    for target in f.readlines():
                        if target.strip():  # Ignore empty lines
                            if not target.startswith('#'):  # Ignore comment lines
                                args_target_list.append(target.strip())
            except IOError:
                raise CommandLineParsingError('Can\'t read targets from input file \'{}.'.format(
                    args_command_list.targets_in))

        if not args_target_list:
            raise CommandLineParsingError('No targets to scan.')

        # Handle the --regular command line parameter as a shortcut
        if self._parser.has_option('--regular'):
            if getattr(args_command_list, 'regular'):
                setattr(args_command_list, 'regular', False)
                for cmd in self.REGULAR_CMD:
                    setattr(args_command_list, cmd, True)

        # Sanity checks on the command line options
        # Prevent --quiet and --xml_out -
        if args_command_list.xml_file and args_command_list.xml_file == '-' and args_command_list.quiet:
            raise CommandLineParsingError('Cannot use --quiet with --xml_out -.')

        # Prevent --quiet and --json_out -
        if args_command_list.json_file and args_command_list.json_file == '-' and args_command_list.quiet:
            raise CommandLineParsingError('Cannot use --quiet with --json_out -.')

        # Prevent --xml_out - and --json_out -
        if args_command_list.json_file and args_command_list.json_file == '-' \
                and args_command_list.xml_file and args_command_list.xml_file == '-':
            raise CommandLineParsingError('Cannot use --xml_out - with --json_out -.')

        # Sanity checks on the client cert options
        client_auth_creds = None
        if bool(args_command_list.cert) ^ bool(args_command_list.key):
            raise CommandLineParsingError('No private key or certificate file were given. See --cert and --key.')

        elif args_command_list.cert:
            # Private key formats
            if args_command_list.keyform == 'DER':
                key_type = OpenSslFileTypeEnum.ASN1
            elif args_command_list.keyform == 'PEM':
                key_type = OpenSslFileTypeEnum.PEM
            else:
                raise CommandLineParsingError('--keyform should be DER or PEM.')

            # Let's try to open the cert and key files
            try:
                client_auth_creds = ClientAuthenticationCredentials(args_command_list.cert,
                                                                    args_command_list.key,
                                                                    key_type,
                                                                    args_command_list.keypass)
            except ValueError as e:
                raise CommandLineParsingError('Invalid client authentication settings: {}.'.format(e.args[0]))

        # HTTP CONNECT proxy
        http_tunneling_settings = None
        if args_command_list.https_tunnel:
            try:
                http_tunneling_settings = HttpConnectTunnelingSettings.from_url(args_command_list.https_tunnel)
            except ValueError as e:
                raise CommandLineParsingError('Invalid proxy URL for --https_tunnel: {}.'.format(e.args[0]))

        # STARTTLS
        tls_wrapped_protocol = TlsWrappedProtocolEnum.PLAIN_TLS
        if args_command_list.starttls:
            if args_command_list.starttls not in self.START_TLS_PROTOCOLS:
                raise CommandLineParsingError(self.START_TLS_USAGE)
            else:
                # StartTLS was specified
                if args_command_list.starttls in self.STARTTLS_PROTOCOL_DICT.keys():
                    # Protocol was given in the command line
                    tls_wrapped_protocol = self.STARTTLS_PROTOCOL_DICT[args_command_list.starttls]

        # Create the server connectivity tester for each specified servers
        # A limitation when using the command line is that only one client_auth_credentials and http_tunneling_settings
        # can be specified, for all the servers to scan
        good_server_list = []
        bad_server_list = []
        for server_string in args_target_list:
            try:
                hostname, ip_address, port = CommandLineServerStringParser.parse_server_string(server_string)
            except ServerStringParsingError as e:
                # Will happen if the server string is malformed
                bad_server_list.append(e)
                continue

            try:
                # TODO(AD): Unicode hostnames may fail on Python2
                # hostname = hostname.decode('utf-8')
                server_info = ServerConnectivityTester(
                    hostname=hostname,
                    port=port,
                    ip_address=ip_address,
                    tls_wrapped_protocol=tls_wrapped_protocol,
                    tls_server_name_indication=args_command_list.sni,
                    xmpp_to_hostname=args_command_list.xmpp_to,
                    client_auth_credentials=client_auth_creds,
                    http_tunneling_settings=http_tunneling_settings
                )
                good_server_list.append(server_info)
            except ValueError as e:
                # Will happen for example if xmpp_to is specified for a non-XMPP connection
                raise CommandLineParsingError(e.args[0])

        # Command line hacks
        # Handle --starttls=auto now that we parsed the server strings
        if args_command_list.starttls == 'auto':
            for server_info in good_server_list:
                # We use the port number to deduce the protocol
                if server_info.port in self.STARTTLS_PROTOCOL_DICT.keys():
                    server_info.tls_wrapped_protocol = self.STARTTLS_PROTOCOL_DICT[server_info.port]

        # Handle --http_get now that we parsed the server strings
        # Doing it here is hacky as the option is defined within PluginOpenSSLCipherSuites
        if args_command_list.http_get:
            for server_info in good_server_list:
                if server_info.port == 443:
                    server_info.tls_wrapped_protocol = TlsWrappedProtocolEnum.HTTPS

        return good_server_list, bad_server_list, args_command_list

    def _add_default_options(self) -> None:
        """Add default command line options to the parser.
        """
        # Updating the trust stores
        update_stores_group = OptionGroup(self._parser, 'Trust stores options', '')
        update_stores_group.add_option(
            '--update_trust_stores',
            help='Update the default trust stores used by SSLyze. The latest stores will be downloaded from '
                 'https://github.com/nabla-c0d3/trust_stores_observatory. This option is meant to be used separately, '
                 'and will silence any other command line option supplied to SSLyze.',
            dest='update_trust_stores',
            action='store_true',
        )
        self._parser.add_option_group(update_stores_group)

        # Client certificate options
        clientcert_group = OptionGroup(self._parser, 'Client certificate options', '')
        clientcert_group.add_option(
            '--cert',
            help='Client certificate chain filename. The certificates must be in PEM format and must be sorted '
                 'starting with the subject\'s client certificate, followed by intermediate CA certificates if '
                 'applicable.',
            dest='cert'
        )
        clientcert_group.add_option(
            '--key',
            help='Client private key filename.',
            dest='key'
        )
        clientcert_group.add_option(
            '--keyform',
            help='Client private key format. DER or PEM (default).',
            dest='keyform',
            default='PEM'
        )
        clientcert_group.add_option(
            '--pass',
            help='Client private key passphrase.',
            dest='keypass',
            default=''
        )
        self._parser.add_option_group(clientcert_group)

        # Input / output
        output_group = OptionGroup(self._parser, 'Input and output options', '')
        # XML output
        output_group.add_option(
            '--xml_out',
            help='Write the scan results as an XML document to the file XML_FILE. If XML_FILE is set to "-", the XML '
                 'output will instead be printed to stdout. The corresponding XML Schema Definition is available at '
                 './docs/xml_out.xsd',
            dest='xml_file',
            default=None
        )
        # JSON output
        output_group.add_option(
            '--json_out',
            help='Write the scan results as a JSON document to the file JSON_FILE. If JSON_FILE is set to "-", the '
                 'JSON output will instead be printed to stdout. The resulting JSON file is a serialized version of '
                 'the ScanResult objects described in SSLyze\'s Python API: the nodes and attributes will be the same. '
                 'See https://nabla-c0d3.github.io/sslyze/documentation/available-scan-commands.html for more details.',
            dest='json_file',
            default=None
        )
        # Read targets from input file
        output_group.add_option(
            '--targets_in',
            help='Read the list of targets to scan from the file TARGETS_IN. It should contain one host:port per '
                 'line.',
            dest='targets_in',
            default=None
        )
        # No text output
        output_group.add_option(
            '--quiet',
            action='store_true',
            dest='quiet',
            help='Do not output anything to stdout; useful when using --xml_out or --json_out.'
        )
        self._parser.add_option_group(output_group)

        # Connectivity option group
        connect_group = OptionGroup(self._parser, 'Connectivity options', '')
        # Connection speed
        connect_group.add_option(
            '--slow_connection',
            help='Greatly reduce the number of concurrent connections initiated by SSLyze. This will make the scans '
                 'slower but more reliable if the connection between your host and the server is slow, or if the '
                 'server cannot handle many concurrent connections. Enable this option if you are getting a lot of '
                 'timeouts or errors.',
            action='store_true',
            dest='slow_connection',
        )
        # HTTP CONNECT Proxy
        connect_group.add_option(
            '--https_tunnel',
            help='Tunnel all traffic to the target server(s) through an HTTP CONNECT proxy. HTTP_TUNNEL should be the '
                 'proxy\'s URL: \'http://*****:*****@HOST:PORT/\'. For proxies requiring authentication, only Basic '
                 'Authentication is supported.',
            dest='https_tunnel',
            default=None
        )
        # STARTTLS
        connect_group.add_option(
            '--starttls',
            help='Perform a StartTLS handshake when connecting to the target server(s). '
                 '{}'.format(self.START_TLS_USAGE),
            dest='starttls',
            default=None
        )
        connect_group.add_option(
            '--xmpp_to',
            help='Optional setting for STARTTLS XMPP. XMPP_TO should be the hostname to be put in the \'to\' '
                 'attribute of the XMPP stream. Default is the server\'s hostname.',
            dest='xmpp_to',
            default=None
        )
        # Server Name Indication
        connect_group.add_option(
            '--sni',
            help='Use Server Name Indication to specify the hostname to connect to.  Will only affect TLS 1.0+ '
                 'connections.',
            dest='sni',
            default=None
        )
        self._parser.add_option_group(connect_group)

    def _add_plugin_options(self, available_plugins: Set[Type[Plugin]]) -> None:
        """Recovers the list of command line options implemented by the available plugins and adds them to the command
        line parser.
        """
        for plugin_class in available_plugins:
            # Add the current plugin's commands to the parser
            group = OptionGroup(self._parser, plugin_class.get_title(), plugin_class.get_description())
            for option in plugin_class.get_cli_option_group():
                group.add_option(option)
            self._parser.add_option_group(group)
def buildOptions(parser=None, usage=None):
    """
    Build a list of command-line options we will accept

    @param parser: optparse parser
    @type parser: optparse object
    @param usage: description of how to use the program
    @type usage: string
    @return: optparse parser
    @rtype: optparse object
    """

   
    #Default option values
    defaultUsername = os.environ.get('USER', '')
    defaultPassword = ""
    defaultLoginTries = 1
    defaultLoginTimeout = 10
    defaultCommandTimeout = 10 
    defaultKeyPath = '~/.ssh/id_dsa'
    defaultConcurrentSessions = 10
    defaultSearchPath = []
    defaultExistanceTest = 'test -f %s'

    if not usage:
        usage = "%prog [options] hostname[:port] command"

    if not parser:
        from optparse import OptionParser
        parser = OptionParser(usage=usage, )
  
    parser.add_option('-u', '--user',
                dest='username',
                default=defaultUsername,
                help='Login username')
    parser.add_option('-P', '--password',
                dest='password',
                default=defaultPassword,
                help='Login password')
    parser.add_option('-t', '--loginTries',
                dest='loginTries',
                default=defaultLoginTries,
                type = 'int',
                help='Number of times to attempt to login')
    parser.add_option('-L', '--loginTimeout',
                dest='loginTimeout',
                type = 'float',
                default = defaultLoginTimeout,
                help='Timeout period (secs) to find login expect statments')
    parser.add_option('-T', '--commandTimeout',
                dest='commandTimeout',
                type = 'float',
                default = defaultCommandTimeout,
                help='Timeout period (secs) after issuing a command')
    parser.add_option('-K', '--keyPath',
                dest='keyPath',
                default = defaultKeyPath,
                help='Path to use when looking for SSH keys')
    parser.add_option('-S', '--concurrentSessions',
                dest='concurrentSessions',
                type='int',
                default = defaultConcurrentSessions,
                help='Allowable number of concurrent SSH sessions')
    parser.add_option('-s', '--searchPath',
                dest='searchPath',
                default=defaultSearchPath,
                help='Path to use when looking for commands')
    parser.add_option('-e', '--existenceTest',
                dest='existenceTest',
                default=defaultExistanceTest,
                help='How to check if a command is available or not')
    if not parser.has_option('-v'):
        parser.add_option('-v', '--logseverity',
                    dest='logseverity',
                    default=logging.INFO,
                    type='int',
                    help='Logging severity threshold')
    return parser
Пример #44
0
def main():

    usage = "usage: %prog config_file.ini"
    parser = OptionParser(usage=usage)
    (cmd_opt, args) = parser.parse_args()

    if len(args) == 1:
        config_files = [args[0]]
    else:
        config_files = ['download_ta_bdys.ini']

    parser = SafeConfigParser()
    found = parser.read(config_files)
    if not found:
        sys.exit('Could not load config ' + config_files[0])

    # set up logging
    logging.config.fileConfig(config_files[0],
                              defaults={'hostname': socket.gethostname()})
    logger = logging.getLogger()

    logger.info('Starting download TA boundaries')

    db_host = None
    db_rolename = None
    db_port = None
    db_user = None
    db_pass = None
    db_schema = 'public'
    layer_name = None
    layer_geom_column = None
    layer_output_srid = 4167
    create_grid = False
    grid_res = 0.05
    shift_geometry = False

    base_uri = parser.get('source', 'base_uri')
    db_name = parser.get('database', 'name')
    db_schema = parser.get('database', 'schema')

    if parser.has_option('database', 'rolename'):
        db_rolename = parser.get('database', 'rolename')
    if parser.has_option('database', 'host'):
        db_host = parser.get('database', 'host')
    if parser.has_option('database', 'port'):
        db_port = parser.get('database', 'port')
    if parser.has_option('database', 'user'):
        db_user = parser.get('database', 'user')
    if parser.has_option('database', 'password'):
        db_pass = parser.get('database', 'password')

    layer_name = parser.get('layer', 'name')
    layer_geom_column = parser.get('layer', 'geom_column')
    if parser.has_option('layer', 'output_srid'):
        layer_output_srid = parser.getint('layer', 'output_srid')
    if parser.has_option('layer', 'create_grid'):
        create_grid = parser.getboolean('layer', 'create_grid')
    if parser.has_option('layer', 'grid_res'):
        grid_res = parser.getfloat('layer', 'grid_res')
    if parser.has_option('layer', 'shift_geometry'):
        shift_geometry = parser.getboolean('layer', 'shift_geometry')

    try:
        output_srs = osr.SpatialReference()
        output_srs.ImportFromEPSG(layer_output_srid)
    except:
        logger.fatal("Output SRID %s is not valid" % (layer_output_srid))
        sys.exit(1)

    if create_grid and not grid_res > 0:
        logger.fatal("Grid resolution must be greater than 0")
        sys.exit(1)

    #
    # Determine TA layer and its year from REST service
    #

    logger.debug(base_uri + '?f=json')
    response = urllib2.urlopen(base_uri + '?f=json')
    capabilities = json.load(response)

    latest_service = None
    latest_year = None
    p = re.compile('((\d{4})\_Geographies)$', flags=re.UNICODE)
    for service in capabilities['services']:
        m = p.search(service['name'])
        if m:
            if not latest_year or m.group(2) > latest_year:
                latest_year = int(m.group(2))
                latest_service = m.group(1)

    logger.debug(base_uri + '/' + latest_service + '/MapServer?f=json')
    response = urllib2.urlopen(base_uri + '/' + latest_service +
                               '/MapServer?f=json')
    capabilities = json.load(response)

    ta_layer = None
    p = re.compile('^Territorial\sAuthorities\s\d{4}$', flags=re.UNICODE)
    for layer in capabilities['layers']:
        m = p.search(layer['name'])
        if m:
            ta_layer = layer
            break

    if not ta_layer:
        logger.fatal('Could not find the TA layer in ' + base_uri)
        sys.exit(1)

    feature_url = base_uri + '/' + latest_service + '/MapServer/' + str(ta_layer['id']) + \
        '/query?f=json&where=1=1&returnGeometry=true&outSR=' + str(layer_output_srid)

    geojson_drv = ogr.GetDriverByName('GeoJSON')
    if geojson_drv is None:
        logger.fatal('Could not load the OGR GeoJSON driver')
        sys.exit(1)

    #
    # Connect to the PostgreSQL database
    #

    pg_drv = ogr.GetDriverByName('PostgreSQL')
    if pg_drv is None:
        logger.fatal('Could not load the OGR PostgreSQL driver')
        sys.exit(1)

    pg_uri = 'PG:dbname=' + db_name
    if db_host:
        pg_uri = pg_uri + ' host=' + db_host
    if db_port:
        pg_uri = pg_uri + ' port=' + db_port
    if db_user:
        pg_uri = pg_uri + ' user='******' password='******'t open PG output database: " + str(e))
        sys.exit(1)
Пример #45
0
class CommandLineParser:
    # Defines what --regular means
    REGULAR_CMD = [
        "sslv2",
        "sslv3",
        "tlsv1",
        "tlsv1_1",
        "tlsv1_2",
        "tlsv1_3",
        "reneg",
        "resum",
        "certinfo",
        "hide_rejected_ciphers",
        "compression",
        "heartbleed",
        "openssl_ccs",
        "fallback",
        "robot",
    ]

    SSLYZE_USAGE = "usage: %prog [options] target1.com target2.com:443 target3.com:443{ip} etc..."

    START_TLS_USAGE = (
        "StartTLS should be one of: auto, {}. The 'auto' option will cause SSLyze to deduce the protocol "
        "(ftp, imap, etc.) from the supplied port number, "
        "for each target servers.".format(", ".join(
            _STARTTLS_PROTOCOL_DICT.keys())))

    def __init__(self, sslyze_version: str) -> None:
        """Generate SSLyze's command line parser.
        """
        self._parser = OptionParser(version=sslyze_version,
                                    usage=self.SSLYZE_USAGE)

        # Add generic command line options to the parser
        self._add_default_options()

        # Add plugin-specific options to the parser
        self._add_plugin_scan_commands()

        # Add the --regular command line parameter as a shortcut if possible
        regular_help = "Regular HTTPS scan; shortcut for --{}".format(
            " --".join(self.REGULAR_CMD))
        self._parser.add_option("--regular",
                                action="store_true",
                                dest=None,
                                help=regular_help)

    def parse_command_line(self) -> ParsedCommandLine:
        """Parses the command line used to launch SSLyze.
        """
        (args_command_list, args_target_list) = self._parser.parse_args()

        if args_command_list.update_trust_stores:
            # Just update the trust stores and do nothing
            TrustStoresRepository.update_default()
            raise TrustStoresUpdateCompleted()

        # Handle the --targets_in command line and fill args_target_list
        if args_command_list.targets_in:
            if args_target_list:
                raise CommandLineParsingError(
                    "Cannot use --targets_list and specify targets within the command line."
                )

            try:  # Read targets from a file
                with open(args_command_list.targets_in) as f:
                    for target in f.readlines():
                        if target.strip():  # Ignore empty lines
                            if not target.startswith(
                                    "#"):  # Ignore comment lines
                                args_target_list.append(target.strip())
            except IOError:
                raise CommandLineParsingError(
                    "Can't read targets from input file '{}.".format(
                        args_command_list.targets_in))

        if not args_target_list:
            raise CommandLineParsingError("No targets to scan.")

        # Handle the --regular command line parameter as a shortcut
        if self._parser.has_option("--regular"):
            if getattr(args_command_list, "regular"):
                setattr(args_command_list, "regular", False)
                for cmd in self.REGULAR_CMD:
                    setattr(args_command_list, cmd, True)

        # Handle JSON settings
        should_print_json_to_console = False
        json_path_out: Optional[Path] = None
        if args_command_list.json_file:
            if args_command_list.json_file == "-":
                if args_command_list.quiet:
                    raise CommandLineParsingError(
                        "Cannot use --quiet with --json_out -.")
                should_print_json_to_console = True
            else:
                json_path_out = Path(args_command_list.json_file).absolute()

        # Sanity checks on the client cert options
        client_auth_creds = None
        if bool(args_command_list.cert) ^ bool(args_command_list.key):
            raise CommandLineParsingError(
                "No private key or certificate file were given. See --cert and --key."
            )

        elif args_command_list.cert:
            # Private key formats
            if args_command_list.keyform == "DER":
                key_type = OpenSslFileTypeEnum.ASN1
            elif args_command_list.keyform == "PEM":
                key_type = OpenSslFileTypeEnum.PEM
            else:
                raise CommandLineParsingError(
                    "--keyform should be DER or PEM.")

            # Let's try to open the cert and key files
            try:
                client_auth_creds = ClientAuthenticationCredentials(
                    certificate_chain_path=Path(args_command_list.cert),
                    key_path=Path(args_command_list.key),
                    key_password=args_command_list.keypass,
                    key_type=key_type,
                )
            except ValueError as e:
                raise CommandLineParsingError(
                    "Invalid client authentication settings: {}.".format(
                        e.args[0]))

        # HTTP CONNECT proxy
        http_proxy_settings = None
        if args_command_list.https_tunnel:
            try:
                http_proxy_settings = HttpProxySettings.from_url(
                    args_command_list.https_tunnel)
            except ValueError as e:
                raise CommandLineParsingError(
                    "Invalid proxy URL for --https_tunnel: {}.".format(
                        e.args[0]))

        # Create the server location objects for each specified servers
        good_servers: List[Tuple[ServerNetworkLocation,
                                 ServerNetworkConfiguration]] = []
        invalid_server_strings: List[InvalidServerStringError] = []
        for server_string in args_target_list:
            try:
                # Parse the string supplied via the CLI for this server
                hostname, ip_address, port = CommandLineServerStringParser.parse_server_string(
                    server_string)
            except InvalidServerStringError as e:
                # The server string is malformed
                invalid_server_strings.append(e)
                continue

            # If not port number was supplied, assume 443
            final_port = port if port else 443

            # Figure out how we're going to connect to the server
            server_location: ServerNetworkLocation
            if http_proxy_settings:
                # Connect to the server via an HTTP proxy
                # A limitation when using the CLI is that only one http_proxy_settings can be specified for all servers
                server_location = ServerNetworkLocationViaHttpProxy(
                    hostname=hostname,
                    port=final_port,
                    http_proxy_settings=http_proxy_settings)
            else:
                # Connect to the server directly
                if ip_address:
                    server_location = ServerNetworkLocationViaDirectConnection(
                        hostname=hostname,
                        port=final_port,
                        ip_address=ip_address)
                else:
                    # No IP address supplied - do a DNS lookup
                    try:
                        server_location = ServerNetworkLocationViaDirectConnection.with_ip_address_lookup(
                            hostname=hostname, port=final_port)
                    except ServerHostnameCouldNotBeResolved:
                        invalid_server_strings.append(
                            InvalidServerStringError(
                                server_string=f"{hostname}:{final_port}",
                                error_message=
                                f"Could not resolve hostname {hostname}",
                            ))
                        continue

            # Figure out extra network config for this server
            # Opportunistic TLS
            opportunistic_tls: Optional[
                ProtocolWithOpportunisticTlsEnum] = None
            if args_command_list.starttls:
                if args_command_list.starttls == "auto":
                    # Special value to auto-derive the protocol from the port number
                    opportunistic_tls = ProtocolWithOpportunisticTlsEnum.from_default_port(
                        final_port)
                elif args_command_list.starttls in _STARTTLS_PROTOCOL_DICT:
                    opportunistic_tls = _STARTTLS_PROTOCOL_DICT[
                        args_command_list.starttls]
                else:
                    raise CommandLineParsingError(self.START_TLS_USAGE)

            try:
                sni_hostname = args_command_list.sni if args_command_list.sni else hostname
                network_config = ServerNetworkConfiguration(
                    tls_opportunistic_encryption=opportunistic_tls,
                    tls_server_name_indication=sni_hostname,
                    tls_client_auth_credentials=client_auth_creds,
                    xmpp_to_hostname=args_command_list.xmpp_to,
                )
                good_servers.append((server_location, network_config))
            except InvalidServerNetworkConfigurationError as e:
                raise CommandLineParsingError(e.args[0])

        # Figure out global network settings
        concurrent_server_scans_limit = None
        per_server_concurrent_connections_limit = None
        if args_command_list.https_tunnel:
            # All the connections will go through a single proxy; only scan one server at a time to not DOS the proxy
            concurrent_server_scans_limit = 1
        if args_command_list.slow_connection:
            # Go easy on the servers; only open 2 concurrent connections against each server
            per_server_concurrent_connections_limit = 2

        # Figure out the scan commands that are enabled
        scan_commands: Set[ScanCommandType] = set()
        scan_commands_extra_arguments: ScanCommandExtraArgumentsDict = {}
        for scan_command in ScanCommandsRepository.get_all_scan_commands():
            cli_connector_cls = ScanCommandsRepository.get_implementation_cls(
                scan_command).cli_connector_cls
            is_scan_cmd_enabled, extra_args = cli_connector_cls.find_cli_options_in_command_line(
                args_command_list.__dict__)
            if is_scan_cmd_enabled:
                scan_commands.add(scan_command)
                if extra_args:
                    scan_commands_extra_arguments[
                        scan_command] = extra_args  # type: ignore

        return ParsedCommandLine(
            invalid_servers=invalid_server_strings,
            servers_to_scans=good_servers,
            scan_commands=scan_commands,
            scan_commands_extra_arguments=scan_commands_extra_arguments,
            should_print_json_to_console=should_print_json_to_console,
            json_path_out=json_path_out,
            should_disable_console_output=args_command_list.quiet
            or args_command_list.json_file == "-",
            concurrent_server_scans_limit=concurrent_server_scans_limit,
            per_server_concurrent_connections_limit=
            per_server_concurrent_connections_limit,
        )

    def _add_default_options(self) -> None:
        """Add default command line options to the parser.
        """
        # Updating the trust stores
        update_stores_group = OptionGroup(self._parser, "Trust stores options",
                                          "")
        update_stores_group.add_option(
            "--update_trust_stores",
            help=
            "Update the default trust stores used by SSLyze. The latest stores will be downloaded from "
            "https://github.com/nabla-c0d3/trust_stores_observatory. This option is meant to be used separately, "
            "and will silence any other command line option supplied to SSLyze.",
            dest="update_trust_stores",
            action="store_true",
        )
        self._parser.add_option_group(update_stores_group)

        # Client certificate options
        clientcert_group = OptionGroup(self._parser,
                                       "Client certificate options", "")
        clientcert_group.add_option(
            "--cert",
            help=
            "Client certificate chain filename. The certificates must be in PEM format and must be sorted "
            "starting with the subject's client certificate, followed by intermediate CA certificates if "
            "applicable.",
            dest="cert",
        )
        clientcert_group.add_option("--key",
                                    help="Client private key filename.",
                                    dest="key")
        clientcert_group.add_option(
            "--keyform",
            help="Client private key format. DER or PEM (default).",
            dest="keyform",
            default="PEM")
        clientcert_group.add_option("--pass",
                                    help="Client private key passphrase.",
                                    dest="keypass",
                                    default="")
        self._parser.add_option_group(clientcert_group)

        # Input / output
        output_group = OptionGroup(self._parser, "Input and output options",
                                   "")
        # JSON output
        output_group.add_option(
            "--json_out",
            help=
            'Write the scan results as a JSON document to the file JSON_FILE. If JSON_FILE is set to "-", the '
            "JSON output will instead be printed to stdout. The resulting JSON file is a serialized version of "
            "the ScanResult objects described in SSLyze's Python API: the nodes and attributes will be the same. "
            "See https://nabla-c0d3.github.io/sslyze/documentation/available-scan-commands.html for more details.",
            dest="json_file",
            default=None,
        )
        # Read targets from input file
        output_group.add_option(
            "--targets_in",
            help=
            "Read the list of targets to scan from the file TARGETS_IN. It should contain one host:port per "
            "line.",
            dest="targets_in",
            default=None,
        )
        # No text output
        output_group.add_option(
            "--quiet",
            action="store_true",
            dest="quiet",
            help=
            "Do not output anything to stdout; useful when using --json_out.",
        )
        self._parser.add_option_group(output_group)

        # Connectivity option group
        connect_group = OptionGroup(self._parser, "Connectivity options", "")
        # Connection speed
        connect_group.add_option(
            "--slow_connection",
            help=
            "Greatly reduce the number of concurrent connections initiated by SSLyze. This will make the scans "
            "slower but more reliable if the connection between your host and the server is slow, or if the "
            "server cannot handle many concurrent connections. Enable this option if you are getting a lot of "
            "timeouts or errors.",
            action="store_true",
            dest="slow_connection",
        )
        # HTTP CONNECT Proxy
        connect_group.add_option(
            "--https_tunnel",
            help=
            "Tunnel all traffic to the target server(s) through an HTTP CONNECT proxy. HTTP_TUNNEL should be the "
            "proxy's URL: 'http://*****:*****@HOST:PORT/'. For proxies requiring authentication, only Basic "
            "Authentication is supported.",
            dest="https_tunnel",
            default=None,
        )
        # STARTTLS
        connect_group.add_option(
            "--starttls",
            help=
            "Perform a StartTLS handshake when connecting to the target server(s). "
            "{}".format(self.START_TLS_USAGE),
            dest="starttls",
            default=None,
        )
        connect_group.add_option(
            "--xmpp_to",
            help=
            "Optional setting for STARTTLS XMPP. XMPP_TO should be the hostname to be put in the 'to' "
            "attribute of the XMPP stream. Default is the server's hostname.",
            dest="xmpp_to",
            default=None,
        )
        # Server Name Indication
        connect_group.add_option(
            "--sni",
            help=
            "Use Server Name Indication to specify the hostname to connect to.  Will only affect TLS 1.0+ "
            "connections.",
            dest="sni",
            default=None,
        )
        self._parser.add_option_group(connect_group)

    def _add_plugin_scan_commands(self) -> None:
        """Recovers the list of command line options implemented by the available plugins and adds them to the command
        line parser.
        """
        scan_commands_group = OptionGroup(self._parser, "Scan commands", "")
        for scan_command in ScanCommandsRepository.get_all_scan_commands():
            cli_connector_cls = ScanCommandsRepository.get_implementation_cls(
                scan_command).cli_connector_cls
            for option in cli_connector_cls.get_cli_options():
                scan_commands_group.add_option(f"--{option.option}",
                                               help=option.help,
                                               action=option.action)

        self._parser.add_option_group(scan_commands_group)
Пример #46
0
def parse_opts(tmpcmdline, silent=False):
	myaction=None
	myopts = {}
	myfiles=[]

	actions = frozenset([
		"clean", "check-news", "config", "depclean", "help",
		"info", "list-sets", "metadata", "moo",
		"prune", "regen",  "search",
		"sync",  "unmerge", "version",
	])

	longopt_aliases = {"--cols":"--columns", "--skip-first":"--skipfirst"}
	y_or_n = ("y", "n")
	true_y_or_n = ("True", "y", "n")
	true_y = ("True", "y")
	argument_options = {

		"--ask": {
			"shortopt" : "-a",
			"help"    : "prompt before performing any actions",
			"type"    : "choice",
			"choices" : true_y_or_n
		},

		"--autounmask": {
			"help"    : "automatically unmask packages",
			"type"    : "choice",
			"choices" : true_y_or_n
		},

		"--autounmask-unrestricted-atoms": {
			"help"    : "write autounmask changes with >= atoms if possible",
			"type"    : "choice",
			"choices" : true_y_or_n
		},

		"--autounmask-keep-masks": {
			"help"    : "don't add package.unmask entries",
			"type"    : "choice",
			"choices" : true_y_or_n
		},

		"--autounmask-write": {
			"help"    : "write changes made by --autounmask to disk",
			"type"    : "choice",
			"choices" : true_y_or_n
		},

		"--accept-properties": {
			"help":"temporarily override ACCEPT_PROPERTIES",
			"action":"store"
		},

		"--backtrack": {

			"help"   : "Specifies how many times to backtrack if dependency " + \
				"calculation fails ",

			"action" : "store"
		},

		"--buildpkg": {
			"shortopt" : "-b",
			"help"     : "build binary packages",
			"type"     : "choice",
			"choices"  : true_y_or_n
		},

		"--buildpkg-exclude": {
			"help"   :"A space separated list of package atoms for which " + \
				"no binary packages should be built. This option overrides all " + \
				"possible ways to enable building of binary packages.",

			"action" : "append"
		},

		"--config-root": {
			"help":"specify the location for portage configuration files",
			"action":"store"
		},
		"--color": {
			"help":"enable or disable color output",
			"type":"choice",
			"choices":("y", "n")
		},

		"--complete-graph": {
			"help"    : "completely account for all known dependencies",
			"type"    : "choice",
			"choices" : true_y_or_n
		},

		"--complete-graph-if-new-use": {
			"help"    : "trigger --complete-graph behavior if USE or IUSE will change for an installed package",
			"type"    : "choice",
			"choices" : y_or_n
		},

		"--complete-graph-if-new-ver": {
			"help"    : "trigger --complete-graph behavior if an installed package version will change (upgrade or downgrade)",
			"type"    : "choice",
			"choices" : y_or_n
		},

		"--deep": {

			"shortopt" : "-D",

			"help"   : "Specifies how deep to recurse into dependencies " + \
				"of packages given as arguments. If no argument is given, " + \
				"depth is unlimited. Default behavior is to skip " + \
				"dependencies of installed packages.",

			"action" : "store"
		},

		"--depclean-lib-check": {
			"help"    : "check for consumers of libraries before removing them",
			"type"    : "choice",
			"choices" : true_y_or_n
		},

		"--deselect": {
			"help"    : "remove atoms/sets from the world file",
			"type"    : "choice",
			"choices" : true_y_or_n
		},

		"--dynamic-deps": {
			"help": "substitute the dependencies of installed packages with the dependencies of unbuilt ebuilds",
			"type": "choice",
			"choices": y_or_n
		},

		"--exclude": {
			"help"   :"A space separated list of package names or slot atoms. " + \
				"Emerge won't  install any ebuild or binary package that " + \
				"matches any of the given package atoms.",

			"action" : "append"
		},

		"--fail-clean": {
			"help"    : "clean temp files after build failure",
			"type"    : "choice",
			"choices" : true_y_or_n
		},

		"--ignore-built-slot-operator-deps": {
			"help": "Ignore the slot/sub-slot := operator parts of dependencies that have "
				"been recorded when packages where built. This option is intended "
				"only for debugging purposes, and it only affects built packages "
				"that specify slot/sub-slot := operator dependencies using the "
				"experimental \"4-slot-abi\" EAPI.",
			"type": "choice",
			"choices": y_or_n
		},

		"--jobs": {

			"shortopt" : "-j",

			"help"   : "Specifies the number of packages to build " + \
				"simultaneously.",

			"action" : "store"
		},

		"--keep-going": {
			"help"    : "continue as much as possible after an error",
			"type"    : "choice",
			"choices" : true_y_or_n
		},

		"--load-average": {

			"help"   :"Specifies that no new builds should be started " + \
				"if there are other builds running and the load average " + \
				"is at least LOAD (a floating-point number).",

			"action" : "store"
		},

		"--misspell-suggestions": {
			"help"    : "enable package name misspell suggestions",
			"type"    : "choice",
			"choices" : ("y", "n")
		},

		"--with-bdeps": {
			"help":"include unnecessary build time dependencies",
			"type":"choice",
			"choices":("y", "n")
		},
		"--reinstall": {
			"help":"specify conditions to trigger package reinstallation",
			"type":"choice",
			"choices":["changed-use"]
		},

		"--reinstall-atoms": {
			"help"   :"A space separated list of package names or slot atoms. " + \
				"Emerge will treat matching packages as if they are not " + \
				"installed, and reinstall them if necessary. Implies --deep.",

			"action" : "append",
		},

		"--binpkg-respect-use": {
			"help"    : "discard binary packages if their use flags \
				don't match the current configuration",
			"type"    : "choice",
			"choices" : true_y_or_n
		},

		"--getbinpkg": {
			"shortopt" : "-g",
			"help"     : "fetch binary packages",
			"type"     : "choice",
			"choices"  : true_y_or_n
		},

		"--getbinpkgonly": {
			"shortopt" : "-G",
			"help"     : "fetch binary packages only",
			"type"     : "choice",
			"choices"  : true_y_or_n
		},

		"--usepkg-exclude": {
			"help"   :"A space separated list of package names or slot atoms. " + \
				"Emerge will ignore matching binary packages. ",

			"action" : "append",
		},

		"--rebuild-exclude": {
			"help"   :"A space separated list of package names or slot atoms. " + \
				"Emerge will not rebuild these packages due to the " + \
				"--rebuild flag. ",

			"action" : "append",
		},

		"--rebuild-ignore": {
			"help"   :"A space separated list of package names or slot atoms. " + \
				"Emerge will not rebuild packages that depend on matching " + \
				"packages due to the --rebuild flag. ",

			"action" : "append",
		},

		"--package-moves": {
			"help"     : "perform package moves when necessary",
			"type"     : "choice",
			"choices"  : true_y_or_n
		},

		"--quiet": {
			"shortopt" : "-q",
			"help"     : "reduced or condensed output",
			"type"     : "choice",
			"choices"  : true_y_or_n
		},

		"--quiet-build": {
			"help"     : "redirect build output to logs",
			"type"     : "choice",
			"choices"  : true_y_or_n,
		},

		"--quiet-fail": {
			"help"     : "suppresses display of the build log on stdout",
			"type"     : "choice",
			"choices"  : true_y_or_n,
		},

		"--rebuild-if-new-slot": {
			"help"     : ("Automatically rebuild or reinstall packages when slot/sub-slot := "
				"operator dependencies can be satisfied by a newer slot, so that "
				"older packages slots will become eligible for removal by the "
				"--depclean action as soon as possible."),
			"type"     : "choice",
			"choices"  : true_y_or_n
		},

		"--rebuild-if-new-rev": {
			"help"     : "Rebuild packages when dependencies that are " + \
				"used at both build-time and run-time are built, " + \
				"if the dependency is not already installed with the " + \
				"same version and revision.",
			"type"     : "choice",
			"choices"  : true_y_or_n
		},

		"--rebuild-if-new-ver": {
			"help"     : "Rebuild packages when dependencies that are " + \
				"used at both build-time and run-time are built, " + \
				"if the dependency is not already installed with the " + \
				"same version. Revision numbers are ignored.",
			"type"     : "choice",
			"choices"  : true_y_or_n
		},

		"--rebuild-if-unbuilt": {
			"help"     : "Rebuild packages when dependencies that are " + \
				"used at both build-time and run-time are built.",
			"type"     : "choice",
			"choices"  : true_y_or_n
		},

		"--rebuilt-binaries": {
			"help"     : "replace installed packages with binary " + \
			             "packages that have been rebuilt",
			"type"     : "choice",
			"choices"  : true_y_or_n
		},
		
		"--rebuilt-binaries-timestamp": {
			"help"   : "use only binaries that are newer than this " + \
			           "timestamp for --rebuilt-binaries",
			"action" : "store"
		},

		"--root": {
		 "help"   : "specify the target root filesystem for merging packages",
		 "action" : "store"
		},

		"--root-deps": {
			"help"    : "modify interpretation of depedencies",
			"type"    : "choice",
			"choices" :("True", "rdeps")
		},

		"--select": {
			"shortopt" : "-w",
			"help"    : "add specified packages to the world set " + \
			            "(inverse of --oneshot)",
			"type"    : "choice",
			"choices" : true_y_or_n
		},

		"--selective": {
			"help"    : "identical to --noreplace",
			"type"    : "choice",
			"choices" : true_y_or_n
		},

		"--use-ebuild-visibility": {
			"help"     : "use unbuilt ebuild metadata for visibility checks on built packages",
			"type"     : "choice",
			"choices"  : true_y_or_n
		},

		"--useoldpkg-atoms": {
			"help"   :"A space separated list of package names or slot atoms. " + \
				"Emerge will prefer matching binary packages over newer unbuilt packages. ",

			"action" : "append",
		},

		"--usepkg": {
			"shortopt" : "-k",
			"help"     : "use binary packages",
			"type"     : "choice",
			"choices"  : true_y_or_n
		},

		"--usepkgonly": {
			"shortopt" : "-K",
			"help"     : "use only binary packages",
			"type"     : "choice",
			"choices"  : true_y_or_n
		},

		"--verbose": {
			"shortopt" : "-v",
			"help"     : "verbose output",
			"type"     : "choice",
			"choices"  : true_y_or_n
		},
	}

	from optparse import OptionParser
	parser = OptionParser()
	if parser.has_option("--help"):
		parser.remove_option("--help")

	for action_opt in actions:
		parser.add_option("--" + action_opt, action="store_true",
			dest=action_opt.replace("-", "_"), default=False)
	for myopt in options:
		parser.add_option(myopt, action="store_true",
			dest=myopt.lstrip("--").replace("-", "_"), default=False)
	for shortopt, longopt in shortmapping.items():
		parser.add_option("-" + shortopt, action="store_true",
			dest=longopt.lstrip("--").replace("-", "_"), default=False)
	for myalias, myopt in longopt_aliases.items():
		parser.add_option(myalias, action="store_true",
			dest=myopt.lstrip("--").replace("-", "_"), default=False)

	for myopt, kwargs in argument_options.items():
		shortopt = kwargs.pop("shortopt", None)
		args = [myopt]
		if shortopt is not None:
			args.append(shortopt)
		parser.add_option(dest=myopt.lstrip("--").replace("-", "_"),
			*args, **kwargs)

	tmpcmdline = insert_optional_args(tmpcmdline)

	myoptions, myargs = parser.parse_args(args=tmpcmdline)

	if myoptions.ask in true_y:
		myoptions.ask = True
	else:
		myoptions.ask = None

	if myoptions.autounmask in true_y:
		myoptions.autounmask = True

	if myoptions.autounmask_unrestricted_atoms in true_y:
		myoptions.autounmask_unrestricted_atoms = True

	if myoptions.autounmask_keep_masks in true_y:
		myoptions.autounmask_keep_masks = True

	if myoptions.autounmask_write in true_y:
		myoptions.autounmask_write = True

	if myoptions.buildpkg in true_y:
		myoptions.buildpkg = True

	if myoptions.buildpkg_exclude:
		bad_atoms = _find_bad_atoms(myoptions.buildpkg_exclude, less_strict=True)
		if bad_atoms and not silent:
			parser.error("Invalid Atom(s) in --buildpkg-exclude parameter: '%s'\n" % \
				(",".join(bad_atoms),))

	if myoptions.changed_use is not False:
		myoptions.reinstall = "changed-use"
		myoptions.changed_use = False

	if myoptions.deselect in true_y:
		myoptions.deselect = True

	if myoptions.binpkg_respect_use is not None:
		if myoptions.binpkg_respect_use in true_y:
			myoptions.binpkg_respect_use = 'y'
		else:
			myoptions.binpkg_respect_use = 'n'

	if myoptions.complete_graph in true_y:
		myoptions.complete_graph = True
	else:
		myoptions.complete_graph = None

	if myoptions.depclean_lib_check in true_y:
		myoptions.depclean_lib_check = True

	if myoptions.exclude:
		bad_atoms = _find_bad_atoms(myoptions.exclude)
		if bad_atoms and not silent:
			parser.error("Invalid Atom(s) in --exclude parameter: '%s' (only package names and slot atoms (with wildcards) allowed)\n" % \
				(",".join(bad_atoms),))

	if myoptions.reinstall_atoms:
		bad_atoms = _find_bad_atoms(myoptions.reinstall_atoms)
		if bad_atoms and not silent:
			parser.error("Invalid Atom(s) in --reinstall-atoms parameter: '%s' (only package names and slot atoms (with wildcards) allowed)\n" % \
				(",".join(bad_atoms),))

	if myoptions.rebuild_exclude:
		bad_atoms = _find_bad_atoms(myoptions.rebuild_exclude)
		if bad_atoms and not silent:
			parser.error("Invalid Atom(s) in --rebuild-exclude parameter: '%s' (only package names and slot atoms (with wildcards) allowed)\n" % \
				(",".join(bad_atoms),))

	if myoptions.rebuild_ignore:
		bad_atoms = _find_bad_atoms(myoptions.rebuild_ignore)
		if bad_atoms and not silent:
			parser.error("Invalid Atom(s) in --rebuild-ignore parameter: '%s' (only package names and slot atoms (with wildcards) allowed)\n" % \
				(",".join(bad_atoms),))

	if myoptions.usepkg_exclude:
		bad_atoms = _find_bad_atoms(myoptions.usepkg_exclude)
		if bad_atoms and not silent:
			parser.error("Invalid Atom(s) in --usepkg-exclude parameter: '%s' (only package names and slot atoms (with wildcards) allowed)\n" % \
				(",".join(bad_atoms),))

	if myoptions.useoldpkg_atoms:
		bad_atoms = _find_bad_atoms(myoptions.useoldpkg_atoms)
		if bad_atoms and not silent:
			parser.error("Invalid Atom(s) in --useoldpkg-atoms parameter: '%s' (only package names and slot atoms (with wildcards) allowed)\n" % \
				(",".join(bad_atoms),))

	if myoptions.fail_clean in true_y:
		myoptions.fail_clean = True

	if myoptions.getbinpkg in true_y:
		myoptions.getbinpkg = True
	else:
		myoptions.getbinpkg = None

	if myoptions.getbinpkgonly in true_y:
		myoptions.getbinpkgonly = True
	else:
		myoptions.getbinpkgonly = None

	if myoptions.keep_going in true_y:
		myoptions.keep_going = True
	else:
		myoptions.keep_going = None

	if myoptions.package_moves in true_y:
		myoptions.package_moves = True

	if myoptions.quiet in true_y:
		myoptions.quiet = True
	else:
		myoptions.quiet = None

	if myoptions.quiet_build in true_y:
		myoptions.quiet_build = 'y'

	if myoptions.quiet_fail in true_y:
		myoptions.quiet_fail = 'y'

	if myoptions.rebuild_if_new_slot in true_y:
		myoptions.rebuild_if_new_slot = 'y'

	if myoptions.rebuild_if_new_ver in true_y:
		myoptions.rebuild_if_new_ver = True
	else:
		myoptions.rebuild_if_new_ver = None

	if myoptions.rebuild_if_new_rev in true_y:
		myoptions.rebuild_if_new_rev = True
		myoptions.rebuild_if_new_ver = None
	else:
		myoptions.rebuild_if_new_rev = None

	if myoptions.rebuild_if_unbuilt in true_y:
		myoptions.rebuild_if_unbuilt = True
		myoptions.rebuild_if_new_rev = None
		myoptions.rebuild_if_new_ver = None
	else:
		myoptions.rebuild_if_unbuilt = None

	if myoptions.rebuilt_binaries in true_y:
		myoptions.rebuilt_binaries = True

	if myoptions.root_deps in true_y:
		myoptions.root_deps = True

	if myoptions.select in true_y:
		myoptions.select = True
		myoptions.oneshot = False
	elif myoptions.select == "n":
		myoptions.oneshot = True

	if myoptions.selective in true_y:
		myoptions.selective = True

	if myoptions.backtrack is not None:

		try:
			backtrack = int(myoptions.backtrack)
		except (OverflowError, ValueError):
			backtrack = -1

		if backtrack < 0:
			backtrack = None
			if not silent:
				parser.error("Invalid --backtrack parameter: '%s'\n" % \
					(myoptions.backtrack,))

		myoptions.backtrack = backtrack

	if myoptions.deep is not None:
		deep = None
		if myoptions.deep == "True":
			deep = True
		else:
			try:
				deep = int(myoptions.deep)
			except (OverflowError, ValueError):
				deep = -1

		if deep is not True and deep < 0:
			deep = None
			if not silent:
				parser.error("Invalid --deep parameter: '%s'\n" % \
					(myoptions.deep,))

		myoptions.deep = deep

	if myoptions.jobs:
		jobs = None
		if myoptions.jobs == "True":
			jobs = True
		else:
			try:
				jobs = int(myoptions.jobs)
			except ValueError:
				jobs = -1

		if jobs is not True and \
			jobs < 1:
			jobs = None
			if not silent:
				parser.error("Invalid --jobs parameter: '%s'\n" % \
					(myoptions.jobs,))

		myoptions.jobs = jobs

	if myoptions.load_average == "True":
		myoptions.load_average = None

	if myoptions.load_average:
		try:
			load_average = float(myoptions.load_average)
		except ValueError:
			load_average = 0.0

		if load_average <= 0.0:
			load_average = None
			if not silent:
				parser.error("Invalid --load-average parameter: '%s'\n" % \
					(myoptions.load_average,))

		myoptions.load_average = load_average
	
	if myoptions.rebuilt_binaries_timestamp:
		try:
			rebuilt_binaries_timestamp = int(myoptions.rebuilt_binaries_timestamp)
		except ValueError:
			rebuilt_binaries_timestamp = -1

		if rebuilt_binaries_timestamp < 0:
			rebuilt_binaries_timestamp = 0
			if not silent:
				parser.error("Invalid --rebuilt-binaries-timestamp parameter: '%s'\n" % \
					(myoptions.rebuilt_binaries_timestamp,))

		myoptions.rebuilt_binaries_timestamp = rebuilt_binaries_timestamp

	if myoptions.use_ebuild_visibility in true_y:
		myoptions.use_ebuild_visibility = True
	else:
		# None or "n"
		pass

	if myoptions.usepkg in true_y:
		myoptions.usepkg = True
	else:
		myoptions.usepkg = None

	if myoptions.usepkgonly in true_y:
		myoptions.usepkgonly = True
	else:
		myoptions.usepkgonly = None

	if myoptions.verbose in true_y:
		myoptions.verbose = True
	else:
		myoptions.verbose = None

	for myopt in options:
		v = getattr(myoptions, myopt.lstrip("--").replace("-", "_"))
		if v:
			myopts[myopt] = True

	for myopt in argument_options:
		v = getattr(myoptions, myopt.lstrip("--").replace("-", "_"), None)
		if v is not None:
			myopts[myopt] = v

	if myoptions.searchdesc:
		myoptions.search = True

	for action_opt in actions:
		v = getattr(myoptions, action_opt.replace("-", "_"))
		if v:
			if myaction:
				multiple_actions(myaction, action_opt)
				sys.exit(1)
			myaction = action_opt

	if myaction is None and myoptions.deselect is True:
		myaction = 'deselect'

	if myargs and isinstance(myargs[0], bytes):
		for i in range(len(myargs)):
			myargs[i] = portage._unicode_decode(myargs[i])

	myfiles += myargs

	return myaction, myopts, myfiles
Пример #47
0
def create_command_line_parser(available_plugins, prog_version, timeout):
    """
    Generates the list of possible command line options by calling the
    get_commands() method of available plugins.
    Then, it generates the associated command line parser and returns
    (parser, available_commands).
    """
    usage = 'usage: %prog [options] target1.com target2.com:443 etc...'
    parser = OptionParser(version=prog_version, usage=usage)
    available_commands = {}

    # TODO: Verbose/Debug

    # Client certificate options
    clientcert_group = OptionGroup(parser, 'Client certificate support',\
                            '')
    clientcert_group.add_option(
        '--cert',
        help='Client certificate filename.',
        dest='cert')
    clientcert_group.add_option(
        '--certform',
        help= 'Client certificate format. DER or PEM (default).',
        dest='certform',
        default='PEM')
    clientcert_group.add_option(
        '--key',
        help= 'Client private key filename.',
        dest='key')
    clientcert_group.add_option(
        '--keyform',
        help= 'Client private key format. DER or PEM (default).',
        dest='keyform',
        default='PEM')
    clientcert_group.add_option(
        '--pass',
        help= 'Client private key passphrase.',
        dest='keypass')
    parser.add_option_group(clientcert_group)

    # XML output
    parser.add_option(
        '--xml_file',
        help= (
            'Output the scan results to an XML file. '
            'XML_FILE should be the name of the file to write to.'),
        dest='xml_file',
        default=None)

    # Timeout
    parser.add_option(
        '--timeout',
        help= (
            'Sets the timeout value in seconds used for every socket '
            'connection made to the target server(s). Default is 5s.'),
        type='int',
        dest='timeout',
        default=timeout)

    
    # HTTP CONNECT Proxy
    parser.add_option(
        '--https_tunnel',
        help= (
            'Sets an HTTP CONNECT proxy to tunnel SSL traffic to the target '
            'server(s). HTTP_TUNNEL should be \'host:port\'. ' 
            'Requires Python 2.7'),
        dest='https_tunnel',
        default=None)
    
    # STARTTLS
    parser.add_option(
        '--starttls',
        help= (
            'Identifies the target server(s) as a SMTP or an XMPP server(s) '
            'and scans the server(s) using STARTTLS. '
            'STARTTLS should be \'smtp\' or \'xmpp\'.'),
        dest='starttls',
        default=None)

    parser.add_option(
        '--xmpp_to',
        help= (
            'Optional setting for STARTTLS XMPP. '
            ' XMPP_TO should be the hostname to be put in the \'to\' attribute '
            'of the XMPP stream. Default is the server\'s hostname.'),
        dest='xmpp_to',
        default=None)

    # Add plugin options to the parser
    for plugin_class in available_plugins:
        pluginoptiongroup = plugin_class.get_commands()

        # Get the list of commands implemented by the current plugin
        plugin_commands = (zip(*pluginoptiongroup.commands))[0]
        # Keep track of which plugin/module supports which command
        for command in plugin_commands:
            available_commands[command] = plugin_class

        # Add the current plugin's commands to the parser
        group = OptionGroup(parser, pluginoptiongroup.title,\
                            pluginoptiongroup.description)
        for option in pluginoptiongroup.commands:
            # If dest is something, store it, otherwise just use store_true
            if option[2] is not None:
                group.add_option('--' + option[0], action="store",
                                    help=option[1], dest=option[2])
            else:
                group.add_option('--' + option[0], action="store_true",
                                    help=option[1], dest=option[2])

        # Add the current plugin's options to the parser
        for option in pluginoptiongroup.options:
            # If dest is something, store it, otherwise just use store_true
            if option[2] is not None:
                group.add_option('--' + option[0], action="store",
                                    help=option[1], dest=option[2])
            else:
                group.add_option('--' + option[0], action="store_true",
                                    help=option[1], dest=option[2])
        parser.add_option_group(group)

    # Add the --regular command line parameter as a shortcut
    if parser.has_option('--sslv2') and parser.has_option('--sslv3') \
        and parser.has_option('--tlsv1') and parser.has_option('--reneg') \
        and parser.has_option('--resum') and parser.has_option('--certinfo') \
        and parser.has_option('--http_get') \
        and parser.has_option('--hide_rejected_ciphers'):
            parser.add_option(
                '--regular',
                action="store_true",
                help=(
                    'Regular HTTP scan. Shortcut for --sslv2 --sslv3 --tlsv1 '
                    '--reneg --resum --certinfo=basic --http_get '
                    '--hide_rejected_ciphers'),
                dest=None)

    return (parser, available_commands)
Пример #48
0
 def tag(self, tag):
     if tag == OptionParser.has_option(tag):
         return lambda func: func
     return unittest.skip("Skip cases ha no tag:{0}".format(tag))
Пример #49
0
class CommandLineParser(object):

    # Defines what --regular means
    REGULAR_CMD = ['sslv2', 'sslv3', 'tlsv1', 'tlsv1_1', 'tlsv1_2', 'reneg', 'resum', 'certinfo_basic', 'http_get',
                   'hide_rejected_ciphers', 'compression', 'heartbleed', 'openssl_ccs', 'fallback']
    SSLYZE_USAGE = 'usage: %prog [options] target1.com target2.com:443 target3.com:443{ip} etc...'

    # StartTLS options
    START_TLS_PROTOCOLS = ['smtp', 'xmpp', 'xmpp_server', 'pop3', 'ftp', 'imap', 'ldap', 'rdp', 'postgres', 'auto']
    START_TLS_USAGE = 'STARTTLS should be one of: {}. The \'auto\' option will cause SSLyze to deduce the protocol ' \
                      '(ftp, imap, etc.) from the supplied port number, ' \
                      'for each target servers.'.format(' , '.join(START_TLS_PROTOCOLS))

    # Mapping of StartTls protocols and ports; useful for starttls=auto
    STARTTLS_PROTOCOL_DICT = {'smtp': TlsWrappedProtocolEnum.STARTTLS_SMTP,
                              587: TlsWrappedProtocolEnum.STARTTLS_SMTP,
                              25: TlsWrappedProtocolEnum.STARTTLS_SMTP,
                              'xmpp': TlsWrappedProtocolEnum.STARTTLS_XMPP,
                              5222 : TlsWrappedProtocolEnum.STARTTLS_XMPP,
                              'xmpp_server': TlsWrappedProtocolEnum.STARTTLS_XMPP_SERVER,
                              5269: TlsWrappedProtocolEnum.STARTTLS_XMPP_SERVER,
                              'pop3': TlsWrappedProtocolEnum.STARTTLS_POP3,
                              109: TlsWrappedProtocolEnum.STARTTLS_POP3,
                              110: TlsWrappedProtocolEnum.STARTTLS_POP3,
                              'imap': TlsWrappedProtocolEnum.STARTTLS_IMAP,
                              143: TlsWrappedProtocolEnum.STARTTLS_IMAP,
                              220: TlsWrappedProtocolEnum.STARTTLS_IMAP,
                              'ftp': TlsWrappedProtocolEnum.STARTTLS_FTP,
                              21: TlsWrappedProtocolEnum.STARTTLS_FTP,
                              'ldap': TlsWrappedProtocolEnum.STARTTLS_LDAP,
                              3268: TlsWrappedProtocolEnum.STARTTLS_LDAP,
                              389: TlsWrappedProtocolEnum.STARTTLS_LDAP,
                              'rdp': TlsWrappedProtocolEnum.STARTTLS_RDP,
                              3389: TlsWrappedProtocolEnum.STARTTLS_RDP,
                              'postgres': TlsWrappedProtocolEnum.STARTTLS_POSTGRES,
                              5432: TlsWrappedProtocolEnum.STARTTLS_POSTGRES}

    # Default values
    DEFAULT_RETRY_ATTEMPTS = 4
    DEFAULT_TIMEOUT = 5


    def __init__(self, available_plugins, sslyze_version):
        """Generates SSLyze's command line parser.
        """

        self._parser = OptionParser(version=sslyze_version, usage=self.SSLYZE_USAGE)

        # Add generic command line options to the parser
        self._add_default_options()

        # Add plugin-specific options to the parser
        self._add_plugin_options(available_plugins)

        # Add the --regular command line parameter as a shortcut if possible
        regular_help = 'Regular HTTPS scan; shortcut for --{}'.format(' --'.join(self.REGULAR_CMD))
        self._parser.add_option('--regular', action="store_true", dest=None, help=regular_help)


    def parse_command_line(self):
        """Parses the command line used to launch SSLyze.
        """

        (args_command_list, args_target_list) = self._parser.parse_args()

        # Handle the --targets_in command line and fill args_target_list
        if args_command_list.targets_in:
            if args_target_list:
                raise CommandLineParsingError("Cannot use --targets_list and specify targets within the command line.")

            try:  # Read targets from a file
                with open(args_command_list.targets_in) as f:
                    for target in f.readlines():
                        if target.strip():  # Ignore empty lines
                            if not target.startswith('#'):  # Ignore comment lines
                                args_target_list.append(target.strip())
            except IOError:
                raise CommandLineParsingError("Can't read targets from input file '{}.".format(
                        args_command_list.targets_in))

        if not args_target_list:
            raise CommandLineParsingError('No targets to scan.')


        # Handle the --regular command line parameter as a shortcut
        if self._parser.has_option('--regular'):
            if getattr(args_command_list, 'regular'):
                setattr(args_command_list, 'regular', False)
                for cmd in self.REGULAR_CMD:
                    setattr(args_command_list, cmd, True)


        # Sanity checks on the command line options
        # Prevent --quiet and --xml_out -
        if args_command_list.xml_file and args_command_list.xml_file == '-' and args_command_list.quiet:
                raise CommandLineParsingError('Cannot use --quiet with --xml_out -.')

        # Prevent --quiet and --json_out -
        if args_command_list.json_file and args_command_list.json_file == '-' and args_command_list.quiet:
                raise CommandLineParsingError('Cannot use --quiet with --json_out -.')

        # Prevent --xml_out - and --json_out -
        if args_command_list.json_file and args_command_list.json_file == '-'\
                and args_command_list.xml_file and args_command_list.xml_file == '-'.quiet:
                raise CommandLineParsingError('Cannot use --xml_out - with --json_out -.')


        # Sanity checks on the client cert options
        client_auth_creds = None
        if bool(args_command_list.cert) ^ bool(args_command_list.key):
            raise CommandLineParsingError('No private key or certificate file were given. See --cert and --key.')

        elif args_command_list.cert:
            # Private key formats
            if args_command_list.keyform == 'DER':
                key_type = SSL_FILETYPE_ASN1
            elif args_command_list.keyform == 'PEM':
                key_type = SSL_FILETYPE_PEM
            else:
                raise CommandLineParsingError('--keyform should be DER or PEM.')

            # Let's try to open the cert and key files
            try:
                client_auth_creds = ClientAuthenticationCredentials(args_command_list.cert,
                                                                    args_command_list.key,
                                                                    key_type,
                                                                    args_command_list.keypass)
            except ValueError as e:
                raise CommandLineParsingError('Invalid client authentication settings: {}.'.format(e[0]))


        # HTTP CONNECT proxy
        http_tunneling_settings = None
        if args_command_list.https_tunnel:
            try:
                http_tunneling_settings = HttpConnectTunnelingSettings.from_url(args_command_list.https_tunnel)
            except ValueError as e:
                raise CommandLineParsingError('Invalid proxy URL for --https_tunnel: {}.'.format(e[0]))


        # STARTTLS
        tls_wrapped_protocol = TlsWrappedProtocolEnum.PLAIN_TLS
        if args_command_list.starttls:
            if args_command_list.starttls not in self.START_TLS_PROTOCOLS:
                raise CommandLineParsingError(self.START_TLS_USAGE)
            else:
                # StartTLS was specified
                if args_command_list.starttls in self.STARTTLS_PROTOCOL_DICT.keys():
                    # Protocol was given in the command line
                    tls_wrapped_protocol = self.STARTTLS_PROTOCOL_DICT[args_command_list.starttls]


        # Number of connection retries
        if args_command_list.nb_retries < 1:
            raise CommandLineParsingError('Cannot have a number smaller than 1 for --nb_retries.')


        # Create the server connectivity info for each specifed servers
        # A limitation when using the command line is that only one client_auth_credentials and http_tunneling_settings
        # can be specified, for all the servers to scan
        good_server_list = []
        bad_server_list = []
        for server_string in args_target_list:
            try:
                good_server_list.append(ServerConnectivityInfo.from_command_line(
                    server_string=server_string,
                    tls_wrapped_protocol=tls_wrapped_protocol,
                    tls_server_name_indication=args_command_list.sni,
                    xmpp_to_hostname=args_command_list.xmpp_to,
                    client_auth_credentials=client_auth_creds,
                    http_tunneling_settings=http_tunneling_settings)
                )
            except ServerConnectivityError as e:
                # Will happen for example if the DNS lookup failed or the server string is malformed
                bad_server_list.append((server_string, e))
            except ValueError as e:
                # Will happen for example if xmpp_to is specified for a non-XMPP connection
                raise CommandLineParsingError(e[0])


        # Command line hacks
        # Handle --starttls=auto now that we parsed the server strings
        if args_command_list.starttls == 'auto':
            for server_info in good_server_list:
                # We use the port number to deduce the protocol
                if server_info.port in self.STARTTLS_PROTOCOL_DICT.keys():
                    server_info.tls_wrapped_protocol = self.STARTTLS_PROTOCOL_DICT[server_info.port]

        # Handle --http_get now that we parsed the server strings
        # Doing it here is hacky as the option is defined within PluginOpenSSLCipherSuites
        if args_command_list.http_get:
            for server_info in good_server_list:
                if server_info.port == 443:
                    server_info.tls_wrapped_protocol = TlsWrappedProtocolEnum.HTTPS

        return good_server_list, bad_server_list, args_command_list



    def _add_default_options(self):
        """
        Adds default command line options to the parser.
        """

        # Client certificate options
        clientcert_group = OptionGroup(self._parser,
            'Client certificate support', '')
        clientcert_group.add_option(
            '--cert',
            help='Client certificate chain filename. The certificates must be in PEM format and must be sorted '
                 'starting with the subject\'s client certificate, followed by intermediate CA certificates if '
                 'applicable.',
            dest='cert'
        )
        clientcert_group.add_option(
            '--key',
            help= 'Client private key filename.',
            dest='key'
        )
        clientcert_group.add_option(
            '--keyform',
            help= 'Client private key format. DER or PEM (default).',
            dest='keyform',
            default='PEM'
        )
        clientcert_group.add_option(
            '--pass',
            help= 'Client private key passphrase.',
            dest='keypass',
            default=''
        )
        self._parser.add_option_group(clientcert_group)

        # XML output
        self._parser.add_option(
            '--xml_out',
            help='Writes the scan results as an XML document to the file XML_FILE. If XML_FILE is set to "-", the XML '
                 'output will instead be printed to stdout.',
            dest='xml_file',
            default=None
        )
        # JSON output
        self._parser.add_option(
            '--json_out',
            help='Writes the scan results as a JSON document to the file JSON_FILE. If JSON_FILE is set to "-", the '
                 'JSON output will instead be printed to stdout.',
            dest='json_file',
            default=None
        )
        # Read targets from input file
        self._parser.add_option(
            '--targets_in',
            help='Reads the list of targets to scan from the file TARGETS_IN. It should contain one host:port per '
                 'line.',
            dest='targets_in',
            default=None
        )
        # Timeout
        self._parser.add_option(
            '--timeout',
            help='Sets the timeout value in seconds used for every socket connection made to the target server(s). '
                 'Default is {}s.'.format(str(self.DEFAULT_TIMEOUT)),
            type='int',
            dest='timeout',
            default=self.DEFAULT_TIMEOUT
        )
        # Control connection retry attempts
        self._parser.add_option(
            '--nb_retries',
            help='Sets the number retry attempts for all network connections initiated throughout the scan. Increase '
                 'this value if you are getting a lot of timeout/connection errors when scanning a specific server. '
                 'Decrease this value to increase the speed of the scans; results may however return connection errors.'
                 ' Default is {} connection attempts.'.format(str(self.DEFAULT_RETRY_ATTEMPTS)),
            type='int',
            dest='nb_retries',
            default=self.DEFAULT_RETRY_ATTEMPTS
        )
        # HTTP CONNECT Proxy
        self._parser.add_option(
            '--https_tunnel',
            help='Tunnels all traffic to the target server(s) through an HTTP CONNECT proxy. HTTP_TUNNEL should be the '
                 'proxy\'s URL: \'http://*****:*****@HOST:PORT/\'. For proxies requiring authentication, only Basic '
                 'Authentication is supported.',
            dest='https_tunnel',
            default=None
        )
        # STARTTLS
        self._parser.add_option(
            '--starttls',
            help='Performs StartTLS handshakes when connecting to the target server(s). ' + self.START_TLS_USAGE,
            dest='starttls',
            default=None
        )
        self._parser.add_option(
            '--xmpp_to',
            help='Optional setting for STARTTLS XMPP. XMPP_TO should be the hostname to be put in the \'to\' attribute '
                 'of the XMPP stream. Default is the server\'s hostname.',
            dest='xmpp_to',
            default=None
        )
        # Server Name Indication
        self._parser.add_option(
            '--sni',
            help='Use Server Name Indication to specify the hostname to connect to.  Will only affect TLS 1.0+ '
                 'connections.',
            dest='sni',
            default=None
        )
        # No text output
        self._parser.add_option(
            '--quiet',
            action="store_true",
            dest='quiet',
            help='Do not output anything to stdout; useful when using --xml_out or --json_out.'
        )


    def _add_plugin_options(self, available_plugins):
        """Recovers the list of command line options implemented by the available plugins and adds them to the command
        line parser.
        """
        for plugin_class in available_plugins:
            plugin_desc = plugin_class.get_interface()

            # Add the current plugin's commands to the parser
            group = OptionGroup(self._parser, plugin_desc.title, plugin_desc.description)
            for cmd in plugin_desc.get_commands():
                    group.add_option(cmd)

            # Add the current plugin's options to the parser
            for option in plugin_desc.get_options():
                    group.add_option(option)

            self._parser.add_option_group(group)
Пример #50
0
class CommandBase(object):
    def __init__(self):
        self.parser = OptionParser()

        cfg = config.ClientConfig()
        self.cfg = cfg

        self.parser.add_option("-v",
                               "--verbose",
                               dest="verbose",
                               action="store_true",
                               help="show debug infomation.",
                               default=cfg.verbose)

        self.parser.add_option("-H",
                               "--host",
                               help="server host, default is %s" %
                               cfg.server_host,
                               default=cfg.server_host,
                               metavar="HOST")

        self.parser.add_option("-p",
                               "--port",
                               help="server port, default is %d" %
                               cfg.server_port,
                               default=cfg.server_port,
                               type="int",
                               metavar="PORT")

        self.parser.add_option("-U",
                               "--username",
                               help="login user name",
                               type="str",
                               metavar="USERNAME")

        self.parser.add_option("-P",
                               "--password",
                               help="login password",
                               type="str",
                               metavar="PASSWORD")

        _parser = self.getOptionParser()
        self.parser.usage = _parser.usage.rstrip()
        for option in _parser.option_list:
            if not self.parser.has_option(option.get_opt_string()):
                self.parser.add_option(option)

    def login(self, options):
        user_name, password = self._getLoginInfo(options)
        client = YumtoolsClient()
        if client.connect(options.host, options.port):
            io.debug(
                "upload", "yum server %s:%d connected." %
                (self.cfg.server_host, self.cfg.server_port))
        else:
            io.error(
                "upload", "server %s:%d connect error." %
                (self.cfg.server_host, self.cfg.server_port))
            return False, None
        if not client.login(user_name, password):
            io.error('upload', 'auth failed')
            return False, None
        else:
            return True, client

    def execute(self, args):
        options, args = self.parser.parse_args(args)
        if options.verbose:
            io.use_debug = True
        return self.run(options, args)

    def getOptionParser(self):
        raise NotImplementedError

    def run(self, options, args):
        raise NotImplementedError

    def showHelp(self):
        self.parser.print_help()

    def _getLoginInfo(self, options):
        user_name = options.username
        password = options.password
        if not user_name:
            user_name = io.get("username: "******"password: ")
        return user_name, password
Пример #51
0
def main(startstring):
    if not gottrac:
        rlog(100, 'tracserver', 'trac is not installed')
        return
    global httpd
    from optparse import OptionParser, OptionValueError
    parser = OptionParser(usage='usage: %prog [options] [projenv] ...',
                          version='%%prog %s' % VERSION)
    auths = {}
    def _auth_callback(option, opt_str, value, parser, cls):
        info = value.split(',', 3)
        if len(info) != 3:
            raise OptionValueError("Incorrect number of parameters for %s"
                                   % option)

        env_name, filename, realm = info
        auths[env_name] = cls(os.path.abspath(filename), realm)

    def _validate_callback(option, opt_str, value, parser, valid_values):
        if value not in valid_values:
            raise OptionValueError('%s must be one of: %s, not %s'
                                   % (opt_str, '|'.join(valid_values), value))
        setattr(parser.values, option.dest, value)

    parser.add_option('-a', '--auth', action='callback', type='string',
                      metavar='DIGESTAUTH', callback=_auth_callback,
                      callback_args=(DigestAuthentication,),
                      help='[projectdir],[htdigest_file],[realm]')
    parser.add_option('--basic-auth', action='callback', type='string',
                      metavar='BASICAUTH', callback=_auth_callback,
                      callback_args=(BasicAuthentication,),
                      help='[projectdir],[htpasswd_file],[realm]')

    parser.add_option('-p', '--port', action='store', type='int', dest='port',
                      help='the port number to bind to')
    parser.add_option('-b', '--hostname', action='store', dest='hostname',
                      help='the host name or IP address to bind to')
    parser.add_option('--protocol', action='callback', type="string",
                      dest='protocol', callback=_validate_callback,
                      callback_args=(('http', 'scgi', 'ajp', 'fcgi'),),
                      help='http|scgi|ajp|fcgi')
    parser.add_option('-e', '--env-parent-dir', action='store',
                      dest='env_parent_dir', metavar='PARENTDIR',
                      help='parent directory of the project environments')
    parser.add_option('--base-path', action='store', type='string', # XXX call this url_base_path?
                      dest='base_path',
                      help='the initial portion of the request URL\'s "path"')

    parser.add_option('-r', '--auto-reload', action='store_true',
                      dest='autoreload',
                      help='restart automatically when sources are modified')

    parser.add_option('-s', '--single-env', action='store_true',
                      dest='single_env', help='only serve a single '
                      'project without the project list', default=False)

    if os.name == 'posix':
        parser.add_option('-d', '--daemonize', action='store_true',
                          dest='daemonize',
                          help='run in the background as a daemon')
        parser.add_option('--pidfile', action='store',
                          dest='pidfile',
                          help='When daemonizing, file to which to write pid')
        parser.add_option('--umask', action='store', type='int', dest='umask',
                          metavar='MASK',
                          help='When daemonizing, file mode creation mask '
                          'to use (default 022)')

    parser.set_defaults(port=None, hostname='', base_path='', daemonize=False,
                        protocol='http', umask=022)
    options, args = parser.parse_args(startstring.split())
    if not args and not options.env_parent_dir:
        parser.error('either the --env-parent-dir option or at least one '
                     'environment must be specified')
    if options.single_env:
        if options.env_parent_dir:
            parser.error('the --single-env option cannot be used with '
                         '--env-parent-dir')
        elif len(args) > 1:
            parser.error('the --single-env option cannot be used with '
                         'more than one enviroment')
    if options.daemonize and options.autoreload:
        parser.error('the --auto-reload option cannot be used with '
                     '--daemonize')

    if options.port is None:
        options.port = {
            'http': 80,
            'scgi': 4000,
            'ajp': 8009,
            'fcgi': 8000,
        }[options.protocol]
    server_address = (options.hostname, options.port)

    # relative paths don't work when daemonized
    args = [os.path.abspath(a) for a in args]
    if options.env_parent_dir:
        options.env_parent_dir = os.path.abspath(options.env_parent_dir)
    if parser.has_option('pidfile') and options.pidfile:
        options.pidfile = os.path.abspath(options.pidfile)

    wsgi_app = TracEnvironMiddleware(dispatch_request,
                                     options.env_parent_dir, args,
                                     options.single_env)
    if auths:
        if options.single_env:
            project_name = os.path.basename(args[0])
            wsgi_app = AuthenticationMiddleware(wsgi_app, auths, project_name)
        else:
            wsgi_app = AuthenticationMiddleware(wsgi_app, auths)
    base_path = options.base_path.strip('/')
    if base_path:
        wsgi_app = BasePathMiddleware(wsgi_app, base_path)

    try:
        httpd = TracHTTPServer(server_address, wsgi_app,
                                   options.env_parent_dir, args)
    except socket.error, ex:
        if 'already in use' in str(ex):
            rlog(10, 'tserver', 'server is already running')
            return
Пример #52
0
class CommandLineParser():
    
    # Defines what --regular means
    REGULAR_CMD = ['sslv3', 'tlsv1', 'reneg', 'resum', 'certinfo', 
                      'http_get', 'hide_rejected_ciphers', 'compression', 
                      'tlsv1_1', 'tlsv1_2']
    SSLYZE_USAGE = 'usage: %prog [options] target1.com target2.com:443 etc...'
    
    
    def __init__(self, available_plugins, sslyze_version, timeout):
        """
        Generates SSLyze's command line parser.
        """

        self._parser = OptionParser(version=sslyze_version,
                                    usage=self.SSLYZE_USAGE)
    
        # Add generic command line options to the parser
        self._add_default_options(timeout)
    
        # Add plugin-specific options to the parser
        self._add_plugin_options(available_plugins)
    
        # Add the --regular command line parameter as a shortcut if possible
        regular_help = 'Regular HTTPS scan; shortcut for'
        for cmd in self.REGULAR_CMD:
            regular_help += ' --' + cmd
            if (self._parser.has_option('--' + cmd) == False):
                return
        
        self._parser.add_option('--regular', action="store_true", dest=None,
                    help=regular_help)
                
        
    def parse_command_line(self):
        """
        Parses the command line used to launch SSLyze.
        """
    
        (args_command_list, args_target_list) = self._parser.parse_args()
    
        # Handle the --targets_in command line and fill args_target_list
        if args_command_list.targets_in:
            if args_target_list:
                raise CommandLineParsingError("Cannot use --targets_list and specify targets within the command line.")
                
            try: # Read targets from a file
                with open(args_command_list.targets_in) as f:
                    for target in f.readlines():
                        if target.strip(): # Ignore empty lines
                            if not target.startswith('#'): # Ignore comment lines
                                args_target_list.append(target.strip())
            except IOError, e:
                raise CommandLineParsingError("Can't read targets from input file '%s'." %  args_command_list.targets_in)
    
        if args_target_list == []:
            raise CommandLineParsingError('No targets to scan.')
    
        # Handle the --regular command line parameter as a shortcut
        if self._parser.has_option('--regular'):
            if getattr(args_command_list, 'regular'):
                setattr(args_command_list, 'regular', False)
                for cmd in self.REGULAR_CMD:
                    setattr(args_command_list, cmd, True)
                setattr(args_command_list, 'certinfo', 'basic') # Special case
                
        # Create the shared_settings object from looking at the command line
        shared_settings = self._process_parsing_results(args_command_list)
        
        return (args_command_list, args_target_list, shared_settings)
Пример #53
0
class CommandBase(object):

    def __init__(self):
        self.parser = OptionParser()

        cfg = config.ClientConfig()
        self.cfg = cfg

        self.parser.add_option("-v", "--verbose", dest="verbose",
                action="store_true",
                help="show debug infomation.",
                default=cfg.verbose)

        self.parser.add_option("-H", "--host",
                help="server host, default is %s" % cfg.server_host,
                default=cfg.server_host,
                metavar="HOST")

        self.parser.add_option("-p", "--port",
                help="server port, default is %d" % cfg.server_port,
                default=cfg.server_port,
                type="int",
                metavar="PORT")

        self.parser.add_option("-U", "--username",
                help="login user name",
                type="str",
                metavar="USERNAME")

        self.parser.add_option("-P", "--password",
                help="login password",
                type="str",
                metavar="PASSWORD")

        _parser = self.getOptionParser()
        self.parser.usage = _parser.usage.rstrip()
        for option in _parser.option_list:
            if not self.parser.has_option(option.get_opt_string()):
                self.parser.add_option(option)

    def login(self, options):
        user_name, password = self._getLoginInfo(options)
        client = YumtoolsClient()
        if client.connect(options.host, options.port):
            io.debug("upload", "yum server %s:%d connected." % (self.cfg.server_host, self.cfg.server_port))
        else:
            io.error("upload", "server %s:%d connect error." % (self.cfg.server_host, self.cfg.server_port))
            return False, None
        if not client.login(user_name, password):
            io.error('upload', 'auth failed')
            return False, None
        else:
            return True, client

    def execute(self, args):
        options, args = self.parser.parse_args(args)
        if options.verbose:
            io.use_debug = True
        return self.run(options, args)

    def getOptionParser(self):
        raise NotImplementedError

    def run(self, options, args):
        raise NotImplementedError

    def showHelp(self):
        self.parser.print_help()

    def _getLoginInfo(self, options):
        user_name   = options.username
        password    = options.password
        if not user_name:
            user_name = io.get("username: "******"password: ")
        return user_name, password
Пример #54
0
def main():
    # All instances we currently have.
    # Keys are the full name of the instance,
    # values are the shorthand "slug" used in usernames.
    all_instances = {'uio': 'uio',
                     'uia': 'uia',
                     'ofk': 'ofk',
                     'hiof': 'hiof',
                     'nmh': 'nmh',
                     'hih': 'hih',
                     'nih': 'nih',
                     'giske': 'gisk',
                     'hine': 'hine',
                     'webid': 'wid'}

    usage = "usage: %prog [options] instances"
    parser = OptionParser(usage)
    parser.add_option("-a", "--all-instances", dest="instances",
                      action="store_const", const=all_instances,
                      help="Shorthand for deploying on all instances")
    parser.add_option("--no-setup", action="store_false", dest="setup",
                      default=True, help="Do not run setup.py")
    parser.add_option("-b", "--restart-bofhd", action="store_true",
                      help="Restart bofhd")
    parser.add_option("-j", "--restart-job_runner", action="store_true",
                      help="Restart job_runner. Note: Runs --quit directly, "
                      "does not wait for jobs to finish.")
    parser.add_option("-s", "--reload-scheduled_jobs", action="store_true",
                      help="Make job_runner reload new scheduled_jobs.")
    parser.add_option("-n", "--restart-individuation", action="store_true",
                      help="Restart Individuation")
    parser.add_option("-r", "--restart-all", action="store_true",
                      help="Restart bofhd, job_runner and Individuation")
    parser.add_option(
        "--only-insert-codes", dest="makedb", action="store_const",
        const="--only-insert-codes", help="makedb.py: Make sure all "
        "code values for the current configuration of "
        "cereconf.CLASS_CONSTANTS have been inserted into the "
        "database. Does not create tables. This is the default.")
    parser.add_option("--update-codes", dest="makedb", action="store_const",
                      const="--update-codes", default="--only-insert-codes",
                      help="makedb.py: Like --only-insert-codes, but will remove"
                      " constants that exists in the database, but not in "
                      "CLASS_CONSTANTS (subject to FK constraints).")

    options, args = parser.parse_args()

    if (len(args) > 0 and parser.has_option('instances')):
        parser.error("Are you sure you meant to deploy on all instances when "
                     "you also specified instances?")

    if len(args) > 0:
        options.instances = dict((i, all_instances[i]) for i in args)

    if options.instances == None:
        parser.error("Must specify instances, either with --instances or "
                     "--all-instances")

    if (options.restart_all and (options.restart_bofhd or
                                 options.restart_job_runner or
                                 options.restart_individuation)):
        parser.error("Are you sure you meant --restart-all when you also "
                     "to restart a specific service?")

    if options.restart_all:
        options.restart_job_runner =\
            options.restart_bofhd =\
            options.restart_individuation = True

    if (options.reload_scheduled_jobs and options.restart_job_runner):
        parser.error("Are you sure you meant to restart job_runner when you "
                     "also wanted to reload its scheduled_jobs?")

    # Production MAXIMUM
    for instance in options.instances.keys():
        user = "******" % options.instances[instance]

        # git pull
        print("%s: Pulling…") % instance
        os.system("ssh cerebrum-%s \"su - %s -c 'cd /cerebrum/%s/%s/src/cerebrum; "
                  "git pull'\"" % (instance, user, instance, user))

        # setup.py
        if options.setup:
            print("%s: Setting up…") % instance
            os.system("ssh cerebrum-%s \"su - %s -c "
                      "'python /cerebrum/%s/%s/src/cerebrum/setup.py install "
                      "--prefix=/cerebrum/%s/ |egrep -v \"skipping|not\"'\"" % (
                          (instance, user, instance, user, instance)))

        # makedb.py, --only-insert-codes is default
        print("%s: Making database…") % instance
        os.system("ssh cerebrum-%s \"su - %s -c 'python "
                  "/cerebrum/%s/%s/src/cerebrum/makedb.py --debug %s'\"" % (
                      (instance, user, instance, user, options.makedb)))

        # Restart services
        job_runner = "/cerebrum/%s/sbin/job_runner.py" % instance

        if options.restart_job_runner:
            print("%s: Restarting job_runner…") % instance
            os.system("ssh cerebrum-%s \"su - %s -c '%s --quit'\"" % (
                      (instance, user, job_runner)))

        if options.reload_scheduled_jobs:
            print("%s: Reloading scheduled_jobs…") % instance
            os.system("ssh cerebrum-%s \"su - %s -c '%s --reload'\"" % (
                      (instance, user, job_runner)))

        if options.restart_bofhd:
            bofhd_pid = "ps aux | grep /cerebrum/%s/sbin/bofhd.py | grep -v "\
                        "keep-running | grep -v grep | tr -s \" \" | cut -f 2 -d \" \""\
                        % instance
            print("%s: Killing bofhd…") % instance
            os.system("ssh cerebrum-%s \"su - %s -c 'kill `%s`'\"" % (
                      (instance, user, bofhd_pid)))