# #
###############################################################################
-WIRELESS_NETWORK_CONFIG_SETTINGS="ENCRYPTION_MODE PRIORITY PSK SSID"
+WIRELESS_NETWORK_SUPPORTED_PSK_MODES="WPA2-PSK-SHA256 WPA2-PSK WPA-PSK-SHA256 WPA-PSK"
+
+WIRELESS_NETWORK_SUPPORTED_MODES="${WIRELESS_NETWORK_SUPPORTED_PSK_MODES} \
+ 802.1X WPA-EAP NONE"
+
+WIRELESS_NETWORK_CONFIG_SETTINGS="ANONYMOUS_IDENTITY EAP_MODES HIDDEN \
+ IDENTITY MODES PASSWORD PRIORITY PSK SSID"
cli_wireless_network() {
case "${1}" in
return ${EXIT_ERROR}
fi
+ # Convert SSID into usable format
+ local handle="$(wireless_network_hash "${ssid}")"
+
case "${key}" in
- encryption_mode|pre_shared_key|priority)
- wireless_network_${key} "${ssid}" "$@"
+ modes|pre_shared_key|priority)
+ wireless_network_${key} "${handle}" "$@"
;;
show)
- wireless_network_show "${ssid}"
+ wireless_network_show "${handle}"
exit $?
;;
*)
local handle
for handle in $(wireless_network_list); do
local ${WIRELESS_NETWORK_CONFIG_SETTINGS}
- if ! wireless_network_read_config_by_handle "${handle}"; then
+ if ! wireless_network_read_config "${handle}"; then
continue
fi
wireless_network_write_config() {
assert [ $# -ge 1 ]
- local ssid="${1}"
-
- local ssid_hash="$(wireless_network_hash "${ssid}")"
- assert isset ssid_hash
-
- if ! wireless_network_exists "${ssid}"; then
- log ERROR "No such wireless network: '${ssid}'"
- return ${EXIT_ERROR}
- fi
+ local handle="${1}"
- local path="${NETWORK_WIRELESS_NETWORKS_DIR}/${ssid_hash}/settings"
+ local path="${NETWORK_WIRELESS_NETWORKS_DIR}/${handle}/settings"
if ! settings_write "${path}" ${WIRELESS_NETWORK_CONFIG_SETTINGS}; then
- log ERROR "Could not write configuration settings for wireless network ${ssid}"
+ log ERROR "Could not write configuration"
return ${EXIT_ERROR}
fi
wireless_network_write_config_key() {
assert [ $# -ge 3 ]
- local ssid="${1}"
+ local handle="${1}"
local key="${2}"
shift 2
local value="$@"
- if ! wireless_network_exists "${ssid}"; then
- log ERROR "No such wireless network: ${ssid}"
- return ${EXIT_ERROR}
- fi
-
- log DEBUG "Set '${key}' to new value '${value}' in wireless network '${ssid}'"
-
local ${WIRELESS_NETWORK_CONFIG_SETTINGS}
# Read the config settings
- if ! wireless_network_read_config "${ssid}"; then
+ if ! wireless_network_read_config "${handle}"; then
return ${EXIT_ERROR}
fi
+ log DEBUG "Set '${key}' to new value '${value}' in wireless network '${SSID}'"
+
# Set the key to a new value
assign "${key}" "${value}"
- if ! wireless_network_write_config "${ssid}"; then
+ if ! wireless_network_write_config "${handle}"; then
return ${EXIT_ERROR}
fi
return ${EXIT_OK}
}
-wireless_network_read_config() {
- local ssid="${1}"
-
- if ! wireless_network_exists "${ssid}"; then
- log ERROR "No such wireless network : ${ssid}"
- return ${EXIT_ERROR}
- fi
-
- local handle="$(wireless_network_hash "${ssid}")"
- wireless_network_read_config_by_handle "${handle}"
-}
-
# Reads one or more keys out of a settings file or all if no key is provided.
-wireless_network_read_config_by_handle() {
+wireless_network_read_config() {
assert [ $# -ge 1 ]
local handle="${1}"
# This function checks if a wireless network exists
# Returns True when yes and false when not
wireless_network_exists() {
- assert [ $# -eq 1 ]
-
local ssid="${1}"
- local ssid_hash="$(wireless_network_hash "${ssid}")"
- assert isset ssid_hash
- local path="${NETWORK_WIRELESS_NETWORKS_DIR}/${ssid_hash}"
+ local handle="$(wireless_network_hash "${ssid}")"
+ assert isset handle
# We cannot use wireless_network_read_config here beacuse we would end in a loop
local SSID
-
- local path_settings="${NETWORK_WIRELESS_NETWORKS_DIR}/${ssid_hash}/settings"
-
- if ! settings_read "${path_settings}" SSID; then
+ if ! settings_read "${NETWORK_WIRELESS_NETWORKS_DIR}/${handle}/settings" SSID; then
return ${EXIT_FALSE}
fi
- assert isset SSID
-
- if [ -d "${path}" ] && [[ "${ssid}" = "${SSID}" ]]; then
+ if [ "${SSID}" = "${ssid}" ]; then
return ${EXIT_TRUE}
else
return ${EXIT_FALSE}
fi
local ssid="${1}"
+
if ! isset ssid; then
error "Please provide a SSID"
return ${EXIT_ERROR}
fi
- local ssid_hash="$(wireless_network_hash "${ssid}")"
- assert isset ssid_hash
-
# Check for duplicates
if wireless_network_exists "${ssid}"; then
error "The wireless network ${ssid} already exists"
return ${EXIT_ERROR}
fi
+ local handle="$(wireless_network_hash "${ssid}")"
+ assert isset handle
+
log DEBUG "Creating wireless network '${ssid}'"
- if ! mkdir -p "${NETWORK_WIRELESS_NETWORKS_DIR}/${ssid_hash}"; then
+ if ! mkdir -p "${NETWORK_WIRELESS_NETWORKS_DIR}/${handle}"; then
log ERROR "Could not create config directory for wireless network ${ssid}"
return ${EXIT_ERROR}
fi
- # When the ssid is not set in the settings file we cannot write it because wireless_network_exists fails
- echo "SSID=\"${ssid}\"" >>"${NETWORK_WIRELESS_NETWORKS_DIR}/${ssid_hash}/settings"
-
local ${WIRELESS_NETWORK_CONFIG_SETTINGS}
- ENCRYPTION_MODE="${WIRELESS_DEFAULT_ENCRYPTION_MODE}"
+ MODES="${WIRELESS_NETWORK_SUPPORTED_MODES}"
SSID="${ssid}"
- PRIORITY=500
+ PRIORITY=0
- if ! wireless_network_write_config "${ssid}"; then
+ if ! wireless_network_write_config "${handle}"; then
log ERROR "Could not write new config file"
return ${EXIT_ERROR}
fi
return ${EXIT_ERROR}
fi
- local ssid_hash="$(wireless_network_hash "${ssid}")"
- assert isset ssid_hash
+ local handle="$(wireless_network_hash "${ssid}")"
+ assert isset handle
- if ! rm -rf "${NETWORK_WIRELESS_NETWORKS_DIR}/${ssid_hash}"; then
+ if ! rm -rf "${NETWORK_WIRELESS_NETWORKS_DIR}/${handle}"; then
error "Could not delete the wireless network"
return ${EXIT_ERROR}
fi
return ${EXIT_OK}
}
-wireless_network_encryption_mode() {
- if [ ! $# -eq 2 ]; then
+wireless_networks_mode_is_valid() {
+ assert [ $# -eq 1 ]
+ local mode=${1}
+
+ if isoneof mode ${WIRELESS_NETWORK_SUPPORTED_MODES}; then
+ return ${EXIT_TRUE}
+ else
+ return ${EXIT_FALSE}
+ fi
+
+}
+
+# WIRELESS_NETWORK_SUPPORTED_MODES
+wireless_network_modes() {
+ if [ ! $# -ge 2 ]; then
log ERROR "Not enough arguments"
return ${EXIT_ERROR}
fi
- local ssid="${1}"
- local mode="${2}"
+ local handle="${1}"
+ shift
- if ! isoneof mode ${WIRELESS_VALID_ENCRYPTION_MODES}; then
- log ERROR "Encryption mode '${mode}' is invalid"
+ if [ $# -eq 0 ]; then
+ log ERROR "You must pass at least one value after mode"
return ${EXIT_ERROR}
fi
local ${WIRELESS_NETWORK_CONFIG_SETTINGS}
- if ! wireless_network_read_config "${ssid}"; then
- error "Could not read configuration for ${ssid}"
+ if ! wireless_network_read_config "${handle}"; then
+ error "Could not read configuration"
return ${EXIT_ERROR}
fi
- # Validate the PSK when changing mode and reset if needed
- if isset PSK && [ "${mode}" != "NONE" ] && \
- ! wireless_pre_shared_key_is_valid "${mode}" "${PSK}"; then
- log WARNING "The configured pre-shared-key is incompatible with this encryption mode and has been reset"
- PSK=""
+ # Remove duplicated entries to proceed the list safely
+ MODES="$(list_unique ${MODES})"
+
+ local modes_added
+ local modes_removed
+ local modes_set
+
+ while [ $# -gt 0 ]; do
+ local arg="${1}"
+
+ case "${arg}" in
+ +*)
+ list_append modes_added "${arg:1}"
+ ;;
+ -*)
+ list_append modes_removed "${arg:1}"
+ ;;
+ [A-Z0-9]*)
+ list_append modes_set "${arg}"
+ ;;
+ *)
+ error "Invalid argument: ${arg}"
+ return ${EXIT_ERROR}
+ ;;
+ esac
+ shift
+ done
+
+ # Check if the user is trying a mixed operation
+ if ! list_is_empty modes_set && (! list_is_empty modes_added || ! list_is_empty modes_removed); then
+ error "You cannot reset the modes list and add or remove modes at the same time"
+ return ${EXIT_ERROR}
fi
- # Save new encryption mode
- ENCRYPTION_MODE="${mode}"
+ # Set new modes list
+ if ! list_is_empty modes_set; then
+ # Check if all modes are valid
+ local mode
+ for mode in ${modes_set}; do
+ if ! wireless_networks_mode_is_valid ${mode}; then
+ error "Unsupported mode: ${mode}"
+ return ${EXIT_ERROR}
+ fi
+ done
+
+ MODES="${modes_set}"
- if ! wireless_network_write_config "${ssid}"; then
+ # Perform incremental updates
+ else
+ local modes
+
+ # Perform all removals
+ for mode in ${modes_removed}; do
+ if ! list_remove MODES ${mode}; then
+ warning "${mode} was not on the list and could not be removed"
+ fi
+ done
+
+ for mode in ${modes_added}; do
+ if wireless_networks_mode_is_valid ${mode}; then
+ if ! list_append_unique MODES ${mode}; then
+ warning "${mode} is already on the modes list"
+ fi
+ else
+ warning "${mode} is unknown or unsupported and could not be added"
+ fi
+ done
+ fi
+
+ # Check if the list contain at least one valid mode
+ if list_is_empty MODES; then
+ error "Cannot save an empty mode list"
+ return ${EXIT_ERROR}
+ fi
+
+ if ! wireless_network_write_config "${handle}"; then
log ERROR "Could not write configuration settings"
return ${EXIT_ERROR}
fi
log ERROR "Not enough arguments"
return ${EXIT_ERROR}
fi
- local ssid="${1}"
+
+ local handle="${1}"
local psk="${2}"
local ${WIRELESS_NETWORK_CONFIG_SETTINGS}
- if ! wireless_network_read_config "${ssid}"; then
- error "Could not read configuration for ${ssid}"
+ if ! wireless_network_read_config "${handle}"; then
+ error "Could not read configuration"
return ${EXIT_ERROR}
fi
fi
fi
- if ! wireless_network_write_config_key "${ssid}" "PSK" "${psk}"; then
+ if ! wireless_network_write_config_key "${handle}" "PSK" "${psk}"; then
log ERROR "Could not write configuration settings"
return ${EXIT_ERROR}
fi
}
+wireless_networks_priority_is_valid() {
+ assert [ $# -eq 1 ]
+
+ local priority=${1}
+
+ if ! isinteger priority || [ ! ${priority} -ge 0 ] || [ ! ${priority} -le 999 ]; then
+ return ${EXIT_FALSE}
+ fi
+
+ return ${EXIT_TRUE}
+}
+
wireless_network_priority() {
if [ ! $# -eq 2 ]; then
log ERROR "Not enough arguments"
return ${EXIT_ERROR}
fi
- local ssid="${1}"
+
+ local handle="${1}"
local priority=${2}
- if ! isinteger priority && [ ! ${priority} -ge 0 ]; then
- log ERROR "The priority must be an integer greater or eqal zero"
+ if ! wireless_networks_priority_is_valid ${priority}; then
+ error "The priority must be an integer greater or eqal zero and and less then 1000"
return ${EXIT_ERROR}
fi
- if ! wireless_network_write_config_key "${ssid}" "PRIORITY" "${priority}"; then
+ if ! wireless_network_write_config_key "${handle}" "PRIORITY" "${priority}"; then
log ERROR "Could not write configuration settings"
return ${EXIT_ERROR}
fi
}
+wireless_networks_write_wpa_supplicant_configuration() {
+ local device="${1}"
+
+ local file="${WPA_SUPPLICANT_CONF_DIR}/${device}.conf"
+
+ # Ensure we can write the file
+ make_parent_directory "${file}"
+
+ (
+ # Write a config header
+ wpa_supplicant_config_header
+
+ wireless_networks_to_wpa_supplicant
+ ) > ${file}
+}
+
wireless_networks_to_wpa_supplicant() {
- local ssid
- for ssid in "$(wireless_network_list_ssids)"; do
- wireless_network_to_wpa_supplicant "${ssid}"
+ local handle
+ for handle in $(wireless_network_list); do
+ wireless_network_to_wpa_supplicant "${handle}"
done
}
wireless_network_to_wpa_supplicant() {
- local ssid="${1}"
+ local handle="${1}"
local ${WIRELESS_NETWORK_CONFIG_SETTINGS}
- if ! wireless_network_read_config "${ssid}"; then
- error "Could not read configuration for ${ssid}"
+ if ! wireless_network_read_config "${handle}"; then
+ error "Could not read configuration for ${handle}"
return ${EXIT_ERROR}
fi
local pairwise
local proto
- case "${ENCRYPTION_MODE}" in
- # Normal WPA
- WPA-PSK)
- auth_alg="OPEN"
- key_mgmt="WPA-PSK"
- proto="WPA"
- pairwise="CCMP TKIP"
- group="CCMP TKIP WEP104 WEP40"
- ;;
-
- # WPA with stronger algorithms
- WPA-PSK-SHA256)
- auth_alg="OPEN"
- key_mgmt="WPA-PSK-SHA256"
- proto="WPA"
- pairwise="CCMP TKIP"
- group="CCMP TKIP WEP104 WEP40"
- ;;
+ local mode
+ for mode in ${WIRELESS_NETWORK_SUPPORTED_MODES}; do
+ # Skip any disabled modes
+ if isset MODES && ! list_match "${mode}" ${MODES}; then
+ continue
+ fi
- # Normal WPA2 (802.11i)
- WPA2-PSK)
- auth_alg="OPEN"
- key_mgmt="WPA-PSK"
- proto="RSN"
- pairwise="CCMP TKIP"
- group="CCMP TKIP WEP104 WEP40"
- ;;
+ case "${mode}" in
+ # WPA2 (802.11i)
+ WPA2-PSK|WPA2-PSK-SHA256)
+ list_append_unique auth_alg "OPEN"
+ list_append_unique key_mgmt "${mode/WPA2/WPA}"
+ list_append_unique proto "RSN"
+
+ local p
+ for p in CCMP TKIP; do
+ list_append_unique pairwise "${p}"
+ done
+
+ local g
+ for g in CCMP TKIP WEP104 WEP40; do
+ list_append_unique group "${g}"
+ done
+ ;;
+
+ # WPA
+ WPA-PSK|WPA-PSK-SHA256)
+ list_append_unique auth_alg "OPEN"
+ list_append_unique key_mgmt "${mode}"
+ list_append_unique proto "WPA"
+
+ local p
+ for p in CCMP TKIP; do
+ list_append_unique pairwise "${p}"
+ done
+
+ local g
+ for g in CCMP TKIP WEP104 WEP40; do
+ list_append_unique group "${g}"
+ done
+ ;;
+
+ # 802.1X
+ 802.1X)
+ list_append_unique key_mgmt "IEEE8021X"
+ ;;
+
+ # No encryption. DANGEROUS!
+ NONE)
+ list_append_unique auth_alg "OPEN"
+ list_append_unique key_mgmt "NONE"
+ ;;
+ esac
+ done
- # WPA2 with stronger algorithms
- WPA2-PSK-SHA256)
- auth_alg="OPEN"
- key_mgmt="WPA-PSK-SHA256"
- proto="RSN"
- pairwise="CCMP TKIP"
- group="CCMP TKIP WEP104 WEP40"
- ;;
+ assert isset auth_alg
+ assert isset key_mgmt
- # WEP
- WEP)
- auth_alg="SHARED"
- wep_key0="${key}"
- wep_tx_keyidx="0"
+ # Certificate Paths
+ local ca_cert_path="${NETWORK_WIRELESS_NETWORKS_DIR}/${handle}/ca.pem"
+ local client_cert_path="${NETWORK_WIRELESS_NETWORKS_DIR}/${handle}/client.pem"
+ local client_key_path="${NETWORK_WIRELESS_NETWORKS_DIR}/${handle}/client.key"
- # Reset PSK.
- psk=""
- ;;
+ print_indent 0 "# ${SSID}"
+ print_indent 0 "network={"
+ print_indent 1 "ssid=\"${SSID}\""
- # No encryption. DANGEROUS!
- NONE)
- auth_alg="OPEN"
- key_mgmt="NONE"
- ;;
- esac
+ # Actively scan for hidden networks
+ if enabled HIDDEN; then
+ print_indent 1 "scan_ssid=1"
+ fi
- print_indent 0 "# ${SSID}"
- print_indent 0 "network = {"
- print_indent 1 "ssid=\"${ssid}\""
+ # Priority
+ if isinteger PRIORITY; then
+ print_indent 1 "priority=${PRIORITY}"
+ fi
print
# Authentication
print_indent 1 "auth_alg=${auth_alg}"
print_indent 1 "key_mgmt=${key_mgmt}"
- case "${ENCRYPTION_MODE}" in
- WPA*)
- print_indent 1 "proto=${proto}"
- print_indent 1 "pairwise=${pairwise}"
- ;;
- esac
+ local i
+ for i in proto pairwise group; do
+ print_indent 1 "${i}=${!i}"
+ done
+ print
- # PSKs
- case "${ENCRYPTION_MODE}" in
- WPA*PSK)
- print_indent 1 "psk=\"${PSK}\""
- ;;
- WEP)
- print_indent 1 "wep_key0=\"${PSK}\""
- print_indent 1 "wep_tx_keyidx=0"
- ;;
- esac
+ # PSK
+ if isset PSK; then
+ print_indent 1 "# Pre Shared Key"
+ print_indent 1 "psk=\"${PSK}\""
+ fi
+
+ if isset EAP_MODES; then
+ print_indent 1 "# EAP"
+ print_indent 1 "eap=${EAP_MODES}"
+ print
+ fi
+
+ if isset IDENTITY; then
+ print_indent 1 "# Credentials"
+ print_indent 1 "identity=\"${IDENTITY}\""
+
+ if isset PASSWORD; then
+ print_indent 1 "password=\"${PASSWORD}\""
+ fi
+
+ if isset ANONYMOUS_IDENTITY; then
+ print_indent 1 "anonymous_identity=\"${ANONYMOUS_IDENTITY}\""
+ fi
+ print
+ fi
+
+ # Client Certificate
+ if file_exists "${client_cert_path}" && file_exists "${client_key_path}"; then
+ print_indent 1 "# Client Certificate"
+ print_indent 1 "client_cert=\"${client_cert_path}\""
+ print_indent 1 "private_key=\"${client_key_path}\""
+ print
+ fi
+
+ # Validate server certificates
+ if file_exists "${ca_cert_path}"; then
+ print_indent 1 "ca_cert=\"${ca_cert_path}\""
+
+ elif isset CA_BUNDLE; then
+ print_indent 1 "ca_cert=\"${CA_BUNDLE}\""
+ fi
print_indent 0 "}"
print