Пример #1
0
class NetWorker(QObject):
    ifcAddrChanged = pyqtSignal(str, name='ifcAddrChanged', arguments=['ip'])
    currentIfcAddrChanged = pyqtSignal()
    wifiStatus = pyqtSignal(str,
                            str,
                            int,
                            int,
                            name='wifiStatus',
                            arguments=['essid', 'freq', 'quality', 'level'])
    wifiStatusChanged = pyqtSignal()

    @pyqtProperty(str, notify=currentIfcAddrChanged)
    def currentIfcAddr(self):
        return self.ifcAddr.toString()

    @pyqtProperty(str, notify=wifiStatusChanged)
    def currentWifiESSID(self):
        return self.essid

    @pyqtProperty(str, notify=wifiStatusChanged)
    def currentWifiFreq(self):
        return self.freq

    @pyqtProperty(int, notify=wifiStatusChanged)
    def currentWifiQuality(self):
        return self.quality

    @pyqtProperty(int, notify=wifiStatusChanged)
    def currentWifiLevel(self):
        return self.level

    def __init__(self, loglevel='WARNING', ifcName='wlan0'):
        QObject.__init__(self)

        self.logger = Logger(name='ratt.networker')
        self.logger.setLogLevelStr(loglevel)
        self.debug = self.logger.isDebug()

        self.mgr = QNetworkAccessManager()
        self.sslConfig = QSslConfiguration()
        self.sslSupported = QSslSocket.supportsSsl()

        self.setAuth()
        self.setSSLCertConfig()

        self.mgr.authenticationRequired.connect(
            self.handleAuthenticationRequired)

        self.ifcName = ifcName
        self.ifcAddr = QHostAddress()

        self.statusTimer = QTimer()
        self.statusTimer.setSingleShot(False)
        self.statusTimer.timeout.connect(self.slotStatusTimer)
        self.statusTimer.start(5000)

        self.essid = ''
        self.freq = ''
        self.quality = 0
        self.level = 0

    def slotStatusTimer(self):
        ip = self.getIfcAddress(ifc=self.ifcName)

        if ip != self.ifcAddr:
            self.ifcAddr = ip
            self.ifcAddrChanged.emit(ip.toString())
            self.currentIfcAddrChanged.emit()

        results = {}
        if self.getWifiStatus(results):
            self.essid = results['essid']
            self.freq = results['freq']
            self.quality = results['quality']
            self.level = results['level']
            self.wifiStatus.emit(self.essid, self.freq, self.quality,
                                 self.level)
            self.wifiStatusChanged.emit()

    # ['wlan0', 'IEEE', '802.11', 'ESSID:"FooBar"', 'Mode:Managed', 'Frequency:2.412',
    # 'GHz', 'Access', 'Point:', '00:11:22:33:44:55', 'Bit', 'Rate=65', 'Mb/s', 'Tx-Power=31',
    # 'dBm', 'Retry', 'short', 'limit:7', 'RTS', 'thr:off', 'Fragment', 'thr:off', 'Power',
    # 'Management:on', 'Link', 'Quality=43/70', 'Signal', 'level=-67', 'dBm', 'Rx', 'invalid',
    # 'nwid:0', 'Rx', 'invalid', 'crypt:0', 'Rx', 'invalid', 'frag:0', 'Tx', 'excessive', 'retries:113',
    # 'Invalid', 'misc:0', 'Missed', 'beacon:0']
    def getWifiStatus(self, res):
        try:
            iw = getoutput('/sbin/iwconfig %s' % self.ifcName)

            fields = iw.split()

            for field in fields:
                if field.find('ESSID') != -1:
                    res['essid'] = field.split('"')[1]
                elif field.find('Frequency') != -1:
                    res['freq'] = field.split(':')[1]
                elif field.find('Quality') != -1:
                    frac = field.split('=')[1]
                    (n, d) = frac.split('/')
                    q = int(n) * 100 / int(d)
                    res['quality'] = q
                elif field.find('level') != -1:
                    res['level'] = int(field.split('=')[1])
        except:
            return False

        return True

    def getIfcAddress(self, ifc):
        myIfc = QNetworkInterface.interfaceFromName(ifc)
        addrList = myIfc.addressEntries()

        for addr in addrList:
            if addr.ip().protocol() == QAbstractSocket.IPv4Protocol:
                return addr.ip()

        return QHostAddress()

    def setAuth(self, user='', password=''):
        self.user = user
        self.password = password

    def setSSLCertConfig(self,
                         enabled=False,
                         caCertFile='',
                         clientCertFile='',
                         clientKeyFile=''):
        self.sslEnabled = enabled

        if self.sslSupported and self.sslEnabled:
            self.caCertFile = caCertFile
            self.clientCertFile = clientCertFile
            self.clientKeyFile = clientKeyFile

            self.configureCerts()

    def get(self, url):
        self.logger.debug('get url=%s' % url.toString())

        request = QNetworkRequest(QUrl(url))
        request.setRawHeader("User-Agent", "RATT")

        if self.sslSupported and self.sslEnabled:
            request.setSslConfiguration(self.sslConfig)

        reply = self.mgr.get(request)

        if self.sslSupported and self.sslEnabled:
            reply.sslErrors.connect(self.handleSSLErrors)

        return reply

    def buildRequest(self, url):
        request = QNetworkRequest(QUrl(url))
        request.setHeader(QNetworkRequest.ContentTypeHeader,
                          "application/x-www-form-urlencoded")

        return request

    def buildQuery(self, vars):
        query = str()
        for key in vars:
            value = vars[key]
            sep = '&' if query != '' else ''
            query = query + '%s%s=%s' % (sep, key, value)

        return query

    def post(self, request, query):
        self.logger.debug('post url=%s query=%s' %
                          (request.url().toString(), query))

        if self.sslSupported and self.sslEnabled:
            request.setSslConfiguration(self.sslConfig)

        bytearray = QByteArray()
        bytearray.append(query)

        reply = self.mgr.post(request, bytearray)

        if self.sslSupported and self.sslEnabled:
            self.mgr.sslErrors.connect(self.handleSSLErrors)

        return reply

    def handleSSLErrors(self, reply, errors):
        for err in errors:
            self.logger.error('SSL errors:' + err.errorString())

    def handleAuthenticationRequired(self, reply, authenticator):
        if self.user == '' and self.password == '':
            self.logger.warning(
                'authentication required and no user/password set')

        authenticator.setUser(self.user)
        authenticator.setPassword(self.password)

    def configureCerts(self):
        ## import the private client key
        privateKeyFile = QFile(self.clientKeyFile)
        privateKeyFile.open(QIODevice.ReadOnly)
        privateKey = QSslKey(privateKeyFile, QSsl.Rsa)

        if privateKey.isNull():
            self.logger.warning('SSL private key is null')
        else:
            self.sslConfig.setPrivateKey(privateKey)

        ## import the client certificate
        certFile = QFile(self.clientCertFile)
        certFile.open(QIODevice.ReadOnly)
        cert = QSslCertificate(certFile)
        self.sslConfig.setLocalCertificate(cert)

        ## import the self-signed CA certificate
        caCertFile = QFile(self.caCertFile)
        caCertFile.open(QIODevice.ReadOnly)
        caCert = QSslCertificate(caCertFile)

        ## add self-signed CA cert to the other CA certs
        caCertList = self.sslConfig.caCertificates()
        caCertList.append(caCert)
        self.sslConfig.setCaCertificates(caCertList)
Пример #2
0
class SSLConfig(_SSLConfig):
    """Qt-based implementation of SSLConfig.

    This implementation does a few things to help:

    * Automate QSslConfiguration.set* calls and ensure that they happen up
      front, which is important when some may have no effect later.

    * Hide the dance of creating a QSslKey.

    * Makes it easier to set SSL options, and sets defaults marked in Qt docs
      as more secure, so that less secure options must be explicitly specified.
    """

    default_options = _SSLConfig.default_options.copy()
    default_options.update({
        # Prevent injection of plaintext into SSL sessions.
        # This option isn't available for other backends.
        "legacy renegotiation": False,

        # Prevents BEAST, but "causes problems with a large number of servers".
        # Yet it works with BCS, so we should use it when it's available.
        "empty_fragments": False,
    })

    def __init__(
        self,
        protocol=None,
        key=None,
        options=None,
    ):
        super(SSLConfig, self).__init__(
            protocol=protocol,
            key=key,
            options=options,
        )

        # Set up implementation-specific state...

        # QSslConfiguration is a bag of data we need to talk to Qt. Its
        # attributes must be set using its various setWhatever methods.
        self._q_ssl_config = QSslConfiguration()

        # Get a protocol constant Qt understands, or cry to the user.
        q_ssl_protocol = _PROTOCOL_CHOICES.get(self.protocol)
        if q_ssl_protocol is None:
            raise InvalidSSLConfig("unknown protocol for Qt: {0!r}".format(
                self.protocol))
        # Hang on to it just in case we possibly need it, e.g. debugger
        self._q_ssl_protocol = q_ssl_protocol

        # Otherwise, tell Qt about the protocol.
        # n.b.: setting this after connection starts has no effect, so we
        # definitely want to do it here instead of deferring this.
        self._q_ssl_config.setProtocol(q_ssl_protocol)

        # If we have an SSLKey, have it make a QSslKey and tell Qt about it.
        if self.key:
            q_ssl_key = self.key.to_q_ssl_key()
            self._q_ssl_config.setPrivateKey(q_ssl_key)
        else:
            q_ssl_key = None
        self._q_ssl_key = q_ssl_key

        # Process self.options
        self._set_options()

    def _set_options(self):
        """Internal: convert options to set QSSLConfiguration option flags.
        """
        for key, value in self.options.items():

            # Get the constant used by PyQt
            option = _PROTOCOL_OPTIONS.get(key.lower().replace("_", " "))

            # Make sure we don't fail silently with unrecognized options
            if option is None:
                raise InvalidSSLConfig(
                    "unknown option for Qt: {0!r}".format(key))

            # All the Qt options are "Disable*", inverting the bools.
            self._q_ssl_config.setSslOption(option, not value)