JPELGRIMS

Kotnet autologin

Om via kotnet te surfen moet je eerst een webformulier invullen voordat je daadwerkelijk online bent. Indien je verbinding met kotnet tijdelijk uitvalt dan zal je vrij waarschijnlijk opnieuw dit webformulier moeten invullen. Ik ondervind al een tijdje last van haperend internet op mijn kot. Uiteindelijk heb ik dan maar een script geschreven dat mij automatisch inlogt op kotnet en de internetverbinding herstelt indien deze even uitvalt.

Inloggen

Het invullen van het webformulier is vrij gemakkelijk te automatiseren. Het formulier op de inlogpagina ziet er als volgt uit:

<form action="/cgi-bin/netlogin.pl" method="post" name="netlogin">
    <table width="100%"  border="0" cellspacing="0" cellpadding="5" class="layouttable">
        <tr>
            <td colspan="2">
                <input type="hidden" name="inst" value="kuleuven" />
                <input type="hidden" name="lang" value="nl" /> 
                <div align="center">
                    <img src="/images/kuleuven.gif" border="0" alt="KU Leuven" />
                </div>
            </td>
        </tr>
        <tr>
            <td><div align="right">Intranet userid:</div></td>
            <td><input type="text" size="20" maxlength="50" name="uid" id="uid" class="formField" /></td>
        </tr>
        <tr>
            <td><div align="right">Wachtwoord:</div></td>
            <td><input type="password" size="20" maxlength="50" name="pwd21965" class="formField" autocomplete="off"/></td>
        </tr>
        <tr>
            <td>&nbsp;</td>
            <td><input type="submit" name="submit" value="Login" /></td>
        </tr>
    </table>
</form> 

Om in te loggen moeten we dus enkel een POST-verzoek met de parameters 'uid', 'pwd', 'inst' en 'lang' naar het serverscript ('https://netlogin.kuleuven.be/cgi-bin/netlogin.pl') sturen. Er is echter wel een klein probleem dat eerst opgelost moet worden: de naam van de 'pwd'-parameter verandert voortdurend. De naam van deze parameter bestaat uit de letters 'pwd' gevolgd door maximaal vijf cijfers, die steeds stijgen in waarde. Om succesvol in te loggen moeten we op één of andere manier de naam van deze parameter kunnen achterhalen. Door een GET-verzoek te doen voordat we proberen in te loggen kunnen we deze parameternaam opzoeken in de gekregen HTML-code.

import requests

username = ""
password = ""
email = ""
ip_addresses = [...]

domain = "https://netlogin.kuleuven.be"
login_prompt_url = "/cgi-bin/wayf2.pl?inst=kuleuven&lang=nl&submit=Ga+verder+%2F+Continue"
login_form_url = "/cgi-bin/netlogin.pl"

headers = {"User-Agent": "KotnetAutoLogin 0.0.1", 
           "From": email}

def parse_pwd_parameter(response):
    start = response.text.find("pwd")
    end = response.text.find('"', start, len(response.text))
    pwd_parameter = response.text[start:end]
    return pwd_parameter

def login():
    response = requests.get(domain + login_prompt_url, headers=headers)
    pwd_parameter = parse_pwd_parameter(response)
    response = requests.post(domain + login_form_url, 
                             headers=headers,
                             data = {'uid': username,
                                     'inst': 'kuleuven',
                                     'lang': 'nl',
                                     'submit': 'Login',
                                     pwd_parameter: password})
    if "Login geslaagd" in response.text:
        return True
    else:
        return False

Uitloggen

Soms gebeurt het echter dat je niet kan inloggen op kotnet omdat je al met te veel apparaten (computer, gsm, ...) ingelogd bent. Dit probleem kunnen we echter gemakkelijk verhelpen door de ip-adressen van alle apparaten te overlopen en deze automatisch uit te loggen, totdat er een plaats vrijkomt. Het uitlog-formulier ziet er als volgt uit:

<form action="/cgi-bin/netlogout.pl" method="post" name="netlogout">
    <table width="100%"  border="0" cellspacing="0" cellpadding="5" class="layouttable">
        <tr>
            <td colspan="2">
                <input type="hidden" name="inst" value="kuleuven" /> 
                <input type="hidden" name="lang" value="nl" /> 
                <input type="hidden" name="ip" value="..." /> 
                <div align="center">
                    <img src="/images/kuleuven.gif" border="0" alt="###INSTELLING" />
                </div>
            </td>
        </tr>
        <tr>
            <td><div align="right">Intranet userid:</div></td>
            <td><input type="hidden" name="uid" id="uid" class="formField" value="..." />...</td>
        </tr>
        <tr>
            <td><div align="right">Wachtwoord:</div></td>
            <td><input type="password" size="20" maxlength="50" name="pwd27529" id="pwd" class="formField" /></td>
        </tr>
        <tr>
            <td>&nbsp;</td>
            <td><input type="submit" name="submit" value="Logout" /></td>
        </tr>
    </table>
</form> 

Net zoals bij het inloggen moeten we hier eerst de naam van de 'pwd'-parameter uit een GET-verzoek halen. Daarna kunnen we een POST-verzoek sturen naar het relevante script ('https://netlogin.kuleuven.be/cgi-bin/netlogout.pl') om uit te loggen, deze keer met een extra parameter 'ip' (het ip-adres van het apparaat dat je wil uitloggen).

def logout(ip_address):
    response = requests.post(domain + logout_prompt_url, 
                             headers=headers, 
                             data= {'inout': "logout",
                                    'ip': ip_address,
                                    'network': 'KotNet',
                                    'uid': "kuleuven/" + username,
                                    'lang': 'ned'})
    pwd_parameter = parse_pwd_parameter(response)
    response = requests.post(domain + logout_form_url, 
                             headers=headers, 
                             data = {'uid': username,
                             pwd_parameter: password,
                             'ip': ip_address,
                             'inst': 'kuleuven',
                             'lang': 'nl',
                             'submit': 'Logout'})
    if "Logout geslaagd" in response.text:
       return True
    elif "rc=207" in response.text:
        # IP address not logged in
        return True
    else:
        return False

Service

Om er voor te zorgen dat de internetverbinding automatisch hersteld word als die uitvalt laten we het script in een eindeloze lus lopen waarin voortdurend gecontroleerd wordt of het internet wel degelijk bereikbaar is. Indien dat niet het geval is dan wordt de login-procedure doorgenomen.

def is_kotnet_up():
    response = requests.get(domain + login_prompt_url, headers=headers)
    if response.status_code is 200:
        return True
    else:
        return False

def is_internet_up():
    response = requests.get("http://www.google.com", timeout=5)
    if response.status_code is 200 and not "Log in aub" in response.text:
        return True
    else:
        return False

def run():
    while True:
        if not is_internet_up() and is_kotnet_up():
            logging.info("Authenticating...")
            if not login():
                for ip_address in ip_addresses:
                    logout(ip_address)
                    if login():
                        break
            if is_internet_up():
                logging.info("Kotnet authentication succesfull!")
            else:
                logging.info("Kotnet authentication failed.")
        time.sleep(60)

if __name__ == "__main__":
    run()

Op een Linux-systeem kan men met systemd een service van het script maken zodat het altijd actief is. Hiervoor gebruik ik de volgende unit file:

[Unit]
Description=KotnetAuth
After=multi-user.target

[Service]
Type=simple
ExecStart=/usr/bin/python3 /opt/KotnetAuth.py
User=user
WorkingDirectory=/opt/
Restart=on-failure

[Install]
WantedBy=multi-user.target

Op windows-systemen kan je met de 'task scheduler' ervoor zorgen dat het script wordt uitgevoerd als het systeem opstart.

Het volledige script kan je hier terugvinden.