Merge ~teknoraver/snappy-hwe-snaps/+git/wifi-ap:wpapass into ~snappy-hwe-team/snappy-hwe-snaps/+git/wifi-ap:master

Proposed by Matteo Croce
Status: Merged
Approved by: Simon Fels
Approved revision: df8df420f7d8357995f0fa1a53fbac01e26223bf
Merged at revision: 67a49951c04daac96a28269bc257ea171b66d5e0
Proposed branch: ~teknoraver/snappy-hwe-snaps/+git/wifi-ap:wpapass
Merge into: ~snappy-hwe-team/snappy-hwe-snaps/+git/wifi-ap:master
Diff against target: 364 lines (+154/-41)
12 files modified
.spread-reuse.22327.yaml (+9/-0)
cmd/client/cmd_wizard.go (+36/-7)
cmd/client/cmd_wizard_test.go (+62/-0)
dev/null (+0/-23)
docs/basic-ap-setup.md (+8/-0)
docs/installation.md (+2/-2)
tests/lib/restore-each.sh (+4/-0)
tests/lib/utilities.sh (+22/-0)
tests/main/conf-wizard-auto-at-boot/task.yaml (+3/-1)
tests/main/default-conf-brings-up-ap/task.yaml (+3/-4)
tests/main/stress-ap-status-control/task.yaml (+4/-2)
tests/main/utf8-ssid/task.yaml (+1/-2)
Reviewer Review Type Date Requested Status
System Enablement Bot continuous-integration Approve
Simon Fels Approve
Konrad Zapałowicz (community) code Approve
Review via email: mp+320490@code.launchpad.net

Description of the change

Generate automatically a WPA password

To post a comment you must log in.
Revision history for this message
Konrad Zapałowicz (kzapalowicz) wrote :

change looks good however the code-layout could be improved for readability.

review: Needs Fixing (code)
Revision history for this message
Simon Fels (morphis) :
review: Needs Fixing
Revision history for this message
System Enablement Bot (system-enablement-ci-bot) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Simon Fels (morphis) :
Revision history for this message
System Enablement Bot (system-enablement-ci-bot) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
System Enablement Bot (system-enablement-ci-bot) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
System Enablement Bot (system-enablement-ci-bot) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
System Enablement Bot (system-enablement-ci-bot) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
System Enablement Bot (system-enablement-ci-bot) wrote :
review: Approve (continuous-integration)
Revision history for this message
Konrad Zapałowicz (kzapalowicz) wrote :

comments inline

review: Needs Fixing (code)
Revision history for this message
System Enablement Bot (system-enablement-ci-bot) wrote :
review: Approve (continuous-integration)
Revision history for this message
System Enablement Bot (system-enablement-ci-bot) wrote :
review: Approve (continuous-integration)
Revision history for this message
Konrad Zapałowicz (kzapalowicz) wrote :

ack

review: Approve (code)
Revision history for this message
System Enablement Bot (system-enablement-ci-bot) wrote :
review: Approve (continuous-integration)
Revision history for this message
System Enablement Bot (system-enablement-ci-bot) wrote :
review: Approve (continuous-integration)
Revision history for this message
Simon Fels (morphis) :
review: Needs Fixing
Revision history for this message
Simon Fels (morphis) :
Revision history for this message
System Enablement Bot (system-enablement-ci-bot) wrote :
review: Approve (continuous-integration)
Revision history for this message
System Enablement Bot (system-enablement-ci-bot) wrote :
review: Approve (continuous-integration)
Revision history for this message
Simon Fels (morphis) :
Revision history for this message
System Enablement Bot (system-enablement-ci-bot) wrote :
review: Approve (continuous-integration)
Revision history for this message
Simon Fels (morphis) wrote :

LGTM

review: Approve
Revision history for this message
System Enablement Bot (system-enablement-ci-bot) wrote :
review: Approve (continuous-integration)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1diff --git a/.spread-reuse.22327.yaml b/.spread-reuse.22327.yaml
2new file mode 100644
3index 0000000..f54942f
4--- /dev/null
5+++ b/.spread-reuse.22327.yaml
6@@ -0,0 +1,9 @@
7+backends:
8+ qemu:
9+ systems:
10+ - ubuntu-core-16:
11+ username: test
12+ password: test
13+ address: localhost:59377
14+ data:
15+ pid: 22341
16diff --git a/cmd/client/cmd_wizard.go b/cmd/client/cmd_wizard.go
17index a8b9bb2..41dd538 100644
18--- a/cmd/client/cmd_wizard.go
19+++ b/cmd/client/cmd_wizard.go
20@@ -18,9 +18,11 @@ package main
21 import (
22 "bufio"
23 "bytes"
24+ "encoding/base64"
25 "encoding/json"
26 "fmt"
27 "log"
28+ "math/rand"
29 "net"
30 "net/http"
31 "os"
32@@ -28,8 +30,11 @@ import (
33 "regexp"
34 "strconv"
35 "strings"
36+ "time"
37 )
38
39+const DefaultPassworthLength = 16
40+
41 type wizardStep func(map[string]interface{}, *bufio.Reader, bool) error
42
43 // Go stores both IPv4 and IPv6 as [16]byte
44@@ -40,7 +45,7 @@ const ipv4Offset = net.IPv6len - net.IPv4len
45 var defaultIp = net.IPv4(10, 0, 60, 1)
46
47 // Utility function to read input and strip the trailing \n
48-func readUserInput(reader *bufio.Reader) string {
49+var readUserInput = func (reader *bufio.Reader) string {
50 ret, err := reader.ReadString('\n')
51 if err != nil {
52 panic(err)
53@@ -98,6 +103,22 @@ func findFreeSubnet(startIp net.IP) (net.IP, error) {
54 return curIp, nil
55 }
56
57+func generatePassword(length int) string {
58+ // base64 produces 4 byte for every 3 byte of input, rounded up
59+ password := make([]byte, length / 4 * 3 + 3)
60+ rand.Read(password)
61+ return base64.StdEncoding.EncodeToString(password)[:length]
62+}
63+
64+func askForPassword(reader *bufio.Reader) (string, error) {
65+ fmt.Print("Please enter the WPA2 passphrase: ")
66+ key := readUserInput(reader)
67+ if len(key) < 8 || len(key) > 63 {
68+ return "", fmt.Errorf("WPA2 passphrase must be between 8 and 63 characters")
69+ }
70+ return key, nil
71+}
72+
73 var allSteps = [...]wizardStep{
74 // determine the WiFi interface
75 func(configuration map[string]interface{}, reader *bufio.Reader, nonInteractive bool) error {
76@@ -150,7 +171,7 @@ var allSteps = [...]wizardStep{
77 // Select WiFi encryption type
78 func(configuration map[string]interface{}, reader *bufio.Reader, nonInteractive bool) error {
79 if nonInteractive {
80- configuration["wifi.security"] = "open"
81+ configuration["wifi.security"] = "wpa2"
82 return nil
83 }
84
85@@ -172,12 +193,18 @@ var allSteps = [...]wizardStep{
86 if configuration["wifi.security"] == "open" {
87 return nil
88 }
89- fmt.Print("Please enter the WPA2 passphrase: ")
90- key := readUserInput(reader)
91- if len(key) < 8 || len(key) > 63 {
92- return fmt.Errorf("WPA2 passphrase must be between 8 and 63 characters")
93+ if nonInteractive {
94+ // Generate a random 16 characters alphanumeric password
95+ configuration["wifi.security-passphrase"] = generatePassword(DefaultPassworthLength)
96+ return nil
97+ }
98+
99+ // Ask the user for a valid password (min 8, max 63 chars)
100+ if password, err := askForPassword(reader); err == nil {
101+ configuration["wifi.security-passphrase"] = password
102+ } else {
103+ return err
104 }
105- configuration["wifi.security-passphrase"] = key
106
107 return nil
108 },
109@@ -423,6 +450,8 @@ type wizardCommand struct {
110 }
111
112 func (cmd *wizardCommand) Execute(args []string) error {
113+ rand.Seed(time.Now().UnixNano())
114+
115 // Setup some sane default values, we don't ask the user for everything
116 configuration := make(map[string]interface{})
117
118diff --git a/cmd/client/cmd_wizard_test.go b/cmd/client/cmd_wizard_test.go
119new file mode 100644
120index 0000000..7bb7391
121--- /dev/null
122+++ b/cmd/client/cmd_wizard_test.go
123@@ -0,0 +1,62 @@
124+//
125+// Copyright (C) 2017 Canonical Ltd
126+//
127+// This program is free software: you can redistribute it and/or modify
128+// it under the terms of the GNU General Public License version 3 as
129+// published by the Free Software Foundation.
130+//
131+// This program is distributed in the hope that it will be useful,
132+// but WITHOUT ANY WARRANTY; without even the implied warranty of
133+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
134+// GNU General Public License for more details.
135+//
136+// You should have received a copy of the GNU General Public License
137+// along with this program. If not, see <http://www.gnu.org/licenses/>.
138+
139+package main
140+
141+import (
142+ "bufio"
143+ "math/rand"
144+ "strconv"
145+ "testing"
146+ "time"
147+
148+ . "gopkg.in/check.v1"
149+)
150+
151+// gopkg.in/check.v1 stuff
152+func TestWizard(t *testing.T) { TestingT(t) }
153+
154+type WizardSuite struct{}
155+
156+var _ = Suite(&WizardSuite{})
157+
158+func (s *WizardSuite) SetUpTest(c *C) {
159+ rand.Seed(time.Now().UnixNano())
160+}
161+
162+func mockUserInput(reply string) func (reader *bufio.Reader) string {
163+ return func (_ *bufio.Reader) string {
164+ return reply
165+ }
166+}
167+
168+var passRegExp = "[a-zA-Z0-9+/]{"+strconv.Itoa(DefaultPassworthLength)+"}"
169+
170+func (s *WizardSuite) TestPasswordGeneration(c *C) {
171+ password := generatePassword(DefaultPassworthLength)
172+ c.Assert(password, HasLen, DefaultPassworthLength)
173+ c.Assert(password, Matches, passRegExp)
174+
175+ readUserInput = mockUserInput("short")
176+ password, err := askForPassword(nil)
177+ c.Assert(err, NotNil)
178+
179+ readUserInput = mockUserInput("4/Valid+Passw0rd")
180+ password, err = askForPassword(nil)
181+ c.Assert(err, IsNil)
182+
183+ c.Assert(password, HasLen, DefaultPassworthLength)
184+ c.Assert(password, Matches, passRegExp)
185+}
186diff --git a/docs/basic-ap-setup.md b/docs/basic-ap-setup.md
187index b535699..6fe0a09 100644
188--- a/docs/basic-ap-setup.md
189+++ b/docs/basic-ap-setup.md
190@@ -13,6 +13,14 @@ $ wifi-ap.status
191
192 if the automatic configuration was successful and the access point is already active.
193
194+By default the automatic wizard, which runs when the wifi-ap snap is installed,
195+will choose secure enough default password and will enable WPA2-PSK security.
196+You can find the selected password when logged into
197+the system the wifi-ap snap installed on by running the command:
198+```
199+$ sudo wifi-ap.config get wifi.security-passphrase
200+```
201+
202 To enable the WiFi access point manually after the snap was installed and all plugs and slots are connected run the following command:
203
204 ```
205diff --git a/docs/installation.md b/docs/installation.md
206index 720cb19..720e9ba 100644
207--- a/docs/installation.md
208+++ b/docs/installation.md
209@@ -41,8 +41,8 @@ $ snap connect wifi-ap:network-manager network-manager:service
210 |------|-------|
211 | **WiFi SSID** | Ubuntu |
212 | **WiFi Interface mode** | direct |
213-| **WiFi Security** | open |
214-| **WiFi Security Passphrase ** | |
215+| **WiFi Security** | wpa2 |
216+| **WiFi Security Passphrase ** | Randomly chosen |
217 | **WiFi Channel** | 6 |
218 | **WiFi Network Interface** | wlan0 |
219 | **WiFi Address** | 192.168.7.1 |
220diff --git a/tests/lib/restore-each.sh b/tests/lib/restore-each.sh
221index b0d1902..0cfc960 100644
222--- a/tests/lib/restore-each.sh
223+++ b/tests/lib/restore-each.sh
224@@ -31,6 +31,10 @@ netplan generate
225 netplan apply
226
227 # remove and reinsert the module to refresh all the wifi network settings
228+pkill wpa_supplicant || true
229+while pidof wpa_supplicant; do
230+ sleep .5
231+done
232 rmmod mac80211_hwsim || true
233 modprobe mac80211_hwsim radios=2
234 wait_until_interface_is_available wlan0
235diff --git a/tests/lib/utilities.sh b/tests/lib/utilities.sh
236index 83f2e9e..9190e21 100644
237--- a/tests/lib/utilities.sh
238+++ b/tests/lib/utilities.sh
239@@ -45,3 +45,25 @@ install_snap_under_test() {
240 snap connect wifi-ap:firewall-control core
241 fi
242 }
243+
244+# Connects to a WiFi network
245+# args1: interface to use
246+connect_to_wifi() {
247+ local enc ssid pass
248+
249+ enc=$(/snap/bin/wifi-ap.config get wifi.security)
250+ ssid=$(/snap/bin/wifi-ap.config get wifi.ssid)
251+ if [ "$enc" = open ]; then
252+ iw "$1" connect "$ssid"
253+ else
254+ pass=$(/snap/bin/wifi-ap.config get wifi.security-passphrase)
255+ wpa_passphrase "$ssid" "$pass" >/tmp/wpa.conf
256+ wpa_supplicant -B -c/tmp/wpa.conf -i"$1"
257+
258+ # Need to wait for a full scan and WPA2 handshake
259+ for i in $(seq 60); do
260+ iw dev "$1" link |fgrep -xq 'Not connected.' || break
261+ sleep 1
262+ done
263+ fi
264+}
265diff --git a/tests/main/conf-wizard-auto-at-boot/task.yaml b/tests/main/conf-wizard-auto-at-boot/task.yaml
266index b042097..13d5394 100644
267--- a/tests/main/conf-wizard-auto-at-boot/task.yaml
268+++ b/tests/main/conf-wizard-auto-at-boot/task.yaml
269@@ -5,7 +5,9 @@ execute: |
270 test "$(/snap/bin/wifi-ap.config get disabled)" = false
271
272 test "$(/snap/bin/wifi-ap.config get wifi.interface)" = wlan0
273- test "$(/snap/bin/wifi-ap.config get wifi.security)" = open
274+ test "$(/snap/bin/wifi-ap.config get wifi.security)" = wpa2
275+ # Random 16 characters password, plus an ending line
276+ test "$(/snap/bin/wifi-ap.config get wifi.security-passphrase |wc -c)" -eq 17
277 test "$(/snap/bin/wifi-ap.config get wifi.ssid)" = Ubuntu
278 test "$(/snap/bin/wifi-ap.config get wifi.address)" = 10.0.60.1
279
280diff --git a/tests/main/conf-wizard-auto/task.yaml b/tests/main/conf-wizard-auto/task.yaml
281deleted file mode 100644
282index ae6219c..0000000
283--- a/tests/main/conf-wizard-auto/task.yaml
284+++ /dev/null
285@@ -1,23 +0,0 @@
286-summary: Verify that the automatic wizard works
287-
288-execute: |
289- # The automatic wizard was already started
290-
291- # Check that we get good default values
292- test "$(/snap/bin/wifi-ap.config get disabled)" = false
293-
294- test "$(/snap/bin/wifi-ap.config get wifi.interface)" = wlan0
295- test "$(/snap/bin/wifi-ap.config get wifi.security)" = open
296- test "$(/snap/bin/wifi-ap.config get wifi.ssid)" = Ubuntu
297- test "$(/snap/bin/wifi-ap.config get wifi.address)" = 10.0.60.1
298-
299- test "$(/snap/bin/wifi-ap.config get dhcp.range-start)" = 10.0.60.2
300- test "$(/snap/bin/wifi-ap.config get dhcp.range-stop)" = 10.0.60.199
301-
302- default_route=$(ip route |awk '/default/{print$5}')
303- if [ -n "$default_route" ]; then
304- test "$(/snap/bin/wifi-ap.config get share.disabled)" = false
305- test "$(/snap/bin/wifi-ap.config get share.network-interface)" = "$default_route"
306- else
307- test "$(/snap/bin/wifi-ap.config get share.disabled)" = true
308- fi
309diff --git a/tests/main/default-conf-brings-up-ap/task.yaml b/tests/main/default-conf-brings-up-ap/task.yaml
310index 6777c8d..28b9363 100644
311--- a/tests/main/default-conf-brings-up-ap/task.yaml
312+++ b/tests/main/default-conf-brings-up-ap/task.yaml
313@@ -14,12 +14,11 @@ execute: |
314 # There should be only a single network
315 network_count=`/snap/bin/wireless-tools.iw dev wlan1 scan | grep -c 'SSID: Ubuntu'`
316 test $network_count -eq 1
317- # The AP should not be secured by default
318- ! /snap/bin/wireless-tools.iw dev wlan1 scan | grep 'WPA:'
319- ! /snap/bin/wireless-tools.iw dev wlan1 scan | grep 'RSN:'
320+ # The AP should not be secured
321+ /snap/bin/wireless-tools.iw dev wlan1 scan | grep 'RSN:'
322
323 # Verify we can associate with the AP
324- /snap/bin/wireless-tools.iw wlan1 connect Ubuntu
325+ connect_to_wifi wlan1
326 /snap/bin/wireless-tools.iw dev wlan1 link | grep 'SSID: Ubuntu'
327
328 # And we should get an IP address assigned over DHCP
329diff --git a/tests/main/stress-ap-status-control/task.yaml b/tests/main/stress-ap-status-control/task.yaml
330index 89ded92..7f3b4cf 100644
331--- a/tests/main/stress-ap-status-control/task.yaml
332+++ b/tests/main/stress-ap-status-control/task.yaml
333@@ -10,6 +10,8 @@ prepare: |
334 snap connect wireless-tools:network-control core
335
336 execute: |
337+ . $TESTSLIB/utilities.sh
338+
339 # Bring up the access point first
340 /snap/bin/wifi-ap.config set disabled=false
341 until /snap/bin/wifi-ap.status | grep "ap.active: true" ; do
342@@ -60,8 +62,8 @@ execute: |
343 test $found_ap -eq 1
344
345 # Verify we can associate with the AP
346- sudo /snap/bin/wireless-tools.iw wlan1 connect Ubuntu
347- sudo /snap/bin/wireless-tools.iw dev wlan1 link | grep 'SSID: Ubuntu'
348+ connect_to_wifi wlan1
349+ /snap/bin/wireless-tools.iw dev wlan1 link | grep 'SSID: Ubuntu'
350
351 # We should only have one hostapd and one dnsmasq process at this time
352 # (we have to ignore the grep'ing process as otherwise we get a count of 2)
353diff --git a/tests/main/utf8-ssid/task.yaml b/tests/main/utf8-ssid/task.yaml
354index ad9e594..b4f53ae 100644
355--- a/tests/main/utf8-ssid/task.yaml
356+++ b/tests/main/utf8-ssid/task.yaml
357@@ -43,6 +43,5 @@ execute: |
358 test $network_count -eq 1
359
360 # Verify we can associate with the AP
361- /snap/bin/wireless-tools.iw wlan1 connect 'Ubuntu👍'
362+ connect_to_wifi wlan1
363 /snap/bin/wireless-tools.iw dev wlan1 link | fgrep 'SSID: Ubuntu\xf0\x9f\x91\x8d'
364-

Subscribers

People subscribed via source and target branches

to all changes: