2 ###############################################################################
4 # IPFire.org - A linux based firewall #
5 # Copyright (C) 2017 IPFire Network Development Team #
7 # This program is free software: you can redistribute it and/or modify #
8 # it under the terms of the GNU General Public License as published by #
9 # the Free Software Foundation, either version 3 of the License, or #
10 # (at your option) any later version. #
12 # This program is distributed in the hope that it will be useful, #
13 # but WITHOUT ANY WARRANTY; without even the implied warranty of #
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
15 # GNU General Public License for more details. #
17 # You should have received a copy of the GNU General Public License #
18 # along with this program. If not, see <http://www.gnu.org/licenses/>. #
20 ###############################################################################
22 WIRELESS_NETWORK_SUPPORTED_PSK_MODES
="WPA2-PSK-SHA256 WPA2-PSK WPA-PSK-SHA256 WPA-PSK"
24 WIRELESS_NETWORK_SUPPORTED_MODES
="${WIRELESS_NETWORK_SUPPORTED_PSK_MODES} \
27 WIRELESS_NETWORK_CONFIG_SETTINGS
="ANONYMOUS_IDENTITY EAP_MODES HIDDEN \
28 IDENTITY MODES PASSWORD PRIORITY PSK SSID"
30 cli_wireless_network
() {
33 wireless_network_new
"${@:2}"
36 wireless_network_destroy
"${@:2}"
43 if ! wireless_network_exists
"${ssid}"; then
44 error
"No such wireless network: ${ssid}"
48 # Convert SSID into usable format
49 local handle
="$(wireless_network_hash "${ssid}")"
52 modes|pre_shared_key|priority
)
53 wireless_network_
${key} "${handle}" "$@"
56 wireless_network_show
"${handle}"
60 error
"Unrecognized argument: ${key}"
68 wireless_network_list
() {
69 list_directory
"${NETWORK_WIRELESS_NETWORKS_DIR}"
72 wireless_network_list_ssids
() {
74 for handle
in $
(wireless_network_list
); do
75 local ${WIRELESS_NETWORK_CONFIG_SETTINGS}
76 if ! wireless_network_read_config
"${handle}"; then
84 # This function writes all values to a via ${ssid} specificated wireless network configuration file
85 wireless_network_write_config
() {
90 local path
="${NETWORK_WIRELESS_NETWORKS_DIR}/${handle}/settings"
92 if ! settings_write
"${path}" ${WIRELESS_NETWORK_CONFIG_SETTINGS}; then
93 log ERROR
"Could not write configuration"
97 # When we get here the writing of the config file was successful
101 # This funtion writes the value for one key to a via ${ssid} specificated
102 # wireless network configuration file
103 wireless_network_write_config_key
() {
112 local ${WIRELESS_NETWORK_CONFIG_SETTINGS}
114 # Read the config settings
115 if ! wireless_network_read_config
"${handle}"; then
119 log DEBUG
"Set '${key}' to new value '${value}' in wireless network '${SSID}'"
121 # Set the key to a new value
122 assign
"${key}" "${value}"
124 if ! wireless_network_write_config
"${handle}"; then
131 # Reads one or more keys out of a settings file or all if no key is provided.
132 wireless_network_read_config
() {
139 if [ $# -eq 0 ] && [ -n "${WIRELESS_NETWORK_CONFIG_SETTINGS}" ]; then
140 list_append args
${WIRELESS_NETWORK_CONFIG_SETTINGS}
142 list_append args
"$@"
145 local path
="${NETWORK_WIRELESS_NETWORKS_DIR}/${handle}/settings"
147 if ! settings_read
"${path}" ${args}; then
148 log ERROR
"Could not read settings for wireless network ${handle}"
153 # This function checks if a wireless network exists
154 # Returns True when yes and false when not
155 wireless_network_exists
() {
158 local handle
="$(wireless_network_hash "${ssid}")"
161 # We cannot use wireless_network_read_config here beacuse we would end in a loop
163 if ! settings_read
"${NETWORK_WIRELESS_NETWORKS_DIR}/${handle}/settings" SSID
; then
167 if [ "${SSID}" = "${ssid}" ]; then
174 wireless_network_hash
() {
179 local hash=$
(echo -n "${string}" |
md5sum )
182 local path
="${NETWORK_WIRELESS_NETWORKS_DIR}/*${hash}"
184 if [ -d "${path}" ]; then
187 local normalized
=$
(normalize
"${string}")
188 normalized
=${normalized%-}
189 echo "${normalized}-${hash}"
193 wireless_network_new
() {
194 if [ $# -gt 1 ]; then
195 error
"Too many arguments"
201 if ! isset ssid
; then
202 error
"Please provide a SSID"
206 # Check for duplicates
207 if wireless_network_exists
"${ssid}"; then
208 error
"The wireless network ${ssid} already exists"
212 local handle
="$(wireless_network_hash "${ssid}")"
215 log DEBUG
"Creating wireless network '${ssid}'"
217 if ! mkdir
-p "${NETWORK_WIRELESS_NETWORKS_DIR}/${handle}"; then
218 log ERROR
"Could not create config directory for wireless network ${ssid}"
222 local ${WIRELESS_NETWORK_CONFIG_SETTINGS}
223 MODES
="${WIRELESS_NETWORK_SUPPORTED_MODES}"
227 if ! wireless_network_write_config
"${handle}"; then
228 log ERROR
"Could not write new config file"
233 # Deletes a wireless network
234 wireless_network_destroy
() {
237 if ! wireless_network_exists
"${ssid}"; then
238 error
"No such wireless network: ${ssid}"
242 local handle
="$(wireless_network_hash "${ssid}")"
245 if ! rm -rf "${NETWORK_WIRELESS_NETWORKS_DIR}/${handle}"; then
246 error
"Could not delete the wireless network"
250 log INFO
"Successfully destroyed wireless network ${ssid}"
254 wireless_networks_mode_is_valid
() {
258 if isoneof mode
${WIRELESS_NETWORK_SUPPORTED_MODES}; then
266 # WIRELESS_NETWORK_SUPPORTED_MODES
267 wireless_network_modes
() {
268 if [ ! $# -ge 2 ]; then
269 log ERROR
"Not enough arguments"
275 if [ $# -eq 0 ]; then
276 log ERROR
"You must pass at least one value after mode"
280 local ${WIRELESS_NETWORK_CONFIG_SETTINGS}
281 if ! wireless_network_read_config
"${handle}"; then
282 error
"Could not read configuration"
286 # Remove duplicated entries to proceed the list safely
287 MODES
="$(list_unique ${MODES})"
293 while [ $# -gt 0 ]; do
298 list_append modes_added
"${arg:1}"
301 list_append modes_removed
"${arg:1}"
304 list_append modes_set
"${arg}"
307 error
"Invalid argument: ${arg}"
314 # Check if the user is trying a mixed operation
315 if ! list_is_empty modes_set
&& (! list_is_empty modes_added ||
! list_is_empty modes_removed
); then
316 error
"You cannot reset the modes list and add or remove modes at the same time"
321 if ! list_is_empty modes_set
; then
322 # Check if all modes are valid
324 for mode
in ${modes_set}; do
325 if ! wireless_networks_mode_is_valid
${mode}; then
326 error
"Unsupported mode: ${mode}"
333 # Perform incremental updates
337 # Perform all removals
338 for mode
in ${modes_removed}; do
339 if ! list_remove MODES
${mode}; then
340 warning
"${mode} was not on the list and could not be removed"
344 for mode
in ${modes_added}; do
345 if wireless_networks_mode_is_valid
${mode}; then
346 if ! list_append_unique MODES
${mode}; then
347 warning
"${mode} is already on the modes list"
350 warning
"${mode} is unknown or unsupported and could not be added"
355 # Check if the list contain at least one valid mode
356 if list_is_empty MODES
; then
357 error
"Cannot save an empty mode list"
361 if ! wireless_network_write_config
"${handle}"; then
362 log ERROR
"Could not write configuration settings"
367 wireless_network_pre_shared_key
() {
368 if [ ! $# -eq 2 ]; then
369 log ERROR
"Not enough arguments"
376 local ${WIRELESS_NETWORK_CONFIG_SETTINGS}
377 if ! wireless_network_read_config
"${handle}"; then
378 error
"Could not read configuration"
382 # Validate the key if encryption mode is known
383 if isset ENCRYPTION_MODE
&& [ "${ENCRYPTION_MODE}" != "NONE" ]; then
384 if ! wireless_pre_share_key_is_valid
"${ENCRYPTION_MODE}" "${psk}"; then
385 error
"The pre-shared-key is invalid for this wireless network: ${psk}"
390 if ! wireless_network_write_config_key
"${handle}" "PSK" "${psk}"; then
391 log ERROR
"Could not write configuration settings"
396 wireless_networks_priority_is_valid
() {
401 if ! isinteger priority ||
[ ! ${priority} -ge 0 ] ||
[ ! ${priority} -le 999 ]; then
408 wireless_network_priority
() {
409 if [ ! $# -eq 2 ]; then
410 log ERROR
"Not enough arguments"
417 if ! wireless_networks_priority_is_valid
${priority}; then
418 error
"The priority must be an integer greater or eqal zero and and less then 1000"
422 if ! wireless_network_write_config_key
"${handle}" "PRIORITY" "${priority}"; then
423 log ERROR
"Could not write configuration settings"
428 wireless_networks_write_wpa_supplicant_configuration
() {
431 local file="${WPA_SUPPLICANT_CONF_DIR}/${device}.conf"
433 # Ensure we can write the file
434 make_parent_directory
"${file}"
437 # Write a config header
438 wpa_supplicant_config_header
440 wireless_networks_to_wpa_supplicant
444 wireless_networks_to_wpa_supplicant
() {
446 for handle
in $
(wireless_network_list
); do
447 wireless_network_to_wpa_supplicant
"${handle}"
451 wireless_network_to_wpa_supplicant
() {
454 local ${WIRELESS_NETWORK_CONFIG_SETTINGS}
455 if ! wireless_network_read_config
"${handle}"; then
456 error
"Could not read configuration for ${handle}"
467 for mode
in ${WIRELESS_NETWORK_SUPPORTED_MODES}; do
468 # Skip any disabled modes
469 if isset MODES
&& ! list_match
"${mode}" ${MODES}; then
475 WPA2-PSK|WPA2-PSK-SHA256
)
476 list_append_unique auth_alg
"OPEN"
477 list_append_unique key_mgmt
"${mode/WPA2/WPA}"
478 list_append_unique proto
"RSN"
481 for p
in CCMP TKIP
; do
482 list_append_unique pairwise
"${p}"
486 for g
in CCMP TKIP WEP104 WEP40
; do
487 list_append_unique group
"${g}"
492 WPA-PSK|WPA-PSK-SHA256
)
493 list_append_unique auth_alg
"OPEN"
494 list_append_unique key_mgmt
"${mode}"
495 list_append_unique proto
"WPA"
498 for p
in CCMP TKIP
; do
499 list_append_unique pairwise
"${p}"
503 for g
in CCMP TKIP WEP104 WEP40
; do
504 list_append_unique group
"${g}"
510 list_append_unique key_mgmt
"IEEE8021X"
513 # No encryption. DANGEROUS!
515 list_append_unique auth_alg
"OPEN"
516 list_append_unique key_mgmt
"NONE"
521 assert isset auth_alg
522 assert isset key_mgmt
525 local ca_cert_path
="${NETWORK_WIRELESS_NETWORKS_DIR}/${handle}/ca.pem"
526 local client_cert_path
="${NETWORK_WIRELESS_NETWORKS_DIR}/${handle}/client.pem"
527 local client_key_path
="${NETWORK_WIRELESS_NETWORKS_DIR}/${handle}/client.key"
529 print_indent
0 "# ${SSID}"
530 print_indent
0 "network={"
531 print_indent
1 "ssid=\"${SSID}\""
533 # Actively scan for hidden networks
534 if enabled HIDDEN
; then
535 print_indent
1 "scan_ssid=1"
539 if isinteger PRIORITY
; then
540 print_indent
1 "priority=${PRIORITY}"
545 print_indent
1 "# Authentication"
546 print_indent
1 "auth_alg=${auth_alg}"
547 print_indent
1 "key_mgmt=${key_mgmt}"
550 for i
in proto pairwise group
; do
551 print_indent
1 "${i}=${!i}"
557 print_indent
1 "# Pre Shared Key"
558 print_indent
1 "psk=\"${PSK}\""
561 if isset EAP_MODES
; then
562 print_indent
1 "# EAP"
563 print_indent
1 "eap=${EAP_MODES}"
567 if isset IDENTITY
; then
568 print_indent
1 "# Credentials"
569 print_indent
1 "identity=\"${IDENTITY}\""
571 if isset PASSWORD
; then
572 print_indent
1 "password=\"${PASSWORD}\""
575 if isset ANONYMOUS_IDENTITY
; then
576 print_indent
1 "anonymous_identity=\"${ANONYMOUS_IDENTITY}\""
582 if file_exists
"${client_cert_path}" && file_exists
"${client_key_path}"; then
583 print_indent
1 "# Client Certificate"
584 print_indent
1 "client_cert=\"${client_cert_path}\""
585 print_indent
1 "private_key=\"${client_key_path}\""
589 # Validate server certificates
590 if file_exists
"${ca_cert_path}"; then
591 print_indent
1 "ca_cert=\"${ca_cert_path}\""
593 elif isset CA_BUNDLE
; then
594 print_indent
1 "ca_cert=\"${CA_BUNDLE}\""