Coova Chilli Hotspot/Installation

aus PUG, der Penguin User Group
Wechseln zu: Navigation, Suche

Inhaltsverzeichnis

Hauptseite

Zurück zur Einführung

Debian Lenny Installation

Zwar verwendet der Autor hier Debian Lenny, aber diese Anleitung sollte auch weitestgehend auf alle anderen Debian- basierten Distributionen übertragbar sein. Mit ein paar Modifikationen kann man sie sicher auch auf RedHat oder SuSE übertragen.

Basis Installation

Für die Installation reicht in der Regel die NetInst Installations CD Um flexibel zu bleiben, entscheide ich mich für eine LVM Konfiguration für die Partitionierung:

Festplatten Aufteilung
Quelle MountPoint Größe Dateisystem
/dev/sda1 /boot 150MB ext3
/dev/sda2 SWAP 512MB - 1GB SwapFS
/dev/system/root_fs / 3-5GB ext3
/dev/system/tmp_fs /tmp 512MB ext3
/dev/system/var_log_fs 2GB /var/log ext3


Weitere Pakete

Die Installation sollte selbst nur die absolute Basis sein. Es reicht daher in der Softwareauswahl entweder alles zu deaktivieren, oder einzig "Standard" aktiviert zu lassen. Ist die Installation soweit abgeschlossen und der Rootprompt bereit, werden nun einige Pakete nachinstalliert:

  • Pakete nachinstallieren
Debian-term.png
spot01 ~ # apt-get install vim ssh nullmailer mysql-server

Vim dient hier lediglich dazu, den Komfort zu erhöhen, beim editieren von Textdateien. Es kann stattdessen natürlich jeder andere Editor verwendet werden, wie z.B joe od. mc. Als absolutes Pflichtpaket gehört ein SSH Server auf den Rechner. Für den Fall der Fälle, dass E-Mail den Rechner verlassen sollen, wird der SMTP Server nullmailer verwendet. Er dient lediglich dazu, E-Mails an einen richtigen E-Mail Server weiterzuleiten. Der MySQL Server wird für die Authentifizierung und Session Verwaltung benötigt. Während der Installation wird nach einem Root Kennwort gefragt, welches entsprechend ausgefüllt werden sollte.

Netzwerk Konfiguration

Wir gehen hier davon aus, dass wir über zwei Netzwerkkarten verfügen:

  • eth0 - über sie erreichen wir das Internet und wird per DHCP konfiguriert
  • eth1 - an dieser Netzwerkkarte hängt der AccessPoint und/oder ein Switch für die W-Lan od. Kabel Clients

Während die eth0 ihre IP Adresse und Default Route über einen DHCP Server bezieht, wird die eth1 dagegen unkonfiguriert belassen. Sie wird später automatisch von Coova Chilli verwendet.

  • /etc/network/interfaces
Ascii.png
auto lo
iface lo inet loopback
  
# Externe NIC zum Router/Internet
auto eth0
iface eth0 inet dhcp

# NIC mit den W-LAN Clients
auto eth1

FreeRadius Server

Wie bereits erwähnt, benötigen wir einen Authentifizierungsserver. Diese Funktion stellt uns der Service FreeRadius zur Verfügung. Als Datenquelle kann der Radius Server unterschiedliche Dienste abfragen. Darunter sind z.B. LDAP, SQL, oder die lokale /etc/passwd Datei. In diesem Fall verwenden wir den bereits installierten MySQL Server. Daher kommt noch das Modul für diesen dazu.

  • FreeRadius installieren
Debian-term.png
spot01 ~ # apt-get install freeradius freeradius-mysql


MySQL Datenbank

Datenbank anlegen

Als nächstes wird die Datenbank erstellt und mit Tabellen gefüllt:

  • Datenbank erstellen
Debian-term.png
spot01 ~ # mysqladmin -psecret create radius
spot01 ~ # mysql radius < /etc/freeradius/sql/mysql/schema.sql  -psecret
spot01 ~ # mysql radius < /etc/freeradius/sql/mysql/nas.sql  -psecret

Mit dem ersten Kommando erzeugen erzeugen wir die Datenbank. Das MySQL Root Kennwort (hier secret) wird der Bequemlichkeit- halber gleich mit gegeben. Das zweite und dritte Kommando füllt die Datenbank und legt die nötigen Tabellen an. Auch hier geben wir das Root Kennwort gleich mit.

Datenbank Benutzer

Da wir nicht den Root Account verwenden wollen, für den Zugriff auf die Datenbank, erzeugen wir einen Benutzer, der die dazu nötigen Rechte erhält. Am einfachsten ist es, eine Datei mit den entsprechenden Kommandos anzulegen und sie dann dem MySQL Server zuzuführen:

  • radius-user.sql
Ascii.png
  CREATE USER 'radius'@'localhost';
  SET PASSWORD FOR 'radius'@'localhost' = PASSWORD('radiuspass');
  
  # The server can read any table in SQL
  GRANT SELECT ON radius.* TO 'radius'@'localhost';
  
  # The server can write to the accounting and post-auth logging table.
  #
  #  i.e. 
  GRANT ALL on radius.radacct TO 'radius'@'localhost';
  GRANT ALL on radius.radpostauth TO 'radius'@'localhost';
  GRANT ALL on radius.radcheck TO 'radius'@'localhost';
  GRANT ALL on radius.nas TO 'radius'@'localhost';

Es wird also ein Benutzer radius angelegt, mit dem Kennwort radiuspass. Er darf auf alle Tabellen lesend zugreifen und zusätzlich schreibend auf die Tabellen radacct, radpostauth, radcheck, nas. Dies jedoch nur vom eigenen Rechner. Nun fügen wir den Benutzer mit folgendem Befehl hinzu:

  • Benutzer hinzufügen
Gnome-terminal.png
spot01 ~ # mysql < radius-user.sql -psecret

Ob dies geklappt hat, kann man überprüfen mit:

Gnome-terminal.png
spot1:~# mysql -uradius -pradiuspass radius -e 'show tables;'

+------------------+
| Tables_in_radius |
+------------------+
| nas              |
| radacct          |
| radcheck         |
| radgroupcheck    |
| radgroupreply    |
| radpostauth      |
| radreply         |
| radusergroup     |
+------------------+

FreeRadius anpassen

Nun muss der FreeRadius Server darauf vorbereitet werden. Dazu bearbeiten wir zuerst die für MySQL zuständige Datei:

  • /etc/freeradius/sql.conf
Ascii.png
sql {
	database = "mysql"
	driver = "rlm_sql_${database}"
	server = "localhost" # DB Server
	login = "radius" # DB Benutzernamen
	password = "radiuspass" # DB Passwort
	radius_db = "radius"
	acct_table1 = "radacct"
	acct_table2 = "radacct"
	postauth_table = "radpostauth"
	authcheck_table = "radcheck"
	authreply_table = "radreply"
	groupcheck_table = "radgroupcheck"
	groupreply_table = "radgroupreply"
	usergroup_table = "radusergroup"
	read_groups = no
	deletestalesessions = yes
	sqltrace = no
	sqltracefile = ${logdir}/sqltrace.sql
	num_sql_socks = 5
	connect_failure_retry_delay = 60
	readclients = yes # von No auf Yes
	nas_table = "nas" # 
	$INCLUDE sql/${database}/dialup.conf # Einbinden
   }

Da die Datei eine Menge Kommentare beinhaltet, wird sie hier Vollständigkeit abgebildet. Wirklich interessant sind allerdings nur die Zeilen für den MySQL Server, sowie die letzten drei Zeilen.

Nun muss diese Datei noch vom Radius Server eingebunden werden, welches wieder über ein Include geschieht. Dazu müssen wir nun die Hauptkonfiguration- Datei öffnen:

  • /etc/freeradius/radiusd.conf
Ascii.png
   prefix = /usr
   exec_prefix = /usr
   sysconfdir = /etc
   localstatedir = /var
   sbindir = ${exec_prefix}/sbin
   logdir = /var/log/freeradius
   raddbdir = /etc/freeradius
   radacctdir = ${logdir}/radacct
   confdir = ${raddbdir}
   run_dir = ${localstatedir}/run/freeradius
   db_dir = $(raddbdir)
   libdir = /usr/lib/freeradius
   pidfile = ${run_dir}/freeradius.pid
   user = freerad
   group = freerad
   max_request_time = 30
   cleanup_delay = 5
   max_requests = 1024

   listen {
	type = auth
	ipaddr = *
	port = 0
   }

   listen {
	ipaddr = *
	port = 0
	type = acct
   }

   hostname_lookups = no
   allow_core_dumps = no
   regular_expressions	= yes
   extended_expressions	= yes

   log {
	destination = files
	file = ${logdir}/radius.log
	syslog_facility = daemon
	stripped_names = no
	auth = no
	auth_badpass = no
	auth_goodpass = no
   }

   checkrad = ${sbindir}/checkrad
   security {
	max_attributes = 200
	reject_delay = 1
	status_server = yes
   }
   ### kann abgeschaltet werden ####
   proxy_requests  = no 
   #####  #####
   $INCLUDE proxy.conf
   $INCLUDE clients.conf
   snmp	= no
   $INCLUDE snmp.conf

   thread pool {
	start_servers = 5
	max_servers = 32
	min_spare_servers = 3
	max_spare_servers = 10
	max_requests_per_server = 0
   }

  modules {
	pap {
		auto_header = no
	}

	chap {
		authtype = CHAP
	}

	pam {
		pam_auth = radiusd
	}

	unix {
		radwtmp = ${logdir}/radwtmp
	}

   $INCLUDE eap.conf

	mschap {
	}

	ldap {
		server = "ldap.your.domain"
		basedn = "o=My Org,c=UA"
		filter = "(uid=%{Stripped-User-Name:-%{User-Name}})"
		ldap_connections_number = 5
		timeout = 4
		timelimit = 3
		net_timeout = 1

		tls {
			start_tls = no
		}

		dictionary_mapping = ${confdir}/ldap.attrmap
		edir_account_policy_check = no
	}

	realm IPASS {
		format = prefix
		delimiter = "/"
	}

	realm suffix {
		format = suffix
		delimiter = "@"
	}

	realm realmpercent {
		format = suffix
		delimiter = "%"
	}

	realm ntdomain {
		format = prefix
		delimiter = "\\"
	}	

	checkval {
		item-name = Calling-Station-Id
		check-name = Calling-Station-Id
		data-type = string
	}

	preprocess {
		huntgroups = ${confdir}/huntgroups
		hints = ${confdir}/hints
		with_ascend_hack = no
		ascend_channels_per_line = 23
		with_ntdomain_hack = no
		with_specialix_jetstream_hack = no
		with_cisco_vsa_hack = no
	}

	files {
		usersfile = ${confdir}/users
		acctusersfile = ${confdir}/acct_users
		preproxy_usersfile = ${confdir}/preproxy_users
		compat = no
	}

	detail {
		detailfile = ${radacctdir}/%{Client-IP-Address}/detail-%Y%m%d
		detailperm = 0600
		header = "%t"
	}

	acct_unique {
		key = "User-Name, Acct-Session-Id, NAS-IP-Address, Client-IP-Address, NAS-Port"
	}

	$INCLUDE sql.conf  ###### Wichtiger Teil #######

	radutmp {
		filename = ${logdir}/radutmp
		username = %{User-Name}
		case_sensitive = yes
		check_with_nas = yes		
		perm = 0600
		callerid = "yes"
	}

	radutmp sradutmp {
		filename = ${logdir}/sradutmp
		perm = 0644
		callerid = "no"
	}

	attr_filter attr_filter.post-proxy {
		attrsfile = ${confdir}/attrs
	}

	attr_filter attr_filter.pre-proxy {
		attrsfile = ${confdir}/attrs.pre-proxy
	}

	attr_filter attr_filter.access_reject {
		key = %{User-Name}
		attrsfile = ${confdir}/attrs.access_reject
	}

	attr_filter attr_filter.accounting_response {
		key = %{User-Name}
		attrsfile = ${confdir}/attrs.accounting_response
	}

	counter daily {
		filename = ${db_dir}/db.daily
		key = User-Name
		count-attribute = Acct-Session-Time
		reset = daily
		counter-name = Daily-Session-Time
		check-name = Max-Daily-Session
		reply-name = Session-Timeout
		allowed-servicetype = Framed-User
		cache-size = 5000
	}

	always fail {
		rcode = fail
	}

	always reject {
		rcode = reject
	}

	always noop {
		rcode = noop
	}

	always handled {
		rcode = handled
	}

	always updated {
		rcode = updated
	}

	always notfound {
		rcode = notfound
	}

	always ok {
		rcode = ok
		simulcount = 0
		mpp = no
	}

	expr {
	}

	digest {
	}

	expiration {
		reply-message = "Password Has Expired\r\n" 
	}

	logintime {
		reply-message = "You are calling outside your allowed timespan\r\n"
		minimum-timeout = 60
	}

	exec {
		wait = yes
		input_pairs = request
		shell_escape = yes
		output = none
	}

	exec echo {
		wait = yes
		program = "/bin/echo %{User-Name}"
		input_pairs = request
		output_pairs = reply
		shell_escape = yes
	}
          # Kann unbeachtet bleiben, nur fuer Dial IN !!!
	ippool main_pool {
		range-start = 192.168.1.1
		range-stop = 192.168.3.254
		netmask = 255.255.255.0
		cache-size = 800
		session-db = ${db_dir}/db.ippool
		ip-index = ${db_dir}/db.ipindex
		override = no
		maximum-timeout = 0
	}

	policy {
	       filename = ${confdir}/policy.txt
	}
   }

   instantiate {
	exec
	expr
	expiration
	logintime
   }
  
 $INCLUDE policy.conf
   
   #### Nebenconfig ####
   $INCLUDE sites-enabled/

Auch hier die vollständige Datei. Zu beachten ist lediglich $INCLUDE sql.conf Zeile.

Da auch hier wiederum Teile ausgegliedert wurde, muss eine weitere Datei editiert werden. Ähnlich wie bei einem Apachen, können unterschiedliche Konfigurationen erzeugt werden, für unterschiedliche Zwecke. Diese liegen im /etc/freeradius/sites-available Verzeichnis.

  • /etc/freeradius/sites-available/default
Ascii.png
authorize {
	preprocess
	chap
	mschap
	suffix

	eap {
		ok = return
	}

	unix
	sql # aktivieren
	expiration
	logintime
	pap
   }

   authenticate {
	Auth-Type PAP {
		pap
	}

	Auth-Type CHAP {
		chap
	}

	Auth-Type MS-CHAP {
		mschap
	}

	unix
	eap
   }

   preacct {
	preprocess
	acct_unique
	suffix
	files
   }

   accounting {
	detail
	unix
	radutmp
	sql # aktivieren
	attr_filter.accounting_response
   }

  session {
	radutmp
	sql # aktivieren
   }

   post-auth {
	exec
	Post-Auth-Type REJECT {
		attr_filter.access_reject
	}
   }

   pre-proxy {
   }

   post-proxy {
	eap
   }

Hier müssen die entsprechend auskommentierten SQL Zeilen von ihrem Kommentarzeichen befreit werden. Vor allem die Zeilen session müssen aktiviert werden.

Zu guter letzt wird die Client Konfiguration vom Radius Server angepasst:

  • /etc/freeradius/clients.conf
Ascii.png
client localhost {
	ipaddr = 127.0.0.1
	secret		= radiussecret
	require_message_authenticator = no
   }

Radius Benutzer hinzufügen

Nun können wir zwei Benutzer für Radius hinzufügen, welche in die Datenbank eingepflegt werden:

Gnome-terminal.png
 
spot01 ~ # echo "INSERT INTO radcheck (UserName, Attribute, Value) VALUES ('guest', 'Password','guest');" | mysql -u radius -pradspot01 radius
spot01 ~ # echo "INSERT INTO radcheck (UserName, Attribute, Value) VALUES ('chillispot', 'Password','chillipass');" | mysql -u radius -pradiuspass radius

Es werden also zwei Benutzer hinzugefügt:

  • Benutzer: guest - Passwort: guest
  • Benutzer: chillispot - Passwort: chillipass

Der erste Benutzer dient später dazu, um unseren W-Lan Clients einen freien Internet Zugang zu gewähren, wenn sie einem Disclaimer zugestimmt haben. Der zweite Benutzer wird von Coova Chilli verwendet. Um die Funktionsfähigkeit zu überprüfen, kann dies mit Hilfe von radtest geschehen.

Gnome-terminal.png
spot01 ~ # /etc/init.d/freeradius restart

spot01 ~ # radtest guest guest 127.0.0.1 0 radiussecret

   Sending Access-Request of id 203 to 127.0.0.1 port 1812
	User-Name = "guest"
	User-Password = "guest"
	NAS-IP-Address = 127.0.1.1
	NAS-Port = 0
   rad_recv: Access-Accept packet from host 127.0.0.1 port 1812, id=203, length=2

Hier kann man nun erkennen, dass die Verbindung erfolgreich war. Sollte es nicht klappen, so lohnt sich der Debugaufruf mittels freeradius -XX. Dazu muss jedoch der Radius Server vorher gestoppt werden, wenn er denn laufen sollte!

Coova CHilli

Nach den Vorarbeiten, kann nun die Installation und Konfiguration von Chilli erfolgen.


Installation Chilli

Es gibt ein fertiges Paket für Debian Distributionen, welches installiert werden kann. Dazu laden wir es herunter und installieren es per dpkg:

  • Installieren
Debian-term.png
spot01 ~ # wget http://ap.coova.org/chilli/coova-chilli_1.0.12-1_i386.deb
spot01 ~ # dpkg -i coova-chilli_1.0.12-1_i386.deb


Webseite Vorarbeiten

Nun müssen ein paar Dateien und Verzeichnisse für die Webseite erstellt und mit Inhalt gefüllt werden.

  • Für die Webseite
Gnome-terminal.png
spot01 ~ # cp /etc/chilli/defaults /etc/chilli/config
spot01 ~ # mkdir -p /var/www/hotspot/uam
spot01 ~ # cp /etc/chilli/www/* /var/www/hotspot

Als erstes kopieren wir die Standard Konfigurations- Datei für Chilli um. Dann wird die Struktur für den späteren HotSpotLogin erstellt, den die Benutzer zu Gesicht bekommen werden.

Gnome-terminal.png
spot01 ~ # cd /var/www/hotspot/uam
spot01 ~ # wget http://ap.coova.org/uam/
spot01 ~ # wget http://ap.coova.org/js/chilli.js

Hier wird eine Standardseite bezogen, welche einige JavaScript Sachen bereithält, die für die spätere Session nötig werden.

Ruft ein Gast eine Webseite auf, so wird er auf die index.html in dem Verzeichnis /var/www/hotspot/uam umgeleitet, welche wiederum selbst eine Umleitung vornimmt. Diese wird ins Leere laufen, solang die dort enthaltene Adresse nicht durch die eigene ausgetauscht wird. Ein kurzer sed Aufruf löst diese Problem:

Gnome-terminal.png
spot01~ # sed -i 's/coova.org\/js\/chilli.js/10.1.0.1\/uam\/chilli.js/g' /var/www/hotspot/uam/index.html

Damit ändern wir also den Umleitung von coova.org auf die IP Adresse 10.1.0.1 (unserem Coova Chilli Spot) um. Sofern ein DNS Server bereit steht, kann das natürlich erneut ein Name sein.

Chiili Konfiguration

Damit Coova Chilli automatisch startet, bedarf es einer kleinen Anpassung:

  • /etc/default/chilli
Ascii.png
START_CHILLI=1


Als nächstes wird nun Chilli selbst konfiguriert. Dazu wieder eine von normalen Kommentaren befreite Datei:

  • /etc/chilli/config
Ascii.png
# Die Externe Netzwerkkarte zum Internet
   HS_WANIF=eth0

# Die Interne Netzwerkkarte zu den HotSpot Clients
   HS_LANIF=eth1

# Das gewünsche Netzwerk für die Hotspot Clients
   HS_NETWORK=10.1.0.0

# Die Netzwerkmaske dazu
   HS_NETMASK=255.255.255.0   # HotSpot Network Netmask

# Die IP Adresse, an der Chilli lauschen soll incl. DHCP Server. Muss zum Netz oben pssen!
   HS_UAMLISTEN=10.1.0.1

# Der Port, an dem Chilli lauscht. Auf diesen greifen die HotSpot Clients zu
   HS_UAMPORT=3990

# Der DNS Server, welcher den Clients mitgegeben wird
   HS_DNS1=10.1.0.1

# Eine ID
   HS_NASID=nas01

# Das Kennwort auf den später das CGI Login Script "hotspotlogin.cgi" zugreift
   HS_UAMSECRET=spotsecret

# Wo ist der erste Radius Server zu finden
   HS_RADIUS=localhost

# Wo ist der zweite Radius Server zu finden
   HS_RADIUS2=localhost

# Mit welchem Kennwort greifen wir zu, siehe: /etc/freeradius/clients.conf
   HS_RADSECRET=radiussecret

# Auf welche DNS/IP Adressen dürfen die HotSpot Clients zugreifen, ohne Authentifizierung!
   HS_UAMALLOW=10.1.0.0/24

# Wo befindet sich die Loginserver, auf die die Clients umgeleitet werden
   HS_UAMSERVER=10.1.0.1/cgi-bin/hotspotlogin.cgi

# Welche Seite wird aufgerufen
   HS_UAMFORMAT=https://\$HS_UAMSERVER/uam/chilli

# Was ist die Standardwebseite
   HS_UAMHOMEPAGE=http://\$HS_UAMLISTEN:\$HS_UAMPORT/www/coova.html

# Unbekannt ???
   HS_UAMSERVICE=https://10.1.0.1/uam/auth

# Soll angebelich für viele Seiten benötigt werden, die google Map eingebettet haben
   HS_USE_MAP=on

# Wenn im Radius kein Session Timeout definiert wurde, wann fliegt der Hotspot User wieder raus
   HS_DEFSESSIONTIMEOUT=900   # In Sekunden

# Wenn nichts passiert, wann fliegt der Hotspot User raus
   HS_DEFIDLETIMEOUT=900	   # In Sekunden

# Der Modus
   HS_MODE=hotspot

# Der Typ
   HS_TYPE=chillispot

# Benutzer in der Datenbank
   HS_ADMUSR=chillispot

# Passwort vom User chillispot in der Datenbank
   HS_ADMPWD=chillipass

# Das Stammverzeichnis von der Webseite
   HS_WWWDIR=/var/www/hotspot

# Die Benärdatei wwwsh
   HS_WWWBIN=/etc/chilli/wwwsh

# Freier Name für den Hotspot
   HS_LOC_NAME="KBB Spot1"	   # WISPr Location Name and used in portal

Firewall Script

Bei jedem Start von Chilli Spot und nach der Anmeldung eines HotSpot Clients, werden Aktionen ausgelöst, wie z.B. das setzen von Firewall Regeln. Darin kann bestimmt werden, welche Ports dem Benutzer zur Verfügung stehen sollen. Dieses Script kann unter dem Namen /etc/chilli/ipup.sh abgelegt werden:

  • /etc/chilli/ipup.sh
Ascii.png
#!/bin/sh
   #
   # Firewall script for ChilliSpot
   # A Wireless LAN Access Point Controller
   #
   # Uses $EXTIF (eth0) as the external interface (Internet or intranet) and
   # $INTIF (eth1) as the internal interface (access points).
   #
   #
   # SUMMARY
   # * All connections originating from chilli are allowed.
   # * Only ssh is allowed in on external interface.
   # * Nothing is allowed in on internal interface.
   # * Forwarding is allowed to and from the external interface, but disallowed
   #   to and from the internal interface.
   # * NAT is enabled on the external interface.
   
   IPTABLES="/sbin/iptables"
   EXTIF="eth0"
   INTIF="eth1"
   
   $IPTABLES -P INPUT DROP
   $IPTABLES -P FORWARD ACCEPT
   $IPTABLES -P OUTPUT ACCEPT
   
   #Allow related and established on all interfaces (input)
   $IPTABLES -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
   
   #Allow releated, established and ssh on $EXTIF. Reject everything else.
   $IPTABLES -A INPUT -i $EXTIF -p tcp -m tcp --dport 22 --syn -j ACCEPT
   $IPTABLES -A INPUT -i $EXTIF -j REJECT
   
   #Allow related and established from $INTIF. Drop everything else.
   $IPTABLES -A INPUT -i $INTIF -j DROP
   
   #Allow http and https on other interfaces (input).
   #This is only needed if authentication server is on same server as chilli
   $IPTABLES -A INPUT -p tcp -m tcp --dport 80 --syn -j ACCEPT
   $IPTABLES -A INPUT -p tcp -m tcp --dport 443 --syn -j ACCEPT
   
   #Allow 3990 on other interfaces (input).
   $IPTABLES -A INPUT -p tcp -m tcp --dport 3990 --syn -j ACCEPT
   
   #Allow everything on loopback interface.
   $IPTABLES -A INPUT -i lo -j ACCEPT
   
   # Drop everything to and from $INTIF (forward)
   # This means that access points can only be managed from ChilliSpot
   $IPTABLES -A FORWARD -i $INTIF -j DROP
   $IPTABLES -A FORWARD -o $INTIF -j DROP
   
   #Enable NAT on output device
   $IPTABLES -t nat -A POSTROUTING -o $EXTIF -j MASQUERADE

Das Script muss natürlich ausführbar sein:

Gnome-terminal.png
spot01 ~ # chmod +x /etc/chilli/ipup.sh

Apache

Nun folgt die Apache2 Konfiguration. Zum einen benötigen wir einen Virtual Host der CGI Dateien ausführen darf, zum anderen soll er über SSL arbeiten.


Vorarbeit

Wir erzeugen ein CGI Verzeichnis und kopieren eine Beispiel hotspotlogin.cg hinein:

Gnome-terminal.png
spot01 ~ # mkdir -p /var/www/hotspot/cgi-bin
spot01 ~ # zcat /usr/share/doc/coova-chilli/hotspotlogin.cgi.gz > /var/www/hotspot/cgi-bin/hotspotlogin.cgi
spot01 ~ # chmod a+x /var/www/hotspot/cgi-bin/hotspotlogin.cgi

Damit die CGI Datei hotspotlogin.cgi mit dem Chilli Server kommunizieren kann, muss die Authentifizierung aktiviert, sowie das Passwort angegeben werden. Dazu passen wir diese Datei an

  • /var/www/hotspot/cgi-bin/hotspotlogin.cgi
Ascii.png
[...]
# Siehe /etc/chilli/config  -> HS_UAMSECRET
   $uamsecret = "spotsecret";
   $userpassword=1;
[..]

Apache SSL

Da die Datei hotspotlogin.cgi erwartet, dass der HotSpot User über eine HTTPS Adresse kommt, benötigen wir daher einen SSL aktivierten Apachen. Um das dafür nötige Zertifikat bequem zu erstellen, eignet sich das Paket ssl-cert. Mit dem richtigen Aufruf erledigt er alles dafür nötige:

Debian-term.png
spot01 ~ # apt-get install apache2 ssl-cert 
spot01 ~ # mkdir /etc/apache2/ssl
spot01 ~ # hostname -f

Die letzte Ausgabe merken, da wir sie für das Zertifikat benötigen:

Debian-term.png
spot01 ~ # make-ssl-cert /usr/share/ssl-cert/ssleay.cnf /etc/apache2/ssl/apache.pem

Bei der Frage für den CommonName bitte die Ausgabe von hostname -f eintragen.

Nun wird das SSL Modul vom Apachen noch aktiviert:

  • SSL Modul aktivieren
Debian-term.png
spot01 ~ # a2enmod ssl

Virtual Host

Nun können wir den Virtual Host erstellen und aktivieren:

  • /etc/apache2/sites-available/hotspot
Ascii.png
NameVirtualHost 10.1.0.1:443
   <VirtualHost 10.1.0.1:443>
        ServerAdmin hotpot@wireless.local
        DocumentRoot "/var/www/hotspot"
        ServerName "spot01.wireless.local"
        <Directory "/var/www/hotspot/">
                Options Indexes FollowSymLinks MultiViews
                AllowOverride None
                Order allow,deny
                allow from all
        </Directory> 
     
        Alias "/dialupadmin/" "/usr/share/freeradius-dialupadmin/htdocs/" 
        <Directory "/usr/share/freeradius-dialupadmin/htdocs/"> 
                Options Indexes FollowSymLinks MultiViews
                AllowOverride None
                Order allow,deny
                allow from all
        </Directory>
   
        ScriptAlias /cgi-bin/ /var/www/hotspot/cgi-bin/
        <Directory "/var/www/hotspot/cgi-bin/">
                AllowOverride None
                Options ExecCGI -MultiViews +SymLinksIfOwnerMatch
                Order allow,deny
                Allow from all
        </Directory>
   
        ErrorLog /var/log/apache2/hotspot-error.log   
        LogLevel warn
        CustomLog /var/log/apache2/hotspot-access.log combined
   
        ServerSignature On 
        SSLEngine on 
        SSLCertificateFile /etc/apache2/ssl/apache.pem
   </VirtualHost>
  • Virtual Host aktivieren
Debian-term.png
spot01 ~ # a2ensite hotspot
spot01 ~ # apache2ctl -t
spot01 ~ # /etc/init.d/apache2 reload

Wer möchte, kann auch noch die Hautpkonfiguration vom Apache anpasen. Anbieten würde sich z.B. der Servername:

  • /etc/apache2/apache2.conf

{{code|

   [...]
   ServerName 10.1.0.1
   [...]

Den Syntax check und ein anschließendes reload nicht vergessen.


Testen

Sind all die Arbeiten abgeschlossen worden, kann nun getestet werden. Der Autor hat hierzu alles in Vmware laufen und kann so beliebige Tests ausführen. Wichtig ist hierbei die richtige Reihenfolge der Dienste:

  1. /etc/init.d/mysql restart
  2. /etc/init.d/freeradius restart
  3. /etc/init.d/chilli restart
  4. /etc/init.d/apache2 restart

Beim start des Hotspot Clients muss dieser eine IP Adresse vom Chilli DHCP Server erhalten haben. Des weiteren wurde auch der DNS Server mitgegeben. Beim öffnen einer beliebigen Webseite vom Hotspot Client, wird die Seite umgeleitet auf die hotspotlogin.cgi Seite. Eventuell gibt es ein Warnhinweis, aufgrund des selbstsignierten SSL Zertifikat. Wurde die Login Seite geöffnet, kann nun der Benutzer "guest" und das Passwort "guest" verwendet werden. Hat alles geklappt, sollte der Zugang zum Internet nun möglich sein. Ein eigenes Fenster klärt über den Status auf.

eth1 wird zu tun0

Wird Chili gestartet, so wird die IP Adresse und der DHCP Server auf das Interface tun0 gelegt, welches in diesem Moment entsteht. Daher ist es wichtig, dass die eth1 nicht konfiguriert wird. Im gleichen Atemzug muss daher das Modul für tun vorhanden sein. Dies kann leicht mit modprobe tun festgestellt werden.

DNS Server

Sollte bisher noch kein DNS Server vorhanden sein, so eignet sich am besten ein Cachin Name Server, wie DNSMasq:

Debian-term.png
spot01 ~ # apt-get install dnsmasq

Er bedarf keiner Konfiguration mehr. Einzig in der /etc/resolv.conf sollten mindestens zwei richtige DNS Server vorhanden sein. Nach einem Neustart von dnsmasq steht er den HotSpot Clients zur Verfügung.

HotSpotLogin.cgi anpassen

Sind alle diese Arbeiten abgeschlossen, kann als nächstes die hotspotlogin.cgi Datei dahingehend angepasst werden, dass lediglich ein Disclaimer verwendet wird, dem die HotSpot Clients zustimmen müssen.

Dazu öffnen wir erneut die Datei und springen zur Zeile 387.

Ab dort befinden sich die entsprechenden Zeilen. Der Benutzername und das Kennwort werden hier abgefragt. Nun müssen wir nichts anderes unternehmen, als diese Felder zu befüllen und zu verstecken:

  • Aus diesen Zeilen ...
Ascii.png
  <center>
  <table border=\"0\" cellpadding=\"5\" cellspacing=\"0\" style=\"width: 217px;\">
    <tbody>
      <tr>
        <td align=\"right\">Username:</td>
        <td><input STYLE=\"font-family: Arial\" type=\"text\" name=\"UserName\" size=\"20\" maxlength=\"128\"></td>
      </tr>
      <tr>
        <td align=\"right\">Password:</td>
        <td><input STYLE=\"font-family: Arial\" type=\"password\" name=\"Password\" size=\"20\" maxlength=\"128\"></td>
      </tr>
      <tr>
        <td align=\"center\" colspan=\"2\" height=\"23\"><input type=\"submit\" name=\"button\" value=\"Login\" onClick=\"javascript:popUp('$loginpath?res=popup1&uamip=$uamip&uamport=$uamport')\"></td>
      </tr>
    </tbody>
  </table>
  </center>
  • Werden diese Zeilen ...
Ascii.png
  <center>
  <table border=\"0\" cellpadding=\"5\" cellspacing=\"0\" style=\"width: 217px;\">
    <tbody>
      <tr>
       <!-- <td align=\"right\">Benutzername:</td> -->
        <td><input TYPE=\"hidden\" STYLE=\"font-family: Arial\" type=\"text\" name=\"UserName\" size=\"20\" value=\"guest\" maxlength=\"128\"></td>
      </tr>
        <!-- DISCLAIMER einbinden-->
           <tr>
           Wenn sie auf \"Login\" klicken. Stimmen sie unserem Disclaimer zu!
           </tr>
        <!-- DISCLAIMER Ende -->
      <tr>
        <!-- <td align=\"right\">Passwort:</td> -->
        <td><input TYPE=\"hidden\" STYLE=\"font-family: Arial\" type=\"password\" name=\"Password\" size=\"20\" value=\"guest\" maxlength=\"128\"></td>
      </tr>
      <tr>
        <td align=\"center\" colspan=\"2\" height=\"23\">AGB akzeptieren: <input type=\"submit\" name=\"button\" value=\"Login\" onClick=\"javascript:popUp('$loginpath?res=popup1&uamip=$uamip&uamport=$uamport')\"></td>
      </tr>
    </tbody>
  </table>
  </center>

Im Zweiten Teil werden die Felder für Benutzernamen und Passwort versteckt. Natürlich ist dies nicht besonders schön, zumal Anführungszeichen maskiert werden müssen. Daher gibt es noch eine weit elegantere Lösung. wir können das Script so anpassen, dass eine externe HTML Datei eingelesen wird. Der Inhalt davon, wird an der Stelle positioniert, wo wir eine entsprechende Variable unterbringen. Dazu müssen wir erneut ein paar Zeilen hinzufügen. Dies geschieht ab der Zeile 387

[...]
if ($result == 5) {
    print "
  <h1 style=\"text-align: center;\">Hotspot Login</h1>";
}

if ($result == 2 || $result == 5) {
[...]

Zwischen der if ($result == 5) {' und der print Zeile, kommen nun folgende Zeilen:

my $inpath="/var/www/hotspot/disclaimer/disclaimer.html";
open IN,"$inpath" || die "cannot open $inpath for read\n\n";
my $disclaimer="";
while (my $l=<IN>) {
  chomp $l;
  $disclaimer="$disclaimer" . "$l";
}

Damit wird nun die Datei /var/www/hotspot/disclaimer/disclaimer.htm eingelesen. Damit sie an der passenden Stelle eingepflegt wird, kommt nun die Variable $disclaimer zum zuge.


      <tr>
       <!-- <td align=\"right\">Benutzername:</td> -->
        <td><input TYPE=\"hidden\" STYLE=\"font-family: Arial\" type=\"text\" name=\"UserName\" size=\"20\" value=\"guest\" maxlength=\"128\"></td>
      </tr>
        <!-- DISCLAIMER einbinden-->
        $disclaimer
        <!-- DISCLAIMER Ende -->
      <tr>
        <!-- <td align=\"right\">Passwort:</td> -->
        <td><input TYPE=\"hidden\" STYLE=\"font-family: Arial\" type=\"password\" name=\"Password\" size=\"20\" value=\"guest\" maxlength=\"128\"></td>
      </tr>
      <tr>

Hat alles geklappt, kann nun sehr leicht der Disclaimer ausgetauscht werden. Dabei können wieder sämtliche HTML Befehle zum Einsatz kommen. Es können nun auch Bilder etc. mit eingebunden werden.

Logging

Wer auf ein Logging angewiesen ist, der kann sehr bequem per SLQ Abfrage die dazu nötigen Tabellen abfragen. In dem nachfolgendem Beispiel werden die Zugriffe vom Benutzer "guest" abgerufen:

Gnome-terminal.png
spot01 ~ # mysql -uradius -pradiuspass radius -e 'select AcctUniqueId,acctstarttime,acctstoptime,callingstationid,FramedIPAddress from radacct where username="guest"'

Heraus kommt diese Auflistung:

+------------------+---------------------+---------------------+-------------------+-----------------+
| AcctUniqueId     | acctstarttime       | acctstoptime        | callingstationid  | FramedIPAddress |
+------------------+---------------------+---------------------+-------------------+-----------------+
| 5193b45afce960fc | 2009-03-05 16:29:59 | 2009-03-05 16:45:02 | 00-0C-29-DD-FA-E7 | 10.1.0.2        | 
| 090e966bc520bff6 | 2009-03-05 17:01:06 | NULL                | 00-0C-29-DD-FA-E7 | 10.1.0.2        | 
+------------------+---------------------+---------------------+-------------------+-----------------+
  • Aufbau
    • AcctUniqueId - Eindeutige Session ID
    • acctstarttime - Session Startzeit
    • acctstoptime - Session Endzeit
    • callingstationid - Client MAC Adresse
    • FramedIPAddress - Zugewiesene IP Adresse


Natürlich können noch weitere Tabellen abgefragt werden. Einfach die passenden heraussuchen.


Anhang

hotspotlogin.cgi

# Shared secret used to encrypt challenge with. Prevents dictionary attacks.
# You should change this to your own shared secret.
$uamsecret = "ahhie3Ju";

# Uncomment the following line if you want to use ordinary user-password
# for radius authentication. Must be used together with $uamsecret.
$userpassword=1;

# This code is horrible -- it came that way, and remains that way. A
# real open-source captive portal for coova-chilli should be built -- david

$loginpath = "/cgi-bin/hotspotlogin.cgi";

use Digest::MD5  qw(md5 md5_hex md5_base64);

# Make sure that the form parameters are clean
$OK_CHARS='-a-zA-Z0-9_.@&=%!';
$_ = $input = <STDIN>;
s/[^$OK_CHARS]/_/go;
$input = $_;

# Make sure that the get query parameters are clean
$OK_CHARS='-a-zA-Z0-9_.@&=%!';
$_ = $query=$ENV{QUERY_STRING};
s/[^$OK_CHARS]/_/go;
$query = $_;


# If she did not use https tell her that it was wrong.
if (!($ENV{HTTPS} =~ /^on$/)) {
    print "Content-type: text/html\n\n
<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">
<html>
<head>
  <title>ChilliSpot Login Failed</title>
  <meta http-equiv=\"Cache-control\" content=\"no-cache\">
  <meta http-equiv=\"Pragma\" content=\"no-cache\">
</head>
<body bgColor = '#c0d8f4'>
  <h1 style=\"text-align: center;\">HotSpot Login Failed</h1>
  <center>
    Login must use encrypted connection.
  </center>
</body>
<!--
<?xml version=\"1.0\" encoding=\"UTF-8\"?>
<WISPAccessGatewayParam 
  xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"
  xsi:noNamespaceSchemaLocation=\"http://www.acmewisp.com/WISPAccessGatewayParam.xsd\">
<AuthenticationReply>
<MessageType>120</MessageType>
<ResponseCode>102</ResponseCode>
<ReplyMessage>Login must use encrypted connection</ReplyMessage>
</AuthenticationReply> 
</WISPAccessGatewayParam>
-->
</html>
";
    exit(0);
}


#Read form parameters which we care about
@array = split('&',$input);
foreach $var ( @array )
{
    @array2 = split('=',$var);
    if ($array2[0] =~ /^username$/i) { $username = $array2[1]; }
    if ($array2[0] =~ /^password$/i) { $password = $array2[1]; }
    if ($array2[0] =~ /^challenge$/) { $challenge = $array2[1]; }
    if ($array2[0] =~ /^button$/) { $button = $array2[1]; }
    if ($array2[0] =~ /^logout$/) { $logout = $array2[1]; }
    if ($array2[0] =~ /^prelogin$/) { $prelogin = $array2[1]; }
    if ($array2[0] =~ /^res$/) { $res = $array2[1]; }
    if ($array2[0] =~ /^uamip$/) { $uamip = $array2[1]; }
    if ($array2[0] =~ /^uamport$/) { $uamport = $array2[1]; }
    if ($array2[0] =~ /^userurl$/)   { $userurl = $array2[1]; }
    if ($array2[0] =~ /^timeleft$/)  { $timeleft = $array2[1]; }
    if ($array2[0] =~ /^redirurl$/)  { $redirurl = $array2[1]; }
}

#Read query parameters which we care about
@array = split('&',$query);
foreach $var ( @array )
{
    @array2 = split('=',$var);
    if ($array2[0] =~ /^username$/i) { $username = $array2[1]; }
    if ($array2[0] =~ /^password$/i) { $password = $array2[1]; }
    if ($array2[0] =~ /^res$/)       { $res = $array2[1]; }
    if ($array2[0] =~ /^challenge$/) { $challenge = $array2[1]; }
    if ($array2[0] =~ /^uamip$/)     { $uamip = $array2[1]; }
    if ($array2[0] =~ /^uamport$/)   { $uamport = $array2[1]; }
    if ($array2[0] =~ /^reply$/)     { $reply = $array2[1]; }
    if ($array2[0] =~ /^userurl$/)   { $userurl = $array2[1]; }
    if ($array2[0] =~ /^timeleft$/)  { $timeleft = $array2[1]; }
    if ($array2[0] =~ /^redirurl$/)  { $redirurl = $array2[1]; }
}


$reply =~ s/\+/ /g;
$reply =~s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/seg;

$userurldecode = $userurl;
$userurldecode =~ s/\+/ /g;
$userurldecode =~s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/seg;

$redirurldecode = $redirurl;
$redirurldecode =~ s/\+/ /g;
$redirurldecode =~s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/seg;

$password =~ s/\+/ /g;
$password =~s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/seg;

# If attempt to login
if ($button =~ /^Login$/) {
    $hexchal  = pack "H32", $challenge;
    if (defined $uamsecret) {
	$newchal  = md5($hexchal, $uamsecret);
    }
    else {
	$newchal  = $hexchal;
    }
    $response = md5_hex("\0", $password, $newchal);
    $pappassword = unpack "H32", ($password ^ $newchal);
#sleep 5;
print "Content-type: text/html\n\n";
print "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">
<html>
<head>
  <title>ChilliSpot Login</title>
  <meta http-equiv=\"Cache-control\" content=\"no-cache\">
  <meta http-equiv=\"Pragma\" content=\"no-cache\">";
    if ((defined $uamsecret) && defined($userpassword)) {
	print "  <meta http-equiv=\"refresh\" content=\"0;url=http://$uamip:$uamport/logon?username=$username&password=$pappassword\">";
    } else {
	print "  <meta http-equiv=\"refresh\" content=\"0;url=http://$uamip:$uamport/logon?username=$username&response=$response&userurl=$userurl\">";
    }
print "</head>
<body bgColor = '#c0d8f4'>";
  print "<h1 style=\"text-align: center;\">Logging in to ChilliSpot</h1>";
  print "
  <center>
    Please wait......
  </center>
</body>
<!--
<?xml version=\"1.0\" encoding=\"UTF-8\"?>
<WISPAccessGatewayParam 
  xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"
  xsi:noNamespaceSchemaLocation=\"http://www.acmewisp.com/WISPAccessGatewayParam.xsd\">
<AuthenticationReply>
<MessageType>120</MessageType>
<ResponseCode>201</ResponseCode>
";
    if ((defined $uamsecret) && defined($userpassword)) {
	print "<LoginResultsURL>http://$uamip:$uamport/logon?username=$username&password=$pappassword</LoginResultsURL>";
    } else {
	print "<LoginResultsURL>http://$uamip:$uamport/logon?username=$username&response=$response&userurl=$userurl</LoginResultsURL>";
    }
print "</AuthenticationReply> 
</WISPAccessGatewayParam>
-->
</html>
";
    exit(0);
}


# Default: It was not a form request
$result = 0;

# If login successful
if ($res =~ /^success$/) { 
    $result = 1;
}

# If login failed 
if ($res =~ /^failed$/) { 
    $result = 2;
}

# If logout successful
if ($res =~ /^logoff$/) { 
    $result = 3;
}

# If tried to login while already logged in
if ($res =~ /^already$/) { 
    $result = 4;
}

# If not logged in yet
if ($res =~ /^notyet$/) { 
    $result = 5;
}

# If login from smart client
if ($res =~ /^smartclient$/) { 
    $result = 6;
}

# If requested a logging in pop up window
if ($res =~ /^popup1$/) { 
    $result = 11;
}

# If requested a success pop up window
if ($res =~ /^popup2$/) { 
    $result = 12;
}

# If requested a logout pop up window
if ($res =~ /^popup3$/) { 
    $result = 13;
}


# Otherwise it was not a form request
# Send out an error message
if ($result == 0) {
    print "Content-type: text/html\n\n
<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">
<html>
<head>
  <title>HostSpot Login fehlgeschlagen</title>
  <meta http-equiv=\"Cache-control\" content=\"no-cache\">
  <meta http-equiv=\"Pragma\" content=\"no-cache\">
</head>
<body bgColor = '#c0d8f4'>
  <h1 style=\"text-align: center;\">ChilliSpot Login Failed</h1>
  <center>
    Login must be performed through ChilliSpot daemon.
  </center>
</body>
</html>
";
    exit(0);
}

#Generate the output
print "Content-type: text/html\n\n
<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">
<html>
<head>
  <title>HotSpot Login</title>
  <meta http-equiv=\"Cache-control\" content=\"no-cache\">
  <meta http-equiv=\"Pragma\" content=\"no-cache\">
  <SCRIPT LANGUAGE=\"JavaScript\">
    var blur = 0;
    var starttime = new Date();
    var startclock = starttime.getTime();
    var mytimeleft = 0;

    function doTime() {
      window.setTimeout( \"doTime()\", 1000 );
      t = new Date();
      time = Math.round((t.getTime() - starttime.getTime())/1000);
      if (mytimeleft) {
        time = mytimeleft - time;
        if (time <= 0) {
          window.location = \"$loginpath?res=popup3&uamip=$uamip&uamport=$uamport\";
        }
      }
      if (time < 0) time = 0;
      hours = (time - (time % 3600)) / 3600;
      time = time - (hours * 3600);
      mins = (time - (time % 60)) / 60;
      secs = time - (mins * 60);
      if (hours < 10) hours = \"0\" + hours;
      if (mins < 10) mins = \"0\" + mins;
      if (secs < 10) secs = \"0\" + secs;
      title = \"Online time: \" + hours + \":\" + mins + \":\" + secs;
      if (mytimeleft) {
        title = \"Remaining time: \" + hours + \":\" + mins + \":\" + secs;
      }
      if(document.all || document.getElementById){
         document.title = title;
      }
      else {   
        self.status = title;
      }
    }

    function popUp(URL) {
      if (self.name != \"chillispot_popup\") {
        chillispot_popup = window.open(URL, 'chillispot_popup', 'toolbar=0,scrollbars=0,location=0,statusbar=0,menubar=0,resizable=0,width=500,height=375');
      }
    }

    function doOnLoad(result, URL, userurl, redirurl, timeleft) {
      if (timeleft) {
        mytimeleft = timeleft;
      }
      if ((result == 1) && (self.name == \"chillispot_popup\")) {
        doTime();
      }
      if ((result == 1) && (self.name != \"chillispot_popup\")) {
        chillispot_popup = window.open(URL, 'chillispot_popup', 'toolbar=0,scrollbars=0,location=0,statusbar=0,menubar=0,resizable=0,width=500,height=375');
      }
      if ((result == 2) || result == 5) {
        document.form1.UserName.focus()
      }
      if ((result == 2) && (self.name != \"chillispot_popup\")) {
        chillispot_popup = window.open('', 'chillispot_popup', 'toolbar=0,scrollbars=0,location=0,statusbar=0,menubar=0,resizable=0,width=400,height=200');
        chillispot_popup.close();
      }
      if ((result == 12) && (self.name == \"chillispot_popup\")) {
        doTime();
        if (redirurl) {
          opener.location = redirurl;
        }
        else if (opener.home) {
          opener.home();
        }
        else {
          opener.location = \"about:home\";
        }
        self.focus();
        blur = 0;
      }
      if ((result == 13) && (self.name == \"chillispot_popup\")) {
        self.focus();
        blur = 1;
      }
    }

    function doOnBlur(result) {
      if ((result == 12) && (self.name == \"chillispot_popup\")) {
        if (blur == 0) {
          blur = 1;
          self.focus();
        }
      }
    }
  </script>
</head>
<body onLoad=\"javascript:doOnLoad($result, '$loginpath?res=popup2&uamip=$uamip&uamport=$uamport&userurl=$userurl&redirurl=$redirurl&timeleft=$timeleft','$userurldecode', '$redirurldecode', '$timeleft')\" onBlur = \"javascript:doOnBlur($result)\" bgColor = '#c0d8f4'>";


#      if (!window.opener) {
#        document.bgColor = '#c0d8f4';
#      }

#print "THE INPUT: $input";
#foreach $key (sort (keys %ENV)) {
#	print $key, ' = ', $ENV{$key}, "<br>\n";
#}

if ($result == 2) {
    print "
  <h1 style=\"text-align: center;\">HotSpot Login fehlgeschlagen</h1>";
    if ($reply) {
	print "<center> $reply </BR></BR></center>";
    }
}

if ($result == 5) {
    print " 
  <h1 style=\"text-align: center;\">Hotspot Login</h1>";
}

if ($result == 2 || $result == 5) {

my $inpath="/var/www/hotspot/disclaimer/disclaimer.html";
open IN,"$inpath" || die "cannot open $inpath for read\n\n";
my $disclaimer="";
while (my $l=<IN>) {
  chomp $l;
  $disclaimer="$disclaimer" . "$l";
}


  print "
  <form name=\"form1\" method=\"post\" action=\"$loginpath\">
  <INPUT TYPE=\"hidden\" NAME=\"challenge\" VALUE=\"$challenge\">
  <INPUT TYPE=\"hidden\" NAME=\"uamip\" VALUE=\"$uamip\">
  <INPUT TYPE=\"hidden\" NAME=\"uamport\" VALUE=\"$uamport\">
  <INPUT TYPE=\"hidden\" NAME=\"userurl\" VALUE=\"$userurl\">
<!--#include virtual=\"index.shtml\"-->

  <center>
  <table border=\"0\" cellpadding=\"5\" cellspacing=\"0\" style=\"width: 217px;\">
    <tbody>
      <tr>
       <!-- <td align=\"right\">Benutzername:</td> -->
        <td><input TYPE=\"hidden\" STYLE=\"font-family: Arial\" type=\"text\" name=\"UserName\" size=\"20\" value=\"guest\" maxlength=\"128\"></td>
      </tr>
	<!-- DISCLAIMER einbinden-->
	$disclaimer
	<!-- DISCLAIMER Ende -->
      <tr>
        <!-- <td align=\"right\">Passwort:</td> -->
        <td><input TYPE=\"hidden\" STYLE=\"font-family: Arial\" type=\"password\" name=\"Password\" size=\"20\" value=\"guest\" maxlength=\"128\"></td>
      </tr>
      <tr>
        <td align=\"center\" colspan=\"2\" height=\"23\">AGB akzeptieren: <input type=\"submit\" name=\"button\" value=\"Login\" onClick=\"javascript:popUp('$loginpath?res=popup1&uamip=$uamip&uamport=$uamport')\"></td> 
      </tr>
    </tbody>
  </table>
  </center>
  </form>
</body>
</html>";
}

if ($result == 1) {
  print "
  <h1 style=\"text-align: center;\">Logged in to ChilliSpot</h1>";

  if ($reply) { 
      print "<center> $reply </BR></BR></center>";
  }
  print "
  <center>
    <a href=\"http://$uamip:$uamport/logoff\">Logout</a>
  </center>
</body>
</html>";
}

if (($result == 4) || ($result == 12)) {
  print "
  <h1 style=\"text-align: center;\">Logged in to ChilliSpot</h1>
  <center>
    <a href=\"http://$uamip:$uamport/logoff\">Logout</a>
  </center>
</body>
</html>";
}


if ($result == 11) {
  print "<h1 style=\"text-align: center;\">Logging in to ChilliSpot</h1>";
  print "
  <center>
    Please wait......
  </center>
</body>
</html>";
}


if (($result == 3) || ($result == 13)) {
    print "
  <h1 style=\"text-align: center;\">Logged out from ChilliSpot</h1>
  <center>
    <a href=\"http://$uamip:$uamport/prelogin\">Login</a>
  </center>
</body>
</html>";
}

exit(0);


Quellen


--Denny 22:12, 11. Mär. 2009 (UTC)