portail_captif.py 6.07 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
import sys
import subprocess
import time
import ldap
sys.path.append('/usr/scripts/')

import lc_ldap.shortcuts
import lc_ldap.objets
from iptools import AddrInNet, NetSubnets, IpSubnet
def _get_ldap_connection():
    return lc_ldap.shortcuts.lc_ldap_readonly(user=u'root')
QUERY = _get_ldap_connection()

cache={}
cache_time=60.0
cleanup_time=3600.0
next_cleanup=time.time() + cleanup_time

def cleanup(now):
20 21 22 23 24 25 26
    global cleanup_time, cache, cache_time, next_cleanup
    if next_cleanup < now:
        for ip in cache.keys(): 
            if cache[ip]['time']<(now - cache_time):
                del cache[ip]
        next_cleanup=time.time() + cleanup_time
        
27 28 29


deco={
30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56
    'non_inscrit': 'ERR_CUSTOM_NON_INSCRIT.html',
    'inscrit': 'ERR_CUSTOM_INSCRIT.html',

    'ex_crous': 'ERR_CUSTOM_EX_CROUS.html',
    'ex_crous_enable': 'ERR_CUSTOM_EX_CROUS_ENABLE.html',
    
    'age': 'ERR_CUSTOM_AGE.html',
    'ago': 'ERR_CUSTOM_AGO.html',
    
    'autodisc_p2p': 'ERR_CUSTOM_BL_AUTO_P2P.html',
    'p2p':'ERR_CUSTOM_BL_P2P.html',
    'autodisc_upload':'ERR_CUSTOM_BL_AUTO_UPLOAD.html',
    'upload':'ERR_CUSTOM_BL_UPLOAD.html',
    'chambre_invalide': 'ERR_CUSTOM_BL_CHAMBRE.html',
    'carte_etudiant':'ERR_CUSTOM_BL_NO_CARTE.html',
    'mail_invalide':'ERR_CUSTOM_BL_NO_MAIL.html',
    'mail_invalide_inscription':'ERR_DISABLED_CUSTOM_BL_NO_MAIL.html',
    'warez':'ERR_CUSTOM_BL_WAREZ.html',
    'bloq':'ERR_CUSTOM_BLOQ.html',
    
    'nouvelle_annee':'ERR_CUSTOM_NOUVELLE_ANNEE.html',
    'paiement': 'ERR_CUSTOM_NOUVELLE_ANNEE.html',
    'proxy_local':'ERR_CUSTOM_PROXY_LOCAL.html',
    
    'virus':'ERR_CUSTOM_BL_VIRUS.html',
    'ipv6_ra':'ERR_CUSTOM_RA.html',
    'autodisc_virus':'ERR_CUSTOM_BL_AUTO_VIRUS.html',
57
}
58
    
59
for bl in deco.keys():
60 61
     deco[bl]="/crans-deco/%s" % deco[bl]
    
62
blacklist_key = [
63 64 65 66 67 68 69 70 71
    'non_inscrit',
    'age','ago',
    'virus','autodisc_virus','ipv6_ra',
    'p2p','autodisc_p2p','upload','autodisc_uplaod','warez',
    'carte_etudiant','chambre_invalide','mail_invalide',
    'bloq',
    'nouvelle_annee','proxy_local', 'paiement',
    'inscrit'
    ]
72 73

def mac_from_ip(ip):
74 75 76 77 78 79 80 81 82
    if ip == "10.51.0.10": return u"02:72:6f:75:74:07"
    cmd = '/usr/sbin/arp -na %s' % ip
    p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE)
    output, errors = p.communicate()
    if output is not None : 
        mac_addr = output.split()[3]
        return mac_addr.strip()
    else:
        return None
83

84 85 86 87 88 89 90 91 92 93 94 95 96
def enable_access(ip):
    """Lance la commande idoine pour autoriser l'adresse IP"""
    p = subprocess.Popen(['sudo', '-n', '/usr/scripts/utils/install-party/ipset_allow', ip],
        stdout=subprocess.PIPE,
        stderr=subprocess.PIPE)
    out, err = p.communicate()
    if out or err:
        print "ipset_allow:"
        print out
        print "---"
        print err
        return False
    return True
97 98

def get(str):
99 100 101 102 103 104 105
    global  QUERY
    try:
        return QUERY.search(str)
    except ldap.SERVER_DOWN:
        QUERY = _get_ldap_connection()
        return QUERY.search(str)
        
106
def get_machine_by_mac(ip):
107 108 109 110 111 112 113 114
        mac_addr=mac_from_ip(ip)
        machines = get(u'macAddress=%s' % mac_addr)
        #if machines and isinstance(machines[0], lc_ldap.objets.machineWifi):
        #    if not 'ipHostNumber' in machines[0].attrs.keys():
        #        machine = QUERY.search(u'macAddress=%s' % mac_addr, mode='rw')[0]
        #        machine.set_ipv4()
        return machines
        
115 116

def get_machine_by_ip(ip):
117 118
    return get(u'ipHostNumber=%s' % ip)
    
119
def get_page(ip, by_mac=False, accueil=False):
120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136
    try:
        if by_mac:
            machines=get_machine_by_mac(ip)
        else:
            machines=get_machine_by_ip(ip)
        adherent=machines[0].proprio()
    except IndexError:
        return deco['non_inscrit']
    blacklist=[bl.value['type'] for bl in adherent.blacklist_actif()]
    for machine in machines:
        blacklist.extend([bl.value['type'] for bl in machine.blacklist_actif()])
    for bl in blacklist_key:
        if bl in blacklist:
            return deco[bl]
    if accueil:
        return deco['inscrit']
    return None
137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155

def special(action, ip, environ, start_response):
    mac = mac_from_ip(ip)
    url = "https://intranet2.crans.org/machines/add/"
    if 'wifi' in action:
        url += 'wifi/'
    else:
        url += 'fil/'
    if mac is not None:
        url += mac + '/'
    start_response("302 OK", [
        ("Content-Type", "text/html"),
        ("Cache-Control", "no-cache, must-revalidate"),
        ("Expires", "Thu, 01 Jan 1970 00:00:00 GMT"),
        ("Location", url),
        ("Content-Length", 0)
    ])
    return ""
    
156
    
157
def app(environ, start_response):
158 159 160 161 162 163
    if 'HTTP_K_REAL_IP' in environ.keys():
        ip=environ['HTTP_K_REAL_IP']
    else:
        ip=environ['HTTP_REAL_IP']
    now=time.time()
    cleanup(now)
164 165
    if environ.get('RAW_URI', '').startswith('/special'):
        return special(environ.get('RAW_URI','')[9:], ip, environ, start_response)
166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198
    if AddrInNet(ip, '10.231.137.0/24'):
        if environ.get('RAW_URI', '').startswith('/enable'):
            enable_access(ip)
            data = deco['ex_crous_enable']
        else:
            data = deco['ex_crous']
    elif ip in cache.keys() and cache[ip]['time']>(now - cache_time):
        data=cache[ip]['page']
    else:
        if AddrInNet(ip,'10.51.0.0/16'):
            data=get_page(ip,True,True)
        elif AddrInNet(ip,'10.52.0.0/16'):
            page=get_page(ip,True)
            if page:
                data=page
            else:
                data=deco['autodisc_virus']
        elif AddrInNet(ip,'138.231.136.0/21') or AddrInNet(ip,'138.231.144.0/21') or AddrInNet(ip,'10.2.9.0/24'):
            page=get_page(ip)
            if page:
                data=page
            else:
                data="/crans-proxy/"
        else:
            data = deco['non_inscrit']
        cache[ip]={'time':time.time(),'page':data}
    start_response("200 OK", [
        ("Content-Type", "text/html"),
        ("Cache-Control", "no-cache, must-revalidate"),
        ("Expires", "Thu, 01 Jan 1970 00:00:00 GMT"),
        ("X-Accel-Redirect", data),
        ("Content-Length", 0)
    ])
199

200
    return ""