Skip to content

Instantly share code, notes, and snippets.

@tuzhucheng
Last active April 7, 2022 12:42
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save tuzhucheng/b99cdab71c28d92dd1358e11d6af9f5e to your computer and use it in GitHub Desktop.
Save tuzhucheng/b99cdab71c28d92dd1358e11d6af9f5e to your computer and use it in GitHub Desktop.
Setup eduroam on RPi
#!/usr/bin/env bash
# script obtained from https://cat.eduroam.org/
if [ -z "$BASH" ] ; then
bash $0
exit
fi
my_name=$0
function setup_environment {
bf=""
n=""
ORGANISATION="University of Waterloo"
URL="https://uwaterloo.ca/information-systems-technology/services/service-desk-ec2-ist"
SUPPORT="helpdesk@uwaterloo.ca"
if [ ! -z "$DISPLAY" ] ; then
if which zenity 1>/dev/null 2>&1 ; then
ZENITY=`which zenity`
elif which kdialog 1>/dev/null 2>&1 ; then
KDIALOG=`which kdialog`
else
if tty > /dev/null 2>&1 ; then
if echo $TERM | grep -E -q "xterm|gnome-terminal|lxterminal" ; then
bf="";
n="";
fi
else
find_xterm
if [ -n "$XT" ] ; then
$XT -e $my_name
fi
fi
fi
fi
}
function split_line {
echo $1 | awk -F '\\\\n' 'END { for(i=1; i <= NF; i++) print $i }'
}
function find_xterm {
terms="xterm aterm wterm lxterminal rxvt gnome-terminal konsole"
for t in $terms
do
if which $t > /dev/null 2>&1 ; then
XT=$t
break
fi
done
}
function ask {
T="eduroam CAT"
# if ! [ -z "$3" ] ; then
# T="$T: $3"
# fi
if [ ! -z $KDIALOG ] ; then
if $KDIALOG --yesno "${1}\n${2}?" --title "$T" ; then
return 0
else
return 1
fi
fi
if [ ! -z $ZENITY ] ; then
text=`echo "${1}" | fmt -w60`
if $ZENITY --no-wrap --question --text="${text}\n${2}?" --title="$T" 2>/dev/null ; then
return 0
else
return 1
fi
fi
yes=Y
no=N
yes1=`echo $yes | awk '{ print toupper($0) }'`
no1=`echo $no | awk '{ print toupper($0) }'`
if [ $3 == "0" ]; then
def=$yes
else
def=$no
fi
echo "";
while true
do
split_line "$1"
read -p "${bf}$2 ${yes}/${no}? [${def}]:$n " answer
if [ -z "$answer" ] ; then
answer=${def}
fi
answer=`echo $answer | awk '{ print toupper($0) }'`
case "$answer" in
${yes1})
return 0
;;
${no1})
return 1
;;
esac
done
}
function alert {
if [ ! -z $KDIALOG ] ; then
$KDIALOG --sorry "${1}"
return
fi
if [ ! -z $ZENITY ] ; then
$ZENITY --warning --text="$1" 2>/dev/null
return
fi
echo "$1"
}
function show_info {
if [ ! -z $KDIALOG ] ; then
$KDIALOG --msgbox "${1}"
return
fi
if [ ! -z $ZENITY ] ; then
$ZENITY --info --width=500 --text="$1" 2>/dev/null
return
fi
split_line "$1"
}
function confirm_exit {
if [ ! -z $KDIALOG ] ; then
if $KDIALOG --yesno "Really quit?" ; then
exit 1
fi
fi
if [ ! -z $ZENITY ] ; then
if $ZENITY --question --text="Really quit?" 2>/dev/null ; then
exit 1
fi
fi
}
function prompt_nonempty_string {
prompt=$2
if [ ! -z $ZENITY ] ; then
if [ $1 -eq 0 ] ; then
H="--hide-text "
fi
if ! [ -z "$3" ] ; then
D="--entry-text=$3"
fi
elif [ ! -z $KDIALOG ] ; then
if [ $1 -eq 0 ] ; then
H="--password"
else
H="--inputbox"
fi
fi
out_s="";
if [ ! -z $ZENITY ] ; then
while [ ! "$out_s" ] ; do
out_s=`$ZENITY --entry --width=300 $H $D --text "$prompt" 2>/dev/null`
if [ $? -ne 0 ] ; then
confirm_exit
fi
done
elif [ ! -z $KDIALOG ] ; then
while [ ! "$out_s" ] ; do
out_s=`$KDIALOG $H "$prompt" "$3"`
if [ $? -ne 0 ] ; then
confirm_exit
fi
done
else
while [ ! "$out_s" ] ; do
read -p "${prompt}: " out_s
done
fi
echo "$out_s";
}
function user_cred {
PASSWORD="a"
PASSWORD1="b"
if ! USER_NAME=`prompt_nonempty_string 1 "enter your userid"` ; then
exit 1
fi
while [ "$PASSWORD" != "$PASSWORD1" ]
do
if ! PASSWORD=`prompt_nonempty_string 0 "enter your password"` ; then
exit 1
fi
if ! PASSWORD1=`prompt_nonempty_string 0 "repeat your password"` ; then
exit 1
fi
if [ "$PASSWORD" != "$PASSWORD1" ] ; then
alert "passwords do not match"
fi
done
}
setup_environment
show_info "This installer has been prepared for ${ORGANISATION}\n\nMore information and comments:\n\nEMAIL: ${SUPPORT}\nWWW: ${URL}\n\nInstaller created with software from the GEANT project."
if ! ask "This installer will only work properly if you are a member of ${bf}University of Waterloo.${n}" "Continue" 1 ; then exit; fi
if [ -d $HOME/.cat_installer ] ; then
if ! ask "Directory $HOME/.cat_installer exists; some of its files may be overwritten." "Continue" 1 ; then exit; fi
else
mkdir $HOME/.cat_installer
fi
# save certificates
echo "-----BEGIN CERTIFICATE-----
MIIDdTCCAl2gAwIBAgILBAAAAAABFUtaw5QwDQYJKoZIhvcNAQEFBQAwVzELMAkG
A1UEBhMCQkUxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExEDAOBgNVBAsTB1Jv
b3QgQ0ExGzAZBgNVBAMTEkdsb2JhbFNpZ24gUm9vdCBDQTAeFw05ODA5MDExMjAw
MDBaFw0yODAxMjgxMjAwMDBaMFcxCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9i
YWxTaWduIG52LXNhMRAwDgYDVQQLEwdSb290IENBMRswGQYDVQQDExJHbG9iYWxT
aWduIFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDaDuaZ
jc6j40+Kfvvxi4Mla+pIH/EqsLmVEQS98GPR4mdmzxzdzxtIK+6NiY6arymAZavp
xy0Sy6scTHAHoT0KMM0VjU/43dSMUBUc71DuxC73/OlS8pF94G3VNTCOXkNz8kHp
1Wrjsok6Vjk4bwY8iGlbKk3Fp1S4bInMm/k8yuX9ifUSPJJ4ltbcdG6TRGHRjcdG
snUOhugZitVtbNV4FpWi6cgKOOvyJBNPc1STE4U6G7weNLWLBYy5d4ux2x8gkasJ
U26Qzns3dLlwR5EiUWMWea6xrkEmCMgZK9FGqkjWZCrXgzT/LCrBbBlDSgeF59N8
9iFo7+ryUp9/k5DPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8E
BTADAQH/MB0GA1UdDgQWBBRge2YaRQ2XyolQL30EzTSo//z9SzANBgkqhkiG9w0B
AQUFAAOCAQEA1nPnfE920I2/7LqivjTFKDK1fPxsnCwrvQmeU79rXqoRSLblCKOz
yj1hTdNGCbM+w6DjY1Ub8rrvrTnhQ7k4o+YviiY776BQVvnGCv04zcQLcFGUl5gE
38NflNUVyRRBnMRddWQVDf9VMOyGj/8N7yy5Y0b2qvzfvGn9LhJIZJrglfCm7ymP
AbEVtQwdpf5pLGkkeB6zpxxxYu7KyJesF12KwvhHhm4qxFYxldBniYUr+WymXUad
DKqC5JlR3XC321Y9YeRq4VzW9v493kHMB65jUr9TU/Qr6cf9tveCX4XSQRjbgbME
HMUfpIBvFSDJ3gyICh3WZlXi/EjJKSZp4A==
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIEaTCCA1GgAwIBAgILBAAAAAABRE7wQkcwDQYJKoZIhvcNAQELBQAwVzELMAkG
A1UEBhMCQkUxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExEDAOBgNVBAsTB1Jv
b3QgQ0ExGzAZBgNVBAMTEkdsb2JhbFNpZ24gUm9vdCBDQTAeFw0xNDAyMjAxMDAw
MDBaFw0yNDAyMjAxMDAwMDBaMGYxCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9i
YWxTaWduIG52LXNhMTwwOgYDVQQDEzNHbG9iYWxTaWduIE9yZ2FuaXphdGlvbiBW
YWxpZGF0aW9uIENBIC0gU0hBMjU2IC0gRzIwggEiMA0GCSqGSIb3DQEBAQUAA4IB
DwAwggEKAoIBAQDHDmw/I5N/zHClnSDDDlM/fsBOwphJykfVI+8DNIV0yKMCLkZc
C33JiJ1Pi/D4nGyMVTXbv/Kz6vvjVudKRtkTIso21ZvBqOOWQ5PyDLzm+ebomchj
SHh/VzZpGhkdWtHUfcKc1H/hgBKueuqI6lfYygoKOhJJomIZeg0k9zfrtHOSewUj
mxK1zusp36QUArkBpdSmnENkiN74fv7j9R7l/tyjqORmMdlMJekYuYlZCa7pnRxt
Nw9KHjUgKOKv1CGLAcRFrW4rY6uSa2EKTSDtc7p8zv4WtdufgPDWi2zZCHlKT3hl
2pK8vjX5s8T5J4BO/5ZS5gIg4Qdz6V0rvbLxAgMBAAGjggElMIIBITAOBgNVHQ8B
Af8EBAMCAQYwEgYDVR0TAQH/BAgwBgEB/wIBADAdBgNVHQ4EFgQUlt5h8b0cFilT
HMDMfTuDAEDmGnwwRwYDVR0gBEAwPjA8BgRVHSAAMDQwMgYIKwYBBQUHAgEWJmh0
dHBzOi8vd3d3Lmdsb2JhbHNpZ24uY29tL3JlcG9zaXRvcnkvMDMGA1UdHwQsMCow
KKAmoCSGImh0dHA6Ly9jcmwuZ2xvYmFsc2lnbi5uZXQvcm9vdC5jcmwwPQYIKwYB
BQUHAQEEMTAvMC0GCCsGAQUFBzABhiFodHRwOi8vb2NzcC5nbG9iYWxzaWduLmNv
bS9yb290cjEwHwYDVR0jBBgwFoAUYHtmGkUNl8qJUC99BM00qP/8/UswDQYJKoZI
hvcNAQELBQADggEBAEYq7l69rgFgNzERhnF0tkZJyBAW/i9iIxerH4f4gu3K3w4s
32R1juUYcqeMOovJrKV3UPfvnqTgoI8UV6MqX+x+bRDmuo2wCId2Dkyy2VG7EQLy
XN0cvfNVlg/UBsD84iOKJHDTu/B5GqdhcIOKrwbFINihY9Bsrk8y1658GEV1BSl3
30JAZGSGvip2CTFvHST0mdCF/vIhCPnG9vHQWe3WVjwIKANnuvD58ZAWR65n5ryA
SOlCdjSXVWkkDoPWoC209fN5ikkodBpBocLTJIg1MGCUF7ThBCIxPTsvFwayuJ2G
K1pp74P1S8SqtCr4fKGxhZSM9AyHDPSsQPhZSZg=
-----END CERTIFICATE-----
" > $HOME/.cat_installer/ca.pem
function run_python_script {
PASSWORD=$( echo "$PASSWORD" | sed "s/'/\\\'/g" )
if python << EEE1 > /dev/null 2>&1
import dbus
EEE1
then
PYTHON=python
elif python3 << EEE2 > /dev/null 2>&1
import dbus
EEE2
then
PYTHON=python3
else
PYTHON=none
return 1
fi
$PYTHON << EOF > /dev/null 2>&1
#-*- coding: utf-8 -*-
import dbus
import re
import sys
import uuid
import os
class EduroamNMConfigTool:
def connect_to_NM(self):
#connect to DBus
try:
self.bus = dbus.SystemBus()
except dbus.exceptions.DBusException:
print("Can't connect to DBus")
sys.exit(2)
#main service name
self.system_service_name = "org.freedesktop.NetworkManager"
#check NM version
self.check_nm_version()
if self.nm_version == "0.9" or self.nm_version == "1.0":
self.settings_service_name = self.system_service_name
self.connection_interface_name = "org.freedesktop.NetworkManager.Settings.Connection"
#settings proxy
sysproxy = self.bus.get_object(self.settings_service_name, "/org/freedesktop/NetworkManager/Settings")
#settings intrface
self.settings = dbus.Interface(sysproxy, "org.freedesktop.NetworkManager.Settings")
elif self.nm_version == "0.8":
#self.settings_service_name = "org.freedesktop.NetworkManagerUserSettings"
self.settings_service_name = "org.freedesktop.NetworkManager"
self.connection_interface_name = "org.freedesktop.NetworkManagerSettings.Connection"
#settings proxy
sysproxy = self.bus.get_object(self.settings_service_name, "/org/freedesktop/NetworkManagerSettings")
#settings intrface
self.settings = dbus.Interface(sysproxy, "org.freedesktop.NetworkManagerSettings")
else:
print("This Network Manager version is not supported")
sys.exit(2)
def check_opts(self):
self.cacert_file = '${HOME}/.cat_installer/ca.pem'
self.pfx_file = '${HOME}/.cat_installer/user.p12'
if not os.path.isfile(self.cacert_file):
print("Certificate file not found, looks like a CAT error")
sys.exit(2)
def check_nm_version(self):
try:
proxy = self.bus.get_object(self.system_service_name, "/org/freedesktop/NetworkManager")
props = dbus.Interface(proxy, "org.freedesktop.DBus.Properties")
version = props.Get("org.freedesktop.NetworkManager", "Version")
except dbus.exceptions.DBusException:
version = "0.8"
if re.match(r'^1\.', version):
self.nm_version = "1.0"
return
if re.match(r'^0\.9', version):
self.nm_version = "0.9"
return
if re.match(r'^0\.8', version):
self.nm_version = "0.8"
return
else:
self.nm_version = "Unknown version"
return
def byte_to_string(self, barray):
return "".join([chr(x) for x in barray])
def delete_existing_connections(self, ssid):
"checks and deletes earlier connections"
try:
conns = self.settings.ListConnections()
except dbus.exceptions.DBusException:
print("DBus connection problem, a sudo might help")
exit(3)
for each in conns:
con_proxy = self.bus.get_object(self.system_service_name, each)
connection = dbus.Interface(con_proxy, "org.freedesktop.NetworkManager.Settings.Connection")
try:
connection_settings = connection.GetSettings()
if connection_settings['connection']['type'] == '802-11-wireless':
conn_ssid = self.byte_to_string(connection_settings['802-11-wireless']['ssid'])
if conn_ssid == ssid:
connection.Delete()
except dbus.exceptions.DBusException:
pass
def add_connection(self,ssid):
server_alt_subject_name_list = dbus.Array({'DNS:eduroam.uwaterloo.ca'})
server_name = 'eduroam.uwaterloo.ca'
if self.nm_version == "0.9" or self.nm_version == "1.0":
match_key = 'altsubject-matches'
match_value = server_alt_subject_name_list
else:
match_key = 'subject-match'
match_value = server_name
s_con = dbus.Dictionary({
'type': '802-11-wireless',
'uuid': str(uuid.uuid4()),
'permissions': ['user:$USER'],
'id': ssid
})
s_wifi = dbus.Dictionary({
'ssid': dbus.ByteArray(ssid.encode('utf8')),
'security': '802-11-wireless-security'
})
s_wsec = dbus.Dictionary({
'key-mgmt': 'wpa-eap',
'proto': ['rsn',],
'pairwise': ['ccmp',],
'group': ['ccmp', 'tkip']
})
s_8021x = dbus.Dictionary({
'eap': ['peap'],
'identity': '$USER_NAME',
'ca-cert': dbus.ByteArray("file://{0}\0".format(self.cacert_file).encode('utf8')),
match_key: match_value,
'password': '$PASSWORD',
'phase2-auth': 'mschapv2',
})
s_ip4 = dbus.Dictionary({'method': 'auto'})
s_ip6 = dbus.Dictionary({'method': 'auto'})
con = dbus.Dictionary({
'connection': s_con,
'802-11-wireless': s_wifi,
'802-11-wireless-security': s_wsec,
'802-1x': s_8021x,
'ipv4': s_ip4,
'ipv6': s_ip6
})
self.settings.AddConnection(con)
def main(self):
self.check_opts()
ver = self.connect_to_NM()
self.delete_existing_connections('eduroam')
self.add_connection('eduroam')
if __name__ == "__main__":
ENMCT = EduroamNMConfigTool()
ENMCT.main()
EOF
}
function create_wpa_conf {
cat << EOFW >> $HOME/.cat_installer/cat_installer.conf
network={
ssid="eduroam"
key_mgmt=WPA-EAP
pairwise=CCMP
group=CCMP TKIP
eap=PEAP
ca_cert="${HOME}/.cat_installer/ca.pem"
identity="${USER_NAME}"
domain_suffix_match="eduroam.uwaterloo.ca"
phase2="auth=MSCHAPV2"
password="${PASSWORD}"
}
EOFW
chmod 600 $HOME/.cat_installer/cat_installer.conf
}
#prompt user for credentials
user_cred
if run_python_script ; then
show_info "Installation successful"
else
show_info "Network Manager configuration failed, generating wpa_supplicant.conf"
if ! ask "Network Manager configuration failed, but we may generate a wpa_supplicant configuration file if you wish. Be warned that your connection password will be saved in this file as clear text." "Write the file" 1 ; then exit ; fi
if [ -f $HOME/.cat_installer/cat_installer.conf ] ; then
if ! ask "File $HOME/.cat_installer/cat_installer.conf exists; it will be overwritten." "Continue" 1 ; then confirm_exit; fi
rm $HOME/.cat_installer/cat_installer.conf
fi
create_wpa_conf
show_info "Output written to $HOME/.cat_installer/cat_installer.conf"
fi

Wi-Fi with eduroam

First, ensure there are no conflicting wpa_supplicant processes running. If there are, ps aux | grep supplicant and kill the processes.

Run the eduroam-linux-UoW.sh script to create the wpa_supplicant config file and a CA key. For me, my file is at /home/pi/.cat_installer/cat_installer.conf.

Use userid@uwaterloo.ca as username. When this file is created, your password is stored in plaintext, which is undesirable. Convert it to a hash using this: echo -n <my_password_here> | iconv -t utf16le | openssl md4. Use the hash returned as the password instead. Your config file should look something like this:

network={
  ssid="eduroam"
  key_mgmt=WPA-EAP
  pairwise=CCMP
  group=CCMP TKIP
  eap=PEAP
  ca_cert="/home/pi/.cat_installer/ca.pem"
  identity="userid@uwaterloo.ca"
  domain_suffix_match="eduroam.uwaterloo.ca"
  phase2="auth=MSCHAPV2"
  password=hash:0012345671489a1234c9b20d4c1234fe
}

For example:

sudo wpa_supplicant -B -d -i wlan0 -c /home/pi/.cat_installer/cat_installer.conf

Wait a few seconds and see if you can connect!

You can copy the config into /etc/wpa_supplicant/wpa_supplicant.conf to group it together with other network configs so wpa_supplicant can automatically connect at startup.

Hotspot

Most of the instructions I found online are out-of-date and misleading. Here are the instructions tested on Raspbian Stretch: goo.gl/xFprM3 up until before the "Using the Raspberry Pi as an access point to share an internet connection" section.

Here is a sample configuration:

/etc/dhcpcd.conf

interface wlan1
    static ip_address=192.168.44.1/24

Do NOT change /etc/network/interfaces. Static IP addresses are no longer specified in there. Instructions online tell you to change it but that's for older version of Raspbian.

Unfortunately wpa_supplicant races with hostapd and can take both wireless interfaces and connect to Wi-Fi. Current a wordaround is to kill the second wpa_supplicant process and then run hostapd again, e.g. sudo hostapd -d /etc/hostapd/hostapd.conf in foreground to debug.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment