示例#1
0
文件: qapi.py 项目: nima/insecurity
class QualysGuard:
    def __init__(self, username, realm_id, config, debug=False):
        self._version = QAPI_VERSION
        self._cookiejar = CookieJar()
        self._username = username
        self._realm_id = realm_id
        self._profile = '@'.join((username, realm_id))
        self._realm = REALMS[self._realm_id]
        self._proxy = None
        self._templates = None
        self._debug = debug
        self._config = None #. User configuration file for scripted mode
        self._connected = False
        self._username = '******'
        self._cFM = None
        try:
            from ConfigFileManager import ConfigFileManager, InternalConfigError
            try:
                self._config = ConfigFileManager(config)
                self._qapi_ini = self._config.option('qapi', 'ini')
                self._cFM = ConfigFileManager(self._qapi_ini)
            except InternalConfigError as e:
                raise Exception("Sorry, %s" % e)
        except ImportError as e:
            raise Exception("Sorry, %s" % e)

        urllib2.install_opener(self._opener())

    def __del__(self):
        self.logout()

    def __repr__(self):
        return "<QualysGuard conn:%s user:%s>" % (
            self._connected,
            self._username
        )

    def _opener(self):
        ntlm = False
        proxy = False
        if 'proxy' in self._config.sections():
            try:
                self._proxy = {
                    'proto'   : self._config.option('proxy', 'proto'),
                    'host'    : self._config.option('proxy', 'host'),
                    'port'    : int(self._config.option('proxy', 'port', 8080)),
                    'user'    : self._config.option('proxy', 'user', None),
                    'pass'    : self._config.option('proxy', 'pass', None),
                }
                if self._proxy['user'] is not None:
                    ntlm = self._proxy['user'].count('\\') == 1

                if self._proxy['host'] and self._proxy['port']:
                    proxy = True

            except InternalConfigError as e:
                pass

        proxy_handler_dict = {}
        if proxy:
            proxy_handler_uri = None
            if self._proxy['user']:
                if self._proxy['pass'] is not None:
                    proxy_handler_uri = "%s://%s:%s@%s:%d" % (
                        "http",
                        self._proxy['user'],
                        self._proxy['pass'],
                        self._proxy['host'],
                        self._proxy['port']
                    )
                else:
                    proxy_handler_uri = "%s://%s@%s:%d" % (
                        "http",
                        self._proxy['user'],
                        self._proxy['host'],
                        self._proxy['port']
                    )
            else:
                proxy_handler_uri = "%s://%s:%d" % (
                    "http",
                    self._proxy['host'],
                    self._proxy['port']
                )

            proxy_handler_dict[self._proxy['proto']] = proxy_handler_uri

        self._pwmgr = urllib2.HTTPPasswordMgrWithDefaultRealm()
        cookiemonster = urllib2.HTTPCookieProcessor(self._cookiejar)
        auth_NTLM   = HTTPNtlmAuthHandler.HTTPNtlmAuthHandler(self._pwmgr)
        auth_basic  = urllib2.HTTPBasicAuthHandler(self._pwmgr)
        auth_digest = urllib2.HTTPDigestAuthHandler(self._pwmgr)
        auth_proxy  = urllib2.ProxyHandler(proxy_handler_dict)

        openers = [
            auth_basic,
            auth_digest,
            auth_proxy,
            cookiemonster,
        ]
        if ntlm:
            openers.append(auth_NTLM)

        opener = urllib2.build_opener(*openers)
        return opener

    def _cookies(self):
        return self._cookiejar._cookies[self._realm]['/api']['QualysSession']

    def _validate(self, resource, **parameters):
        valid = False
        action = parameters.get('action', None)
        if action is not None:
            valid = resource in self._cFM.option('resource', 'valid')
        else:
            raise NameError(
                "Missing mandarory option `action'"
            )

        msg = None
        if valid:
            for param in self._cFM.section('%s-options' % resource):
                meaning = self._cFM.option(
                    '%s-options' % resource,
                    param
                )
                if meaning.has_key(action):
                    if meaning[action] is 1 and param not in parameters.keys():
                        raise NameError(
                            "Missing mandarory option `%s' for `%s'" % (
                                param, resource
                            )
                        )
                else:
                    pass

            validators = self._cFM.section('%s-validators' % resource)
            for param in parameters:
                if param in self._cFM.options('%s-options' % resource):
                    validator = validators.get(param, None)
                    if validator is not None:
                        if type(validator) is list:
                            valid = parameters[param] in validator
                            msg = "`%s=%s' (required) not in %s" % (
                                param,
                                parameters[param],
                                validator
                            )
                        else:
                            validator_fn = eval(validator)
                            valid = validator_fn(parameters[param])
                            msg = "`%s=%s' failed on %s" % (
                                param,
                                validator,
                                parameters[param]
                            )

                        if not valid:
                            raise QAPILocalValidationError(
                                "`%s:%s=%s': %s",
                                resource, param, parameters[param], msg
                            )
                else:
                    raise NameError(
                        "Invalid option `%s' for `%s'" % (
                            param, resource
                        )
                    )
        else:
            raise NameError(
                "Invalid resource `%s'" % resource
            )

        return valid

    def _request(self, resource, application, data=dict()):
        '''
        application:
            api: QualysGuard API v1
            msp: QualysGuard API v2
        '''
        if application == 'api':
            assert self._validate(resource, **data) is True
        elif application != 'msp':
            raise QAPIInteralError(
                "%s not in `api' or `msp'", application,
            )

        uri = None
        if application == 'api':
            uri = 'https://%s:443/%s/%0.1f/%s/%s/' % (
                self._realm,
                application, URI_DATA['version'], 'fo',
                resource
            )
        elif application == 'msp':
            uri = 'https://%s:443/%s/%s.php' % (
                self._realm,
                application,
                resource
            )

        if self._debug:
            print "\n#. %-8s: %s (%s)" % ('URI', uri, application)
            if application is 'api':
                print "#. %-8s: %s" % ('POST', urllib.urlencode(data))

        encdata = urllib.urlencode(data)
        headers = { 'X-Requested-With' : 'qapi-v%s' % QAPI_VERSION }
        response = None
        error = None
        try:
            request = urllib2.Request(uri, encdata, headers)
            if self._debug:
                print "#. REQUEST HEADERS"
                print request.headers
                print "#. REQUEST DATA"
                print request.data

            response = urllib2.urlopen(request)
            if self._debug:
                print "#. RESPONSE HEADERS"
                print response.msg
                print response.headers
                #print "#. RESPONSE DATA"
                #print '\n'.join(response.readlines())
                #print dir(response.fp)
                #print dir(response)

        except urllib2.HTTPError, e:
            if not self._debug: raise e #. TODO: Cleanup - Not XML, so can't use QAPIHTTPError(e)
            else: error = e
        except urllib2.URLError, e:
            #if not self._debug: raise QAPISessionTimeoutError(e)
            #else:
            error = e
            if hasattr(e, 'reason'):
                print 'We failed to reach a server.'
                print 'Reason: ', e.reason
            elif hasattr(e, 'code'):
                print 'The server couldn\'t fulfill the request.'
                print 'Error code: ', e.code