diff --git a/modules/cmb/backend.py b/modules/cmb/backend.py index e8e16aea..b8998a02 100644 --- a/modules/cmb/backend.py +++ b/modules/cmb/backend.py @@ -23,6 +23,7 @@ from weboob.tools.backend import BaseBackend, BackendConfig from weboob.tools.value import ValueBackendPassword, ValueBool from weboob.capabilities.base import NotAvailable from weboob.tools.browser import BrowserIncorrectPassword, BrokenPageError +from weboob.tools.browser2 import BaseBrowser from re import match, compile, sub from urllib import urlencode @@ -31,16 +32,8 @@ from lxml import etree from datetime import date from StringIO import StringIO -from ssl import DER_cert_to_PEM_cert -from hashlib import sha256 - - import os -# import a library that adds certificate verification and proxy support to -# HTTPSConnection -from hellhttp import HellHTTPS - __all__ = ['CmbBackend'] @@ -53,7 +46,8 @@ class CmbBackend(BaseBackend, ICapBank): LICENSE = 'AGPLv3+' AUTH_CERT = os.path.dirname(__file__) AUTH_CERT += '/Verisign_Class_3_Public_Primary_Certification_Authority.pem' - CERTHASH = '684d79eb02f59497b5a9c5dcc4c26db1ee637db12f29d703fdf6a80aafef892d' + # CERTHASH is not used anymore + # CERTHASH = '684d79eb02f59497b5a9c5dcc4c26db1ee637db12f29d703fdf6a80aafef892d' DESCRIPTION = u'Crédit Mutuel de Bretagne' CONFIG = BackendConfig( ValueBackendPassword('login', label='Identifiant', masked=False), @@ -97,7 +91,9 @@ class CmbBackend(BaseBackend, ICapBank): ) ] + BROWSER = BaseBrowser cookie = None + islogged = False headers = { 'User-Agent': 'Mozilla/5.0 (iPad; U; CPU OS 3_2_1 like Mac OSX; en-us) ' + @@ -110,55 +106,28 @@ class CmbBackend(BaseBackend, ICapBank): return certhash == self.CERTHASH def login(self): - params = urlencode({ + data = { 'codeEspace': 'NO', 'codeEFS': '01', 'codeSi': '001', 'noPersonne': self.config['login'].get(), 'motDePasse': self.config['password'].get() - }) - if 'no_check' in self.config and self.config['no_check'].get() == "y": - conn = HellHTTPS("www.cmb.fr") - else: - conn = HellHTTPS("www.cmb.fr", ca_file=self.AUTH_CERT, callBack=self.sslCallBack) - conn.connect() - headers = {'Content-Type': 'application/x-www-form-urlencoded'} - conn.request("POST", - "/domiweb/servlet/Identification", - params, - headers) - response = conn.getresponse() - conn.close() - if response.status == 302: - self.cookie = response.getheader('Set-Cookie').split(';')[0] - self.cookie += ';' - return True + } + + response = self.browser.open("https://www.cmb.fr/domiweb/servlet/Identification", None, False, data=data) + + if response.status_code == 302: + self.islogged=True + return True else: raise BrowserIncorrectPassword() return False def iter_accounts(self): - if not self.cookie: + if not self.islogged: self.login() - def do_http(): - if 'no_check' in self.config and self.config['no_check'].get() == "y": - conn = HellHTTPS("www.cmb.fr") - else: - conn = HellHTTPS("www.cmb.fr", ca_file=self.AUTH_CERT, callBack=self.sslCallBack) - conn.connect() - headers = self.headers - headers['Cookie'] = self.cookie - conn.request("GET", - '/domiweb/prive/particulier/releve/0-releve.act', - {}, - headers) - response = conn.getresponse() - data = response.read() - conn.close() - return data - - data = do_http() + data = self.browser.open("https://www.cmb.fr/domiweb/prive/particulier/releve/0-releve.act").content parser = etree.HTMLParser() tree = etree.parse(StringIO(data), parser) @@ -167,7 +136,7 @@ class CmbBackend(BaseBackend, ICapBank): title = tree.xpath('/html/head/title')[0].text if title == u"Utilisateur non identifié": self.login() - data = do_http() + data = self.browser.open("https://www.cmb.fr/domiweb/prive/particulier/releve/0-releve.act").content parser = etree.HTMLParser() tree = etree.parse(StringIO(data), parser) @@ -216,7 +185,7 @@ class CmbBackend(BaseBackend, ICapBank): raise AccountNotFound() def iter_history(self, account): - if not self.cookie: + if not self.islogged: self.login() page = "/domiweb/prive/particulier/releve/" @@ -230,21 +199,7 @@ class CmbBackend(BaseBackend, ICapBank): page += account._cmbvaleur2 page += "&deviseOrigineEcran=EUR" - def do_http(): - if 'no_check' in self.config and self.config['no_check'].get() == "y": - conn = HellHTTPS("www.cmb.fr") - else: - conn = HellHTTPS("www.cmb.fr", ca_file=self.AUTH_CERT, callBack=self.sslCallBack) - conn.connect() - headers = self.headers - headers['Cookie'] = self.cookie - conn.request("GET", page, {}, headers) - response = conn.getresponse() - data = response.read() - conn.close - return data - - data = do_http() + data = self.browser.open(page).content parser = etree.HTMLParser() tree = etree.parse(StringIO(data), parser) @@ -253,7 +208,7 @@ class CmbBackend(BaseBackend, ICapBank): title = tree.xpath('/html/head/title')[0].text if title == u"Utilisateur non identifié": self.login() - data = do_http() + data = self.browser.open(page).content parser = etree.HTMLParser() tree = etree.parse(StringIO(data), parser) diff --git a/modules/cmb/hellhttp.py b/modules/cmb/hellhttp.py deleted file mode 100644 index 68a05e97..00000000 --- a/modules/cmb/hellhttp.py +++ /dev/null @@ -1,142 +0,0 @@ -# -*- coding: utf-8 -*- - -# Copyright(C) 2012 Johann Broudin -# -# This file is part of weboob. -# -# weboob is free software: you can redistribute it and/or modify -# it under the terms of the GNU Affero General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# weboob is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Affero General Public License for more details. -# -# You should have received a copy of the GNU Affero General Public License -# along with weboob. If not, see . - -import httplib -import socket -import ssl -import hashlib -from urlparse import urlsplit - - -__all__ = ['HTTPSVerifiedConnection', 'HellHTTPS'] - - -PROXY_PORT = 8080 - - -class HTTPSVerifiedConnection(httplib.HTTPSConnection): - """ - This class allows communication via SSL, and will checks certificates - """ - - def __init__(self, host, port=None, key_file=None, cert_file=None, - ca_file=None, strict=None, timeout=socket._GLOBAL_DEFAULT_TIMEOUT, - callBack=None): - httplib.HTTPSConnection.__init__(self, host, port, key_file, - cert_file, strict, timeout) - self.ca_file = ca_file - self.callBack = callBack - self.certificate = None - - def connect(self): - """ - Connect to a host on a given port and check the certificate - This is almost the same than the conect of HTTPSConnection, but adds - some function for SSL certificate verification - """ - - sock = socket.create_connection((self.host, self.port), self.timeout) - if self._tunnel_host: - self.sock = sock - self._tunnel() - - if self.ca_file: - self.sock = ssl.wrap_socket(sock, - self.key_file, - self.cert_file, - ca_certs = self.ca_file, - cert_reqs=ssl.CERT_REQUIRED) - else: - self.sock = ssl.wrap_socket(sock, - self.key_file, - self.cert_file, - cert_reqs=ssl.CERT_NONE) - - self.certificate = self.sock.getpeercert(True) - if self.callBack: - if not self.callBack(self.certificate): - raise ssl.SSLError(1, "Call back verification failed") - - -class HellHTTPS(object): - "This class is the library used by the weboob's CMB module" - - def __init__(self, host, port=None, proxy=None, proxy_port=None, - key_file=None, cert_file=None, ca_file=None, strict=None, - timeout=socket._GLOBAL_DEFAULT_TIMEOUT, callBack=None): - self.proxy = proxy - self.proxy_port = proxy_port - if not self.proxy: - import os - if 'http_proxy' in os.environ: - o = urlsplit(os.environ['http_proxy']) - self.proxy = o.hostname - if o.port: - self.proxy_port = o.port - else: - self.proxy_port = PROXY_PORT - self.host = host - self.port = port - if self.proxy: - if self.proxy_port: - pport = self.proxy_port - else: - pport = PROXY_PORT - self.conn = HTTPSVerifiedConnection(proxy, pport, key_file, - cert_file, ca_file, strict, timeout, callBack) - else: - self.conn = HTTPSVerifiedConnection(host, port, key_file, cert_file, - ca_file, strict, timeout, callBack) - - def request(self, *args, **kwargs): - self.conn.request(*args, **kwargs) - - def connect(self): - # set the proxy - # python 2.6 needs _set_tunnel, 2.7 needs set_tunnel - if self.proxy: - self.conn._set_tunnel(self.host, self.port) - self.conn.connect() - - def getresponse(self, *args): - return self.conn.getresponse(*args) - - def close(self): - self.conn.close - - -# A script to find the hash that has to be used in the call back function -if __name__ == '__main__': - import sys - if len(sys.argv) > 5 or len(sys.argv) < 1: - print 'usage: python %s host [port [proxy [proxy_port]]]' % sys.argv[0] - sys.exit(1) - conn = HellHTTPS(*sys.argv[1:]) - - conn.connect() - conn.request('GET', '/') - - response = conn.getresponse() - print response.status, response.reason - - pemcert = ssl.DER_cert_to_PEM_cert(conn.conn.certificate) - certhash = hashlib.sha256(pemcert).hexdigest() - - print "Hash: %s" % certhash - conn.close()