]> git.ipfire.org Git - people/stevee/network.git/blame - src/functions/functions.wireless-networks
wireless networks: Write user credentials into configuration
[people/stevee/network.git] / src / functions / functions.wireless-networks
CommitLineData
49958b8c
MT
1#!/bin/bash
2###############################################################################
3# #
4# IPFire.org - A linux based firewall #
5# Copyright (C) 2017 IPFire Network Development Team #
6# #
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. #
11# #
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. #
16# #
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/>. #
19# #
20###############################################################################
21
790ab927
MT
22WIRELESS_NETWORK_SUPPORTED_PSK_MODES="WPA2-PSK-SHA256 WPA2-PSK WPA-PSK-SHA256 WPA-PSK"
23
fa25d793 24WIRELESS_NETWORK_SUPPORTED_MODES="${WIRELESS_NETWORK_SUPPORTED_PSK_MODES} 802.1X NONE"
790ab927 25
26078fa1
MT
26WIRELESS_NETWORK_CONFIG_SETTINGS="ANONYMOUS_IDENTITY EAP_MODES IDENTITY \
27 MODES PASSWORD PRIORITY PSK SSID"
49958b8c 28
49958b8c 29cli_wireless_network() {
479b2273
MT
30 case "${1}" in
31 new)
32 wireless_network_new "${@:2}"
33 ;;
34 destroy)
35 wireless_network_destroy "${@:2}"
36 ;;
37 *)
38 local ssid="${1}"
39 local key="${2//-/_}"
549c5b97 40 shift 2
49958b8c 41
479b2273
MT
42 if ! wireless_network_exists "${ssid}"; then
43 error "No such wireless network: ${ssid}"
44 return ${EXIT_ERROR}
45 fi
49958b8c 46
2f64ac44
MT
47 # Convert SSID into usable format
48 local handle="$(wireless_network_hash "${ssid}")"
49
479b2273 50 case "${key}" in
364da6f4 51 encryption_mode|pre_shared_key|priority)
2f64ac44 52 wireless_network_${key} "${handle}" "$@"
479b2273
MT
53 ;;
54 show)
2f64ac44 55 wireless_network_show "${handle}"
479b2273
MT
56 exit $?
57 ;;
58 *)
59 error "Unrecognized argument: ${key}"
60 exit ${EXIT_ERROR}
61 ;;
62 esac
63 ;;
64 esac
49958b8c
MT
65}
66
d86b2dee
MT
67wireless_network_list() {
68 list_directory "${NETWORK_WIRELESS_NETWORKS_DIR}"
69}
70
71wireless_network_list_ssids() {
72 local handle
73 for handle in $(wireless_network_list); do
74 local ${WIRELESS_NETWORK_CONFIG_SETTINGS}
2f64ac44 75 if ! wireless_network_read_config "${handle}"; then
d86b2dee
MT
76 continue
77 fi
78
79 print "${SSID}"
80 done
81}
82
49958b8c
MT
83# This function writes all values to a via ${ssid} specificated wireless network configuration file
84wireless_network_write_config() {
85 assert [ $# -ge 1 ]
86
2f64ac44 87 local handle="${1}"
49958b8c 88
2f64ac44 89 local path="${NETWORK_WIRELESS_NETWORKS_DIR}/${handle}/settings"
49958b8c
MT
90
91 if ! settings_write "${path}" ${WIRELESS_NETWORK_CONFIG_SETTINGS}; then
2f64ac44 92 log ERROR "Could not write configuration"
49958b8c
MT
93 return ${EXIT_ERROR}
94 fi
95
96 # When we get here the writing of the config file was successful
97 return ${EXIT_OK}
98}
99
100# This funtion writes the value for one key to a via ${ssid} specificated
101# wireless network configuration file
102wireless_network_write_config_key() {
103 assert [ $# -ge 3 ]
104
2f64ac44 105 local handle="${1}"
49958b8c
MT
106 local key="${2}"
107 shift 2
108
109 local value="$@"
110
49958b8c
MT
111 local ${WIRELESS_NETWORK_CONFIG_SETTINGS}
112
113 # Read the config settings
2f64ac44 114 if ! wireless_network_read_config "${handle}"; then
49958b8c
MT
115 return ${EXIT_ERROR}
116 fi
117
2f64ac44
MT
118 log DEBUG "Set '${key}' to new value '${value}' in wireless network '${SSID}'"
119
49958b8c
MT
120 # Set the key to a new value
121 assign "${key}" "${value}"
122
2f64ac44 123 if ! wireless_network_write_config "${handle}"; then
49958b8c
MT
124 return ${EXIT_ERROR}
125 fi
126
127 return ${EXIT_OK}
128}
129
d86b2dee 130# Reads one or more keys out of a settings file or all if no key is provided.
2f64ac44 131wireless_network_read_config() {
d86b2dee
MT
132 assert [ $# -ge 1 ]
133
134 local handle="${1}"
135 shift
136
49958b8c
MT
137 local args
138 if [ $# -eq 0 ] && [ -n "${WIRELESS_NETWORK_CONFIG_SETTINGS}" ]; then
139 list_append args ${WIRELESS_NETWORK_CONFIG_SETTINGS}
140 else
141 list_append args "$@"
142 fi
143
d86b2dee 144 local path="${NETWORK_WIRELESS_NETWORKS_DIR}/${handle}/settings"
49958b8c
MT
145
146 if ! settings_read "${path}" ${args}; then
d86b2dee 147 log ERROR "Could not read settings for wireless network ${handle}"
49958b8c
MT
148 return ${EXIT_ERROR}
149 fi
150}
151
152# This function checks if a wireless network exists
153# Returns True when yes and false when not
154wireless_network_exists() {
49958b8c 155 local ssid="${1}"
49958b8c 156
2f64ac44
MT
157 local handle="$(wireless_network_hash "${ssid}")"
158 assert isset handle
49958b8c
MT
159
160 # We cannot use wireless_network_read_config here beacuse we would end in a loop
161 local SSID
2f64ac44 162 if ! settings_read "${NETWORK_WIRELESS_NETWORKS_DIR}/${handle}/settings" SSID; then
49958b8c
MT
163 return ${EXIT_FALSE}
164 fi
165
2f64ac44 166 if [ "${SSID}" = "${ssid}" ]; then
49958b8c
MT
167 return ${EXIT_TRUE}
168 else
169 return ${EXIT_FALSE}
170 fi
171}
172
173wireless_network_hash() {
174 assert [ $# -eq 1 ]
175
176 local string="${1}"
177
178 local hash=$(echo -n "${string}" | md5sum )
179 hash=${hash%% -}
180
181 local path="${NETWORK_WIRELESS_NETWORKS_DIR}/*${hash}"
182
183 if [ -d "${path}" ]; then
184 basename "${path}"
185 else
186 local normalized=$(normalize "${string}")
187 normalized=${normalized%-}
188 echo "${normalized}-${hash}"
189 fi
190}
191
192wireless_network_new() {
193 if [ $# -gt 1 ]; then
194 error "Too many arguments"
195 return ${EXIT_ERROR}
196 fi
197
198 local ssid="${1}"
2f64ac44 199
49958b8c
MT
200 if ! isset ssid; then
201 error "Please provide a SSID"
202 return ${EXIT_ERROR}
203 fi
204
49958b8c
MT
205 # Check for duplicates
206 if wireless_network_exists "${ssid}"; then
207 error "The wireless network ${ssid} already exists"
208 return ${EXIT_ERROR}
209 fi
210
2f64ac44
MT
211 local handle="$(wireless_network_hash "${ssid}")"
212 assert isset handle
213
49958b8c
MT
214 log DEBUG "Creating wireless network '${ssid}'"
215
2f64ac44 216 if ! mkdir -p "${NETWORK_WIRELESS_NETWORKS_DIR}/${handle}"; then
49958b8c
MT
217 log ERROR "Could not create config directory for wireless network ${ssid}"
218 return ${EXIT_ERROR}
219 fi
220
49958b8c 221 local ${WIRELESS_NETWORK_CONFIG_SETTINGS}
1c9e2fa8 222 ENCRYPTION_MODE="${WIRELESS_DEFAULT_ENCRYPTION_MODE}"
49958b8c
MT
223 SSID="${ssid}"
224 PRIORITY=500
225
2f64ac44 226 if ! wireless_network_write_config "${handle}"; then
49958b8c
MT
227 log ERROR "Could not write new config file"
228 return ${EXIT_ERROR}
229 fi
230}
231
4b08d574 232# Deletes a wireless network
49958b8c 233wireless_network_destroy() {
4b08d574
MT
234 local ssid="${1}"
235
236 if ! wireless_network_exists "${ssid}"; then
237 error "No such wireless network: ${ssid}"
238 return ${EXIT_ERROR}
239 fi
240
2f64ac44
MT
241 local handle="$(wireless_network_hash "${ssid}")"
242 assert isset handle
4b08d574 243
2f64ac44 244 if ! rm -rf "${NETWORK_WIRELESS_NETWORKS_DIR}/${handle}"; then
4b08d574
MT
245 error "Could not delete the wireless network"
246 return ${EXIT_ERROR}
247 fi
248
249 log INFO "Successfully destroyed wireless network ${ssid}"
250 return ${EXIT_OK}
49958b8c
MT
251}
252
253wireless_network_encryption_mode() {
254 if [ ! $# -eq 2 ]; then
255 log ERROR "Not enough arguments"
256 return ${EXIT_ERROR}
257 fi
2f64ac44 258 local handle="${1}"
49958b8c
MT
259 local mode="${2}"
260
1c9e2fa8 261 if ! isoneof mode ${WIRELESS_VALID_ENCRYPTION_MODES}; then
49958b8c
MT
262 log ERROR "Encryption mode '${mode}' is invalid"
263 return ${EXIT_ERROR}
264 fi
265
549c5b97 266 local ${WIRELESS_NETWORK_CONFIG_SETTINGS}
2f64ac44
MT
267 if ! wireless_network_read_config "${handle}"; then
268 error "Could not read configuration"
549c5b97
MT
269 return ${EXIT_ERROR}
270 fi
271
272 # Validate the PSK when changing mode and reset if needed
273 if isset PSK && [ "${mode}" != "NONE" ] && \
274 ! wireless_pre_shared_key_is_valid "${mode}" "${PSK}"; then
275 log WARNING "The configured pre-shared-key is incompatible with this encryption mode and has been reset"
276 PSK=""
277 fi
278
279 # Save new encryption mode
280 ENCRYPTION_MODE="${mode}"
281
2f64ac44 282 if ! wireless_network_write_config "${handle}"; then
49958b8c
MT
283 log ERROR "Could not write configuration settings"
284 return ${EXIT_ERROR}
285 fi
286}
287
364da6f4 288wireless_network_pre_shared_key() {
49958b8c
MT
289 if [ ! $# -eq 2 ]; then
290 log ERROR "Not enough arguments"
291 return ${EXIT_ERROR}
292 fi
2f64ac44
MT
293
294 local handle="${1}"
364da6f4 295 local psk="${2}"
49958b8c 296
549c5b97 297 local ${WIRELESS_NETWORK_CONFIG_SETTINGS}
2f64ac44
MT
298 if ! wireless_network_read_config "${handle}"; then
299 error "Could not read configuration"
549c5b97
MT
300 return ${EXIT_ERROR}
301 fi
302
303 # Validate the key if encryption mode is known
304 if isset ENCRYPTION_MODE && [ "${ENCRYPTION_MODE}" != "NONE" ]; then
305 if ! wireless_pre_share_key_is_valid "${ENCRYPTION_MODE}" "${psk}"; then
306 error "The pre-shared-key is invalid for this wireless network: ${psk}"
307 return ${EXIT_ERROR}
308 fi
309 fi
310
2f64ac44 311 if ! wireless_network_write_config_key "${handle}" "PSK" "${psk}"; then
49958b8c
MT
312 log ERROR "Could not write configuration settings"
313 return ${EXIT_ERROR}
314 fi
315}
316
317wireless_network_priority() {
318 if [ ! $# -eq 2 ]; then
319 log ERROR "Not enough arguments"
320 return ${EXIT_ERROR}
321 fi
2f64ac44
MT
322
323 local handle="${1}"
49958b8c
MT
324 local priority=${2}
325
326 if ! isinteger priority && [ ! ${priority} -ge 0 ]; then
327 log ERROR "The priority must be an integer greater or eqal zero"
328 return ${EXIT_ERROR}
329 fi
330
2f64ac44 331 if ! wireless_network_write_config_key "${handle}" "PRIORITY" "${priority}"; then
49958b8c
MT
332 log ERROR "Could not write configuration settings"
333 return ${EXIT_ERROR}
334 fi
335}
d86b2dee 336
e66e539b
MT
337wireless_networks_write_wpa_supplicant_configuration() {
338 local device="${1}"
339
340 local file="${WPA_SUPPLICANT_CONF_DIR}/${device}.conf"
341
342 # Ensure we can write the file
343 make_parent_directory "${file}"
344
e66e539b 345 (
f1b49125
MT
346 # Write a config header
347 wpa_supplicant_config_header
e66e539b
MT
348
349 wireless_networks_to_wpa_supplicant
350 ) > ${file}
351}
352
d86b2dee 353wireless_networks_to_wpa_supplicant() {
2f64ac44
MT
354 local handle
355 for handle in $(wireless_network_list); do
356 wireless_network_to_wpa_supplicant "${handle}"
d86b2dee
MT
357 done
358}
359
360wireless_network_to_wpa_supplicant() {
2f64ac44 361 local handle="${1}"
d86b2dee
MT
362
363 local ${WIRELESS_NETWORK_CONFIG_SETTINGS}
2f64ac44
MT
364 if ! wireless_network_read_config "${handle}"; then
365 error "Could not read configuration for ${handle}"
d86b2dee
MT
366 return ${EXIT_ERROR}
367 fi
368
369 local auth_alg
370 local group
371 local key_mgmt
372 local pairwise
373 local proto
374
790ab927
MT
375 local mode
376 for mode in ${WIRELESS_NETWORK_SUPPORTED_MODES}; do
377 # Skip any disabled modes
0afdbac2 378 if isset MODES && ! list_match "${mode}" ${MODES}; then
790ab927
MT
379 continue
380 fi
d86b2dee 381
790ab927
MT
382 case "${mode}" in
383 # WPA2 (802.11i)
384 WPA2-PSK|WPA2-PSK-SHA256)
385 list_append_unique auth_alg "OPEN"
386 list_append_unique key_mgmt "${mode/WPA2/WPA}"
387 list_append_unique proto "RSN"
388
389 local p
390 for p in CCMP TKIP; do
391 list_append_unique pairwise "${p}"
392 done
393
394 local g
395 for g in CCMP TKIP WEP104 WEP40; do
396 list_append_unique group "${g}"
397 done
398 ;;
399
400 # WPA
401 WPA-PSK|WPA-PSK-SHA256)
402 list_append_unique auth_alg "OPEN"
403 list_append_unique key_mgmt "${mode}"
404 list_append_unique proto "WPA"
405
406 local p
407 for p in CCMP TKIP; do
408 list_append_unique pairwise "${p}"
409 done
410
411 local g
412 for g in CCMP TKIP WEP104 WEP40; do
413 list_append_unique group "${g}"
414 done
415 ;;
416
fa25d793
MT
417 # 802.1X
418 802.1X)
419 list_append_unique key_mgmt "IEEE8021X"
420 ;;
421
790ab927
MT
422 # No encryption. DANGEROUS!
423 NONE)
424 list_append_unique auth_alg "OPEN"
425 list_append_unique key_mgmt "NONE"
426 ;;
427 esac
428 done
d86b2dee 429
790ab927
MT
430 assert isset auth_alg
431 assert isset key_mgmt
d86b2dee
MT
432
433 print_indent 0 "# ${SSID}"
d8d0eefc 434 print_indent 0 "network={"
2f64ac44 435 print_indent 1 "ssid=\"${SSID}\""
028a39d1
MT
436
437 # Priority
438 if isinteger PRIORITY; then
439 print_indent 1 "priority=${PRIORITY}"
440 fi
d86b2dee
MT
441 print
442
443 # Authentication
444 print_indent 1 "# Authentication"
445 print_indent 1 "auth_alg=${auth_alg}"
446 print_indent 1 "key_mgmt=${key_mgmt}"
447
790ab927
MT
448 local i
449 for i in proto pairwise group; do
450 print_indent 1 "${i}=${!i}"
451 done
452 print
d86b2dee 453
790ab927
MT
454 # PSK
455 if isset PSK; then
456 print_indent 1 "# Pre Shared Key"
457 print_indent 1 "psk=\"${PSK}\""
458 fi
d86b2dee 459
54948d3c
MT
460 if isset EAP_MODES; then
461 print_indent 1 "# EAP"
462 print_indent 1 "eap=${EAP_MODES}"
463 print
464 fi
465
26078fa1
MT
466 if isset IDENTITY; then
467 print_indent 1 "# Credentials"
468 print_indent 1 "identity=\"${IDENTITY}\""
469
470 if isset PASSWORD; then
471 print_indent 1 "password=\"${PASSWORD}\""
472 fi
473
474 if isset ANONYMOUS_IDENTITY; then
475 print_indent 1 "anonymous_identity=\"${ANONYMOUS_IDENTITY}\""
476 fi
477 print
478 fi
479
d86b2dee
MT
480 print_indent 0 "}"
481 print
482}