Merge lp:~joergberroth/ubuntu-system-settings/wifi-802-1x-configurations into lp:ubuntu-system-settings

Proposed by JkB
Status: Superseded
Proposed branch: lp:~joergberroth/ubuntu-system-settings/wifi-802-1x-configurations
Merge into: lp:ubuntu-system-settings
Diff against target: 1255 lines (+927/-48)
9 files modified
plugins/wifi/CMakeLists.txt (+4/-0)
plugins/wifi/CertDialog.qml (+63/-0)
plugins/wifi/CertPicker.qml (+75/-0)
plugins/wifi/OtherNetwork.qml (+456/-42)
plugins/wifi/certhandler.cpp (+144/-0)
plugins/wifi/certhandler.h (+45/-0)
plugins/wifi/plugin.cpp (+3/-0)
plugins/wifi/wifidbushelper.cpp (+135/-5)
plugins/wifi/wifidbushelper.h (+2/-1)
To merge this branch: bzr merge lp:~joergberroth/ubuntu-system-settings/wifi-802-1x-configurations
Reviewer Review Type Date Requested Status
Matthew Paul Thomas design Pending
Jonas G. Drange Pending
Review via email: mp+258318@code.launchpad.net

This proposal supersedes a proposal from 2015-04-27.

This proposal has been superseded by a proposal from 2015-06-03.

Commit message

With 1392, I have added basic file picker functionality for choosing cert files.

It arises a general question: Where to store the cert files?

Network Manager (NM) allows to use to different schemes: blob and path [1].
If one uses blob NM parses the content and creates a file uuid-certtype.pem in
/userdata/system-data/etc/NetworkManager/system-connections/ .
At least a unique place to store them with the connection.
For path, a file:///... will be handed over and set in the network configuration.
In my first approach I have decided to use blob as the path scheme did not work for me on desktop environment. Haven't worked on that further.

Thus, at the moment there are three different ways to handle the cert data in the ui.
1. Copy cert content from clipboard
2. absolute path to cert file
3. Use ContentHub to choose file. The file will be stored in .local/share/ubuntu-system-settings/Documents/ . The file URL will be send back to ui.
All end up with parsing the content to NetworkManager as described above.

In general, if there is a general place to store the certs, a Menu should be implemented as propagated in [2]. This Menu than should point to all "installed" certs on the device (system or user).

---
[1] https://developer.gnome.org/NetworkManager/stable/ref-settings.html
[2] https://wiki.ubuntu.com/Networking#wi-fi-authentication-variations

Description of the change

Added support for 802-1x wireless network configurations.
now back on dialog.

To post a comment you must log in.
Revision history for this message
Jonas G. Drange (jonas-drange) wrote : Posted in a previous version of this proposal

This is really great. Thanks for proposing this.

I've added some comments, but they're mostly about your decision to make the Dialog an ItemPage. If this is not crucial to the implementation of support for 802-1x, we need to revert it.

Also, if cert picking is not implemented, please remove all components that are unused. Please leave the UI bits in, but hide it with "visible: showAllUI". This way we can get strings translated.

Thanks again.

review: Needs Fixing
Revision history for this message
JkB (joergberroth) wrote : Posted in a previous version of this proposal

> This is really great. Thanks for proposing this.
>
> I've added some comments, but they're mostly about your decision to make the
> Dialog an ItemPage. If this is not crucial to the implementation of support
> for 802-1x, we need to revert it.
>
> Also, if cert picking is not implemented, please remove all components that
> are unused. Please leave the UI bits in, but hide it with "visible:
> showAllUI". This way we can get strings translated.
>
> Thanks again.

Hey, thanks a lot for for reviewing.

First I had the concerns about pushing it to an ItemPage, too. Then, after dealing with the variety of different configurations, I found there would be an advantage if one changes to ItemPage. There is no need for the ItemPage from implementation point of view but there are configurations for which the user has to be asked up to two different certificates and an additional private key (TLS) and there can be different types of path2 authentication types for the different WPA Enterprise configurations.
So if we want the user to be able two choose all the different types of configurations, it seems to me that a dialog would get quite overloaded with ui inputs. And correct me if I'm wrong but scrolling, which certainly would be needed, seems not to be provided for the dialogs.
At the moment there are some pages in the cellular settings (e.g. APN) where one switched to ItemPages, too. So from design point of view it would keep consistent.

Maybe, based on these points, we can quickly discuss this again before I revert the change.

All other comments are clear. I will consider for the next commit.
I think the file picker would make selecting certificates even more comfortable but I will remove it as proposed, so one can work on that later.

Thanks again.

Joerg

Revision history for this message
Matthew Paul Thomas (mpt) wrote : Posted in a previous version of this proposal

Thanks so much for working on this, Joerg!

Jonas is right, though, that the authentication UI does need to remain a dialog. The reason is that System Settings is just one of three -- and will eventually be just one of six -- different places that might launch the UI for entering Wi-Fi details. The first-run setup "Connect to Wi-Fi" screen, and the network indicator menu, should let you connect to all the same Wi-Fi networks that System Settings does, by putting up the same dialog. <https://wiki.ubuntu.com/Networking#wi-fi-authenticating>

When dialog contents are bigger than the available screen space, the body is supposed to scroll automatically, and apparently this has been implemented already (bug 1376763). If it's not working, please report a bug.

review: Needs Fixing (design)
Revision history for this message
JkB (joergberroth) wrote : Posted in a previous version of this proposal

Thanks for the review and the hints.
It was not clear from documentation for me. But the bug post made it.
I just reverted the page back to dialog.

Am 2015-04-27 um 13:04 schrieb Matthew Paul Thomas:
> Review: Needs Fixing design
>
> Thanks so much for working on this, Joerg!
>
> Jonas is right, though, that the authentication UI does need to remain a dialog. The reason is that System Settings is just one of three -- and will eventually be just one of six -- different places that might launch the UI for entering Wi-Fi details. The first-run setup "Connect to Wi-Fi" screen, and the network indicator menu, should let you connect to all the same Wi-Fi networks that System Settings does, by putting up the same dialog. <https://wiki.ubuntu.com/Networking#wi-fi-authenticating>
>
> When dialog contents are bigger than the available screen space, the body is supposed to scroll automatically, and apparently this has been implemented already (bug 1376763). If it's not working, please report a bug.
>

Revision history for this message
Matthew Paul Thomas (mpt) wrote : Posted in a previous version of this proposal

Thank you.

review: Abstain (design)
Revision history for this message
Marcus Tomlinson (marcustomlinson) wrote : Posted in a previous version of this proposal

Your code isn't compiling. There are some weird "!==" occurrences in 2 of your .cpp files. Rather hard to test your changes work when the project doesn't compile no? :P

review: Needs Fixing
Revision history for this message
Jonas G. Drange (jonas-drange) wrote : Posted in a previous version of this proposal

Getting [1] when trying to build. Could you fix those? Thanks.

[1] http://pastebin.ubuntu.com/10989993/

review: Needs Fixing
Revision history for this message
Matthew Paul Thomas (mpt) wrote :

Yesterday, before I saw this new merge proposal, I was tackling the same question: "Where to store the cert files?" Also private key files and PAC files. On Ubuntu for PC, the current answer is in their own app, "Passwords and Keys". But on phones/tablets the overall system UI real estate is much smaller, so as with software updates and system version, this task fits best in System Settings.

This means the same conclusion (3) that you came to: storing the files in System Settings. "For this reason, System Settings should be set up as the default handler for certificates, private key files, and PAC files that you download or open, showing a confirmation dialog with info about the certificate/file and “Cancel” and “Save” buttons, and then lowering itself behind the previous app." <https://wiki.ubuntu.com/Networking#wi-fi-authentication-variations> I haven't designed those three dialogs in detail because I haven't yet found a reference for what data those files contain.

A later task will be to design+implement a way to remove previously-saved certificates/files inside System Settings.

1393. By JkB

Added CertificateHandling to list installed and add new certificates from OtherNetwork
Now uses ItemSelectors and dataModels. Certs can be added by calling ContentHub.

ToDos:
*improve list update for ItemSelectors
*Add handling for private keys and pac files.
*add password-flags
*add pac-Provisioning
*change? from blob to path scheme for nm configurations no that certs can be stored in a central place.

--- in wifi settings:
*Page (from PageComponents) to manage all installed certs and keys.

1394. By JkB

Improved certificate and key handling. List installed and add new certificates from OtherNetwork Dialog.
    Uses ItemSelectors and dataModels to select certs and keys. Certs and keys can be added by calling ContentHub.

    ToDos:
    *improve list update for ItemSelectors
    *Improve handling pac files.
    *change? from blob to path scheme for nm configurations no that certs can be stored in a central place.

    --- in wifi settings:
    *Page (from PageComponents) to manage all "installed" certs and keys.

1395. By JkB

Merge with trunk

1396. By JkB

merge with trunk.
Fixed bugs.

1397. By JkB

removed some bugs,
finally tested on my BQ Aquaris. At least for WPA and a WPA Enterprise TTLS/MCHAP2 connection.
Had no other networks around.

final changes:
*changed to path scheme for cert handling with networkmanager
*removed some further small bugs that made it finally work.

----
ToDos:
*Improve handling of pac Files.
*As suggested, cert and key managment for "installed" ones will be needed.
*Improve CertDialog not to show raw content of cert.
*Implement network encryption detection to use dialog for visible networks as well.

1398. By JkB

merge with trunk
----
*added checks against bad cert/key content
*improved data update.

1399. By JkB

OtherNetwork extensions mature now.
---
*improved Pac fIle handling.

1400. By JkB

*

1401. By JkB

formatting

1402. By JkB

* ItemSelectors: select back to "None" as standard for cases when filePicker is canceled.
* formatting
----
ToDo (later on):
- change selectedIndex to Item that has been added via ContentHub.

1403. By JkB

merge with trunk

1404. By JkB

* improve config handling
* fixed bug: added missing nul termination to successfully store certs with path scheme.

1405. By JkB

* added QStandardPaths for cert handling
* improved getting secrets in Previous network to get wpa-eap passwords as well.
* restored .bzrignore

1406. By JkB

merge with trunk

1407. By JkB

merged with jgdx merge proposal. Thanks a lot Jonas for the extensive format fixes!
+Also, considered some quickly managable FIXMEs from Jonas. Some stay.

1408. By JkB

* fixed wpa-eap/peap configurations.
* added "certificates recommended" security hint.

1409. By JkB

*merged with trunk

1410. By JkB

merge jonas branch

1411. By JkB

merge with trunk

1412. By JkB

* set feedback back to original implementation

1413. By JkB

merge Jonas fixmes

1414. By JkB

clear spaces

1415. By JkB

merge with trunk

1416. By JkB

* multiple %1 args in i18n.tr all fall back to the first arg() provided.
Is this an individuell problem of my build?
If not we should consider this last commit.

1417. By JkB

* only show "using certificate.." hint if selected one == "None"

Unmerged revisions

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'plugins/wifi/CMakeLists.txt'
2--- plugins/wifi/CMakeLists.txt 2014-09-15 15:39:50 +0000
3+++ plugins/wifi/CMakeLists.txt 2015-05-12 23:13:53 +0000
4@@ -1,6 +1,8 @@
5 set(QML_SOURCES
6 AccessPoint.qml
7 BaseMenuItem.qml
8+CertPicker.qml
9+CertDialog.qml
10 Common.qml
11 DivMenuItem.qml
12 FramedMenuItem.qml
13@@ -23,10 +25,12 @@
14 plugin.cpp
15 unitymenumodelstack.cpp
16 previousnetworkmodel.cpp
17+ certhandler.cpp
18 wifidbushelper.h
19 plugin.h
20 unitymenumodelstack.h
21 previousnetworkmodel.h
22+ certhandler.cpp
23 nm_manager_proxy.h
24 nm_settings_proxy.h
25 nm_settings_connection_proxy.h
26
27=== added file 'plugins/wifi/CertDialog.qml'
28--- plugins/wifi/CertDialog.qml 1970-01-01 00:00:00 +0000
29+++ plugins/wifi/CertDialog.qml 2015-05-12 23:13:53 +0000
30@@ -0,0 +1,63 @@
31+import QtQuick 2.0
32+import QtQuick.Layouts 1.1
33+import Ubuntu.Components.Popups 0.1
34+import Ubuntu.Components 0.1
35+import Ubuntu.Components.ListItems 0.1 as ListItem
36+import Ubuntu.SystemSettings.Wifi 1.0
37+
38+Component {
39+
40+ Dialog {
41+ id: certDialog
42+
43+ property var certFileName;
44+
45+ anchors.fill: parent
46+
47+ title: i18n.tr("Add Certificate?")
48+
49+ CertificateHandler {
50+ id: certificateHandler
51+ }
52+
53+ TextArea {
54+ id : certContent
55+ objectName: "certContent"
56+ readOnly: true
57+ width: parent.width
58+ autoSize: true
59+ maximumLineCount: 7
60+ placeholderText: i18n.tr("No data available.")
61+ text: {certificateHandler.getCertContent(certDialog.certFileName).toString()}
62+ }
63+
64+ RowLayout {
65+ id: buttonRow
66+ anchors {
67+ left: parent.left
68+ right: parent.right
69+ }
70+ spacing: units.gu(2)
71+ height: cancelButton.height
72+
73+ Button {
74+ id: cancelButton
75+ text: i18n.tr("Cancel")
76+ onClicked: { certificateHandler.removeFile(certDialog.certFileName);
77+ PopupUtils.close(certDialog);
78+ }
79+ }
80+
81+ Button {
82+ id: saveButton
83+ text: i18n.tr("Add Certificate")
84+ enabled: (certDialog.certContent.text !== [])
85+ onClicked: { certificateHandler.moveCertFile(certDialog.certFileName);
86+ // just to be sure source file will be deleted if move was not successfull:
87+ certificateHandler.removeFile(certDialog.certFileName);
88+ PopupUtils.close(certDialog);
89+ }
90+ }
91+ }
92+ }
93+}
94
95=== added file 'plugins/wifi/CertPicker.qml'
96--- plugins/wifi/CertPicker.qml 1970-01-01 00:00:00 +0000
97+++ plugins/wifi/CertPicker.qml 2015-05-12 23:13:53 +0000
98@@ -0,0 +1,75 @@
99+import QtQuick 2.0
100+import QtQuick.Layouts 1.1
101+import Ubuntu.Components 0.1
102+import Ubuntu.Components.Popups 0.1
103+import Ubuntu.Content 0.1
104+
105+/* with a little help by looking into dekko mail client (lp:dekko) :*/
106+PopupBase {
107+ //visible: false
108+ id: picker
109+
110+ /* Picked Ffles will be stored in
111+ ~/.local/share/ubuntu-system-settings/Documents/
112+
113+ At this state of implementation, this store will be used to parse the file to
114+ Networkmanager.
115+ As I haven't found that it is yet decided where to store cert files in general, all certs will be stored
116+ by parsing the cert content to NM. NM then creates a file (UUID-certType.pem) in /userdata/system-data/etc/NetworkManager/system-connections/ .
117+ At least a unique place.
118+
119+ The files in ~/.local/share/ubuntu-system-settings/Documents/
120+ will not be deleted. Could be implemented later on.
121+ */
122+
123+
124+ signal fileImportSignal(var file)
125+ property var activeTransfer
126+
127+ Rectangle {
128+ anchors.fill: parent
129+
130+ ContentTransferHint {
131+ id: transferHint
132+ anchors.fill: parent
133+ activeTransfer: picker.activeTransfer
134+ }
135+
136+ ContentStore {
137+ id: appStore
138+ scope: ContentScope.App
139+ }
140+
141+ ContentPeerPicker {
142+ id: peerPicker
143+ anchors.fill: parent
144+ visible: true
145+ contentType: ContentType.Documents
146+ handler: ContentHandler.Source
147+ onPeerSelected: {
148+ peer.selectionType = ContentTransfer.Single;
149+ picker.activeTransfer = peer.request(appStore);
150+ }
151+ onCancelPressed: {
152+ PopupUtils.close(picker)
153+ }
154+ }
155+ }
156+
157+ Connections {
158+ target: picker.activeTransfer ? picker.activeTransfer : null
159+ onStateChanged: {
160+ if (picker.activeTransfer.state === ContentTransfer.Charged) {
161+ if (picker.activeTransfer.items.length > 0) {
162+ var fileUrl = picker.activeTransfer.items[0].url;
163+ picker.fileImportSignal(fileUrl.toString().replace("file://", ""));
164+ PopupUtils.close(picker);
165+ }
166+
167+ } else if (picker.activeTransfer.state === ContentTransfer.Aborted){
168+ PopupUtils.close(picker);
169+ }
170+ }
171+ }
172+
173+}
174
175=== modified file 'plugins/wifi/OtherNetwork.qml'
176--- plugins/wifi/OtherNetwork.qml 2015-01-09 08:47:53 +0000
177+++ plugins/wifi/OtherNetwork.qml 2015-05-12 23:13:53 +0000
178@@ -38,14 +38,16 @@
179 if(securityList.selectedIndex == 0) {
180 return true
181 }
182- if(securityList.selectedIndex == 1) {
183- return password.length >= 8
184+ if(securityList.selectedIndex == 3) {
185+
186+ // WEP
187+ return password.length === 5 ||
188+ password.length === 10 ||
189+ password.length === 13 ||
190+ password.length === 26;
191 }
192- // WEP
193- return password.length === 5 ||
194- password.length === 10 ||
195- password.length === 13 ||
196- password.length === 26;
197+ //WPA
198+ return password.length >= 8
199 }
200
201 title: i18n.tr("Connect to Hidden Network")
202@@ -66,6 +68,19 @@
203 target: connectButtonIndicator
204 running: true
205 }
206+
207+ PropertyChanges {
208+ target: p2authList
209+ enabled: false
210+ }
211+ PropertyChanges {
212+ target: p2authListLabel
213+ opacity: 0.5
214+ }
215+ PropertyChanges {
216+ target: cacertLabel
217+ opacity: 0.5
218+ }
219 PropertyChanges {
220 target: passwordVisibleSwitch
221 enabled: false
222@@ -79,7 +94,36 @@
223 enabled: false
224 }
225 PropertyChanges {
226- target: passwordListLabel
227+ target: passwordLabel
228+ opacity: 0.5
229+ }
230+ PropertyChanges {
231+ target: username
232+ enabled: false
233+ }
234+ PropertyChanges {
235+ target: usernameLabel
236+ opacity: 0.5
237+ }
238+ PropertyChanges {
239+ target: anonymousIdentity
240+ enabled: false
241+ }
242+ PropertyChanges {
243+ target: anonymousIdentityLabel
244+ opacity: 0.5
245+ }
246+ PropertyChanges {
247+ target: authList
248+ enabled: false
249+ opacity: 0.5
250+ }
251+ PropertyChanges {
252+ target: authListLabel
253+ opacity: 0.5
254+ }
255+ PropertyChanges {
256+ target: wepInsecureLabel
257 opacity: 0.5
258 }
259 PropertyChanges {
260@@ -102,6 +146,7 @@
261 PropertyChanges {
262 target: feedback
263 enabled: true
264+ visible: true
265 }
266 },
267 State {
268@@ -109,6 +154,7 @@
269 PropertyChanges {
270 target: feedback
271 enabled: true
272+ visible: true
273 }
274 },
275 State {
276@@ -117,10 +163,7 @@
277 target: successIndicator
278 running: true
279 }
280- PropertyChanges {
281- target: cancelButton
282- enabled: false
283- }
284+
285 PropertyChanges {
286 target: connectAction
287 enabled: false
288@@ -142,7 +185,7 @@
289 text : i18n.tr("Network name")
290 objectName: "networknameLabel"
291 fontSize: "medium"
292- font.bold: true
293+ font.bold: false
294 color: Theme.palette.selected.backgroundText
295 elide: Text.ElideRight
296 }
297@@ -150,6 +193,8 @@
298 TextField {
299 id : networkname
300 objectName: "networkname"
301+ width: parent.width
302+ placeholderText: i18n.tr("SSID")
303 inputMethodHints: Qt.ImhNoPredictiveText
304 Component.onCompleted: forceActiveFocus()
305 }
306@@ -159,7 +204,7 @@
307 text : i18n.tr("Security")
308 objectName: "securityListLabel"
309 fontSize: "medium"
310- font.bold: true
311+ font.bold: false
312 color: Theme.palette.selected.backgroundText
313 elide: Text.ElideRight
314 }
315@@ -167,18 +212,348 @@
316 ListItem.ItemSelector {
317 id: securityList
318 objectName: "securityList"
319- model: [i18n.tr("None"), // index: 0
320- i18n.tr("WPA & WPA2 Personal"), // index: 1
321- i18n.tr("WEP"), // index: 2
322- ]
323- }
324-
325- Label {
326- id: passwordListLabel
327- text : i18n.tr("Password")
328+ model: [i18n.tr("None"), // index: 0
329+ i18n.tr("WPA & WPA2 Personal"), // index: 1
330+ i18n.tr("WPA & WPA2 Enterprise"),// index: 2
331+ i18n.tr("WEP"), // index: 3
332+ i18n.tr("Dynamic WEP (802.1x)"), // index: 4
333+ i18n.tr("LEAP"), // index: 5
334+ ]
335+ selectedIndex: 1
336+ }
337+
338+ Label {
339+ id: wepInsecureLabel
340+ objectName: "wepInsecureLabel"
341+ color: "red"
342+ text: i18n.tr("This network is insecure.")
343+ visible: ( securityList.selectedIndex == 3)
344+ }
345+
346+ Label {
347+ id: authListLabel
348+ text : i18n.tr("Authentication")
349+ objectName: "authListLabel"
350+ fontSize: "medium"
351+ font.bold: false
352+ color: Theme.palette.selected.backgroundText
353+ elide: Text.ElideRight
354+ visible: ( securityList.selectedIndex == 2 || securityList.selectedIndex == 4)
355+ }
356+
357+ ListItem.ItemSelector {
358+ id: authList
359+ objectName: "authList"
360+ model: [i18n.tr("TLS"), // index: 0
361+ i18n.tr("TTLS"), // index: 1
362+ i18n.tr("LEAP"), // index: 2
363+ i18n.tr("FAST"), // index: 3
364+ i18n.tr("PEAP"), // index: 4
365+ ]
366+ visible: ( securityList.selectedIndex == 2 || securityList.selectedIndex == 4)
367+ }
368+
369+ Label {
370+ id: p2authListLabel
371+ text : i18n.tr("Inner authentication")
372+ objectName: "p2authLabel"
373+ fontSize: "medium"
374+ font.bold: false
375+ color: Theme.palette.selected.backgroundText
376+ elide: Text.ElideRight
377+ visible: ( securityList.selectedIndex == 2 || securityList.selectedIndex == 4) // WPA or D-WEP
378+ && ( authList.selectedIndex == 1 ||
379+ authList.selectedIndex == 3 ||
380+ authList.selectedIndex == 4 )
381+ }
382+
383+ ListItem.ItemSelector {
384+ id: p2authList
385+ objectName: "p2authList"
386+ width: parent.width
387+ model: [i18n.tr("PAP"), // index: 0
388+ i18n.tr("MSCHAPv2"), // index: 1
389+ i18n.tr("MSCHAP"), // index: 2
390+ i18n.tr("CHAP"), // index: 3
391+ i18n.tr("GTC"), // index: 4
392+ i18n.tr("MD5") // index: 5
393+ ]
394+ visible: ( securityList.selectedIndex == 2 || securityList.selectedIndex == 4) // WPA or D-WEP
395+ && ( authList.selectedIndex == 1 ||
396+ authList.selectedIndex == 3 ||
397+ authList.selectedIndex == 4 )
398+ }
399+
400+ Label {
401+ id: cacertLabel
402+ text : i18n.tr("CA Certificate")
403+ objectName: "cacertListLabel"
404+ fontSize: "medium"
405+ font.bold: false
406+ color: Theme.palette.selected.backgroundText
407+ visible: ( securityList.selectedIndex == 2 || securityList.selectedIndex == 4) // WPA or D-WEP
408+ && ( authList.selectedIndex == 0 ||
409+ authList.selectedIndex == 1 ||
410+ authList.selectedIndex == 3 )
411+ }
412+
413+ ListItem.ItemSelector {
414+ id: cacertSelector
415+ anchors {
416+ left: parent.left
417+ right: parent.right
418+ }
419+ visible: ( securityList.selectedIndex == 2 || securityList.selectedIndex == 4) // WPA or D-WEP
420+ && ( authList.selectedIndex == 0 ||
421+ authList.selectedIndex == 1 ||
422+ authList.selectedIndex == 3 )
423+ model: cacertListModel
424+ expanded: false
425+ delegate: certSelectorDelegate
426+ selectedIndex: 0
427+ property string cacertFileName : { if(cacertSelector.selectedIndex !== 0 &&
428+ cacertSelector.selectedIndex !== (certListModel.rowCount()-1)){
429+ certListModel.getfileName(cacertSelector.selectedIndex)
430+ } else {"";}
431+ }
432+ onSelectedIndexChanged: {
433+ cacertListModel.dataupdate();
434+ if (cacertSelector.selectedIndex === cacertListModel.rowCount()-1){
435+ var pickerDialog = PopupUtils.open(Qt.resolvedUrl("./CertPicker.qml"));
436+ pickerDialog.fileImportSignal.connect(function(file){
437+ certDialogLoader.source = "./CertDialog.qml";
438+ PopupUtils.open(certDialogLoader.item, cacertSelector, {certFileName: file});
439+ });
440+ }
441+ }
442+
443+
444+ }
445+
446+ Component{
447+ id: certSelectorDelegate
448+ OptionSelectorDelegate { text: CommonName;
449+ subText:(CommonName != "None" && CommonName != "Choose file…") ?
450+ (Organization +", Exp.date: " + expiryDate) : ""
451+ }
452+ }
453+ CertificateListModel {
454+ id: cacertListModel
455+ }
456+
457+ Loader{
458+ id: certDialogLoader
459+ asynchronous: false
460+ }
461+
462+ Label {
463+ id: usercertLabel
464+ text : i18n.tr("Client Certificate")
465+ objectName: "usercertLabel"
466+ fontSize: "medium"
467+ font.bold: false
468+ color: Theme.palette.selected.backgroundText
469+ visible: ( securityList.selectedIndex == 2 || securityList.selectedIndex == 4)
470+ && ( authList.selectedIndex == 0 ) // only for TLS
471+
472+ }
473+
474+ ListItem.ItemSelector {
475+ id: usercertSelector
476+ anchors {
477+ left: parent.left
478+ right: parent.right
479+ }
480+ visible: ( securityList.selectedIndex == 2 || securityList.selectedIndex == 4)
481+ && ( authList.selectedIndex == 0 ) // only for TLS
482+ model: cacertListModel
483+ expanded: false
484+ delegate: certSelectorDelegate
485+ selectedIndex: 0
486+ property string usercertFileName: { if(usercertFileName.selectedIndex !== 0 &&
487+ usercertFileName.selectedIndex !== (certListModel.rowCount()-1)){
488+ certListModel.getfileName(usercertFileName.selectedIndex)
489+ } else {"";}
490+ }
491+ onSelectedIndexChanged: {
492+ if (usercertSelector.selectedIndex === cacertListModel.rowCount()-1){
493+ var pickerDialog = PopupUtils.open(Qt.resolvedUrl("./CertPicker.qml"));
494+ pickerDialog.fileImportSignal.connect(function(file){
495+ });
496+ }
497+ }
498+ }
499+
500+ /*CertificateListModel {
501+ id: usercertListModel
502+ }*/
503+
504+ RowLayout{
505+ spacing: units.gu(4)
506+ anchors {
507+ left: parent.left
508+ right: parent.right
509+ }
510+ visible: ( securityList.selectedIndex == 2 || securityList.selectedIndex == 4)
511+ && ( authList.selectedIndex == 0 ) // only for TLS
512+
513+ Label {
514+ id: userprivatekeyLabel
515+ text : i18n.tr("User Private Key")
516+ objectName: "userprivatekeyLabel"
517+ fontSize: "medium"
518+ font.bold: false
519+ color: Theme.palette.selected.backgroundText
520+ anchors.bottom: adduserprivatekeyButton.bottom
521+ }
522+
523+ Button {
524+ id: adduserprivatekeyButton
525+ visible: true
526+ objectName: "adduserprivatekeyButton"
527+ anchors.right: parent.right
528+ text: i18n.tr("Choose file…")
529+ onClicked: {
530+ var pickerDialog = PopupUtils.open(Qt.resolvedUrl("./CertPicker.qml"));
531+ pickerDialog.fileImportSignal.connect(function(file){
532+ userprivatekey.text = file;
533+ });
534+ }
535+ }
536+ }
537+
538+ TextArea {
539+ id : userprivatekey
540+ objectName: "userprivatekey"
541+ visible: ( securityList.selectedIndex == 2 || securityList.selectedIndex == 4)
542+ && ( authList.selectedIndex == 0 )
543+ width: parent.width
544+ autoSize: true
545+ maximumLineCount: 4
546+ placeholderText: i18n.tr("Absolute path to key or clipboard content")
547+ }
548+
549+ Column{ // pacFile
550+ id: pacFileColumn
551+ anchors {
552+ left: parent.left
553+ right: parent.right
554+ }
555+ spacing: parent.spacing
556+
557+ visible: ( securityList.selectedIndex == 2 || securityList.selectedIndex == 4)
558+ && ( authList.selectedIndex == 3 )
559+
560+ RowLayout{
561+ spacing: units.gu(4)
562+ anchors {
563+ left: parent.left
564+ right: parent.right
565+ }
566+
567+ Label {
568+ id: pacFileLabel
569+ text : i18n.tr("Pac File")
570+ objectName: "pacFileLabel"
571+ fontSize: "medium"
572+ font.bold: false
573+ color: Theme.palette.selected.backgroundText
574+ anchors.bottom: adduserprivatekeyButton.bottom
575+ }
576+
577+ Button {
578+ id: addpacFileButton
579+ visible: true
580+ objectName: "addpacFileButton"
581+ anchors.right: parent.right
582+ text: i18n.tr("Choose file…")
583+ onClicked: {
584+ var pickerDialog = PopupUtils.open(Qt.resolvedUrl("./CertPicker.qml"));
585+ pickerDialog.fileImportSignal.connect(function(file){
586+ PopupUtils.open(Qt.resolvedUrl("./CertDialog.qml"), {certContentText: file}); // pacFile.text = file;
587+ });
588+ }
589+ }
590+ }
591+
592+ TextArea {
593+ id : pacFile
594+ objectName: "pacFile"
595+ width: parent.width
596+ autoSize: true
597+ maximumLineCount: 4
598+ placeholderText: i18n.tr("Absolute path to Pac File or clipboard content")
599+ }
600+
601+ }
602+
603+ Label {
604+ id: anonymousIdentityLabel
605+ text : i18n.tr("Anonymous identity")
606+ objectName: "anonymousIdentityLabel"
607+ fontSize: "medium"
608+ font.bold: false
609+ color: Theme.palette.selected.backgroundText
610+ visible: ( securityList.selectedIndex == 2 && authList.selectedIndex != 2 )
611+ }
612+
613+ TextField {
614+ id : anonymousIdentity
615+ objectName: "anonymousIdentity"
616+ width: parent.width
617+ visible: ( securityList.selectedIndex == 2 && authList.selectedIndex != 2 )
618+ inputMethodHints: Qt.ImhNoPredictiveText
619+ Component.onCompleted: forceActiveFocus()
620+ onAccepted: {
621+ connectAction.trigger()
622+ }
623+ }
624+
625+ Label {
626+ id: usernameLabel
627+ text : {
628+ if ( ( securityList.selectedIndex == 2 || securityList.selectedIndex == 4)
629+ && ( authList.selectedIndex == 0 )) {
630+ i18n.tr("Identity")
631+ }
632+ else {
633+ i18n.tr("Username")
634+ }
635+ }
636+ objectName: "usernameLabel"
637+ fontSize: "medium"
638+ font.bold: false
639+ color: Theme.palette.selected.backgroundText
640+ elide: Text.ElideRight
641+ visible: ( securityList.selectedIndex == 2 || securityList.selectedIndex == 4 || securityList.selectedIndex == 5)
642+ }
643+
644+ TextField {
645+ id : username
646+ objectName: "username"
647+ width: parent.width
648+ visible: ( securityList.selectedIndex == 2 || securityList.selectedIndex == 4 || securityList.selectedIndex == 5)
649+ inputMethodHints: Qt.ImhNoPredictiveText
650+ Component.onCompleted: forceActiveFocus()
651+ onAccepted: {
652+ connectAction.trigger()
653+ }
654+ }
655+
656+ Label {
657+ id: passwordLabel
658+ text: {
659+ if ( ( securityList.selectedIndex == 2 || securityList.selectedIndex == 4)
660+ && ( authList.selectedIndex == 0 )) {
661+ i18n.tr("Private Key Password")
662+ } else {
663+ i18n.tr("Password")
664+ }
665+ }
666+
667 objectName: "passwordListLabel"
668 fontSize: "medium"
669- font.bold: true
670+ font.bold: false
671 color: Theme.palette.selected.backgroundText
672 elide: Text.ElideRight
673 visible: securityList.selectedIndex !== 0
674@@ -187,16 +562,17 @@
675 TextField {
676 id : password
677 objectName: "password"
678+ width: parent.width
679 visible: securityList.selectedIndex !== 0
680 echoMode: passwordVisibleSwitch.checked ?
681- TextInput.Normal : TextInput.Password
682+ TextInput.Normal : TextInput.Password
683 inputMethodHints: Qt.ImhNoPredictiveText
684 onAccepted: {
685 connectAction.trigger();
686 }
687 }
688
689- Row {
690+ Row {
691 id: passwordVisiblityRow
692 layoutDirection: Qt.LeftToRight
693 spacing: units.gu(2)
694@@ -204,7 +580,7 @@
695
696 CheckBox {
697 id: passwordVisibleSwitch
698- activeFocusOnPress: false
699+ //activeFocusOnPress: false
700 }
701
702 Label {
703@@ -222,10 +598,44 @@
704 }
705 onClicked: {
706 passwordVisibleSwitch.checked =
707- !passwordVisibleSwitch.checked
708- }
709- }
710- }
711+ !passwordVisibleSwitch.checked
712+ }
713+ }
714+ }
715+ }
716+
717+ Row {
718+ id: passwordRememberRow
719+ layoutDirection: Qt.LeftToRight
720+ spacing: units.gu(2)
721+ visible: false
722+ //( authList.selectedIndex == 1 || authList.selectedIndex == 3 || authList.selectedIndex == 4)
723+ //not implemented yet.
724+ CheckBox {
725+ id: passwordRememberSwitch
726+ //activeFocusOnPress: false
727+ }
728+
729+ Label {
730+ id: passwordRememberLabel
731+ text : i18n.tr("Remember password")
732+ objectName: "passwordRememberLabel"
733+ fontSize: "medium"
734+ color: Theme.palette.selected.backgroundText
735+ elide: Text.ElideRight
736+ height: passwordRememberSwitch.height
737+ verticalAlignment: Text.AlignVCenter
738+ MouseArea {
739+ anchors {
740+ fill: parent
741+ }
742+ onClicked: {
743+ passwordRememberSwitch.checked =
744+ !passwordRememberSwitch.checked
745+ }
746+ }
747+ }
748+
749 }
750
751 RowLayout {
752@@ -287,9 +697,13 @@
753 enabled: settingsValid()
754 onTriggered: {
755 DbusHelper.connect(
756- networkname.text,
757- securityList.selectedIndex,
758- password.text);
759+ networkname.text,
760+ securityList.selectedIndex,
761+ authList.selectedIndex,
762+ [username.text, anonymousIdentity.text],
763+ password.text,
764+ [cacertSelector.cacertFileName, usercertSelector.usercertFileName, userprivatekey.text, pacFile.text] ,
765+ p2authList.selectedIndex);
766 otherNetworkDialog.state = "CONNECTING";
767 }
768 }
769@@ -321,15 +735,15 @@
770 */
771 if (otherNetworkDialog.state === "CONNECTING") {
772 switch (newState) {
773- case 120:
774- feedback.text = common.reasonToString(reason);
775- otherNetworkDialog.state = "FAILED";
776- break;
777- case 100:
778- /* connection succeeded only if it was us that
779+ case 120:
780+ feedback.text = common.reasonToString(reason);
781+ otherNetworkDialog.state = "FAILED";
782+ break;
783+ case 100:
784+ /* connection succeeded only if it was us that
785 created it */
786- otherNetworkDialog.state = "SUCCEEDED";
787- break;
788+ otherNetworkDialog.state = "SUCCEEDED";
789+ break;
790 }
791 }
792 }
793
794=== added file 'plugins/wifi/certhandler.cpp'
795--- plugins/wifi/certhandler.cpp 1970-01-01 00:00:00 +0000
796+++ plugins/wifi/certhandler.cpp 2015-05-12 23:13:53 +0000
797@@ -0,0 +1,144 @@
798+#include "certhandler.h"
799+
800+#include <QtQml>
801+#include <QtQml/QQmlContext>
802+#include <QtDebug>
803+#include <QObject>
804+#include <QSslCertificate>
805+#include <QAbstractListModel>
806+#include <QDir>
807+
808+#define CERTS_PATH "/home/phablet/.local/share/ubuntu-system-settings/Documents/" //<----to be changed #jkb
809+#define KEYS_PATH "/home/phablet/.local/share/ubuntu-system-settings/Documents/"
810+/*
811+CERTS_PATH points to the certificates directory.
812+Later on should/could be .../ubuntu-system-settings/wifi/ssl/certs
813+CA and client to be stored here.
814+and KEYS_PATH to private keys
815+Cold be .../ubuntu-system-settings/wifi/ssl/keys
816+
817+Same for pac files?
818+*/
819+
820+QByteArray CertificateHandler::getCertContent(QString filename){
821+ QFile file(filename);
822+ if (!file.open(QIODevice::ReadOnly)) {
823+ qWarning() << "Could not resolve Cert-File (" << filename << "): File does not exist or is empty." ;
824+ return QByteArray();
825+ }
826+ else {
827+ return file.readAll();
828+ }
829+}
830+
831+QString CertificateHandler::moveCertFile(QString filename){
832+ QDir certPath(CERTS_PATH);
833+ if (!certPath.exists(CERTS_PATH)){
834+ certPath.mkpath(CERTS_PATH);
835+ }
836+ QFile file(filename);
837+ QByteArray certificate = getCertContent(filename);
838+ QList<QSslCertificate> SslCertificate = QSslCertificate::fromData(certificate, QSsl::Pem);
839+ QStringList subject = SslCertificate[0].subjectInfo(QSslCertificate::CommonName);
840+ QString modFileName = CERTS_PATH+subject[0]+".pem";
841+ if(file.rename(modFileName.replace(" ", "_"))){
842+ return file.fileName();
843+ } else {
844+ return "Error storing certificate." ;
845+ }
846+}
847+
848+bool CertificateHandler::removeFile(QString filename){
849+ QFile file(filename);
850+ return file.remove();
851+}
852+
853+
854+struct CertificateListModel::Private {
855+ QStringList data;
856+};
857+
858+CertificateListModel::CertificateListModel(QObject *parent) : QAbstractListModel(parent) {
859+ p = new CertificateListModel::Private();
860+ QStringList nameFilter("*.pem");
861+ QDir directory(CERTS_PATH);
862+ QStringList files = directory.entryList(nameFilter);
863+ files.sort(Qt::CaseInsensitive);
864+ files.insert(0, "None");
865+ files.append("Choose file…");
866+ p->data = files;
867+}
868+
869+CertificateListModel::~CertificateListModel() {
870+ delete p;
871+}
872+
873+QHash<int, QByteArray> CertificateListModel::roleNames() const {
874+ QHash<int, QByteArray> roles;
875+ roles[CNRole] = "CommonName";
876+ roles[ORole] = "Organization";
877+ roles[expDateRole] = "expiryDate";
878+
879+ //roles[certFileNameRole] = "certFileName";
880+ //...more if needed see QSslCertificate::SubjectInfo
881+ return roles;
882+}
883+
884+int CertificateListModel::rowCount(const QModelIndex &/*parent*/) const {
885+ return p->data.size();
886+}
887+
888+QString CertificateListModel::getfileName(const int selectedIndex) const {
889+ return CERTS_PATH + p->data[selectedIndex];
890+}
891+
892+void CertificateListModel::dataupdate(){
893+ beginResetModel();
894+ p->data.clear();
895+ QStringList nameFilter("*.pem");
896+ QDir directory(CERTS_PATH);
897+ QStringList files = directory.entryList(nameFilter);
898+ files.sort(Qt::CaseInsensitive);
899+ files.insert(0, "None");
900+ files.append("Choose file…");
901+ p->data = files;
902+ endResetModel();
903+}
904+
905+QVariant CertificateListModel::data(const QModelIndex &index, int role) const {
906+ if(!index.isValid() || index.row() >= ( p->data.size()) ) {
907+ return QVariant();
908+ } else if (index.row() == 0){
909+ const QString &row0 = p->data[index.row()];
910+
911+ switch(role) {
912+ case CNRole : return row0;
913+ case ORole : return "";
914+ case expDateRole : return "";
915+ //case certFileNameRole : return "";
916+ }
917+ } else if (index.row() == p->data.size()-1){
918+ const QString &rowend = p->data[index.row()];
919+
920+ switch(role) {
921+ case CNRole : return rowend;
922+ case ORole : return "";
923+ case expDateRole : return "";
924+ //case certFileNameRole : return "";
925+ }
926+ }
927+
928+ const QString &row = CERTS_PATH+p->data[index.row()];
929+ QList<QSslCertificate> certificate = QSslCertificate::fromPath(row, QSsl::Pem, QRegExp::Wildcard);
930+
931+ switch(role) {
932+
933+ case CNRole : return certificate[0].subjectInfo(QSslCertificate::CommonName)[0];
934+ case ORole : return certificate[0].subjectInfo(QSslCertificate::Organization)[0];
935+ case expDateRole : return certificate[0].expiryDate().toString("dd.MM.yyyy");
936+ //case certFileNameRole : return row;
937+
938+ default : return QVariant();
939+
940+ }
941+}
942
943=== added file 'plugins/wifi/certhandler.h'
944--- plugins/wifi/certhandler.h 1970-01-01 00:00:00 +0000
945+++ plugins/wifi/certhandler.h 2015-05-12 23:13:53 +0000
946@@ -0,0 +1,45 @@
947+#ifndef CERTHANDLER_H
948+#define CERTHANDLER_H
949+
950+#include <QtQml>
951+#include <QtQml/QQmlContext>
952+#include <QObject>
953+#include <QAbstractListModel>
954+
955+class CertificateHandler : public QObject
956+{
957+ Q_OBJECT
958+public:
959+ Q_INVOKABLE QByteArray getCertContent(QString filename);
960+ Q_INVOKABLE QString moveCertFile(QString filename);
961+ Q_INVOKABLE bool removeFile(QString filename);
962+};
963+
964+
965+
966+class CertificateListModel : public QAbstractListModel
967+{
968+ Q_OBJECT
969+
970+public:
971+ enum CertificateListRoles {
972+ CNRole = Qt::UserRole + 1,
973+ ORole,
974+ expDateRole,
975+ //certFileNameRole,
976+ };
977+
978+ explicit CertificateListModel(QObject *parent = 0);
979+ ~CertificateListModel();
980+ QHash<int, QByteArray> roleNames() const;
981+ Q_INVOKABLE int rowCount(const QModelIndex &parent = QModelIndex()) const;
982+ Q_INVOKABLE QString getfileName(const int selectedIndex) const;
983+ Q_INVOKABLE void dataupdate();
984+ QVariant data(const QModelIndex &index, int role) const;
985+private:
986+ struct Private;
987+ Private *p;
988+
989+};
990+#endif // CERTHANDLER_H
991+
992
993=== modified file 'plugins/wifi/plugin.cpp'
994--- plugins/wifi/plugin.cpp 2014-07-23 13:53:48 +0000
995+++ plugins/wifi/plugin.cpp 2015-05-12 23:13:53 +0000
996@@ -22,6 +22,7 @@
997 #include "unitymenumodelstack.h"
998 #include "wifidbushelper.h"
999 #include "previousnetworkmodel.h"
1000+#include "certhandler.h"
1001
1002 namespace {
1003
1004@@ -45,6 +46,8 @@
1005 qmlRegisterType<UnityMenuModelStack>(uri, 1, 0, "UnityMenuModelStack");
1006 qmlRegisterSingletonType<WifiDbusHelper>(uri, 1, 0, "DbusHelper", dbusProvider);
1007 qmlRegisterType<PreviousNetworkModel>(uri, 1, 0, "PreviousNetworkModel");
1008+ qmlRegisterType<CertificateListModel>(uri, 1, 0, "CertificateListModel");
1009+ qmlRegisterType<CertificateHandler>(uri, 1, 0, "CertificateHandler");
1010 }
1011
1012 void BackendPlugin::initializeEngine(QQmlEngine *engine, const char *uri)
1013
1014=== modified file 'plugins/wifi/wifidbushelper.cpp'
1015--- plugins/wifi/wifidbushelper.cpp 2014-10-10 14:10:52 +0000
1016+++ plugins/wifi/wifidbushelper.cpp 2015-05-12 23:13:53 +0000
1017@@ -37,15 +37,29 @@
1018 typedef QMap<QString,QVariantMap> ConfigurationData;
1019 Q_DECLARE_METATYPE(ConfigurationData)
1020
1021+
1022 WifiDbusHelper::WifiDbusHelper(QObject *parent) : QObject(parent),
1023 m_systemBusConnection(QDBusConnection::systemBus())
1024 {
1025 qDBusRegisterMetaType<ConfigurationData>();
1026 }
1027
1028-void WifiDbusHelper::connect(QString ssid, int security, QString password)
1029+
1030+QByteArray WifiDbusHelper::getCertContent(QString filename){
1031+ QFile file(filename);
1032+ if (!file.open(QIODevice::ReadOnly)) {
1033+ qWarning() << "Could not resolve Cert-File (" << filename << "): File does not exist or is empty." ;
1034+ return QByteArray();
1035+ }
1036+ else {
1037+ return file.readAll();
1038+ }
1039+}
1040+
1041+
1042+void WifiDbusHelper::connect(QString ssid, int security, int auth, QStringList usernames, QString password, QStringList certs, int p2auth)
1043 {
1044- if(security<0 || security>2) {
1045+ if((security<0 || security>5) || (auth<0 || auth>4) || (p2auth<0 || p2auth>5)) {
1046 qWarning() << "Qml and C++ have gotten out of sync. Can't connect.\n";
1047 return;
1048 }
1049@@ -66,8 +80,11 @@
1050 // security:
1051 // 0: None
1052 // 1: WPA & WPA2 Personal
1053- // 2: WEP
1054- if (security != 0) {
1055+ // 2: WPA Enterprise
1056+ // 3: WEP
1057+ // 4: Dynamic WEP
1058+ // 5: LEAP
1059+ if (security != 0) { // WPA Enterprise or Dynamic WEP
1060 wireless["security"] = QStringLiteral("802-11-wireless-security");
1061
1062 QVariantMap wireless_security;
1063@@ -75,17 +92,124 @@
1064 if (security == 1) {
1065 wireless_security["key-mgmt"] = QStringLiteral("wpa-psk");
1066 wireless_security["psk"] = password;
1067- } else if (security == 2) {
1068+ } else if (security == 3) {
1069 wireless_security["key-mgmt"] = QStringLiteral("none");
1070 wireless_security["auth-alg"] = QStringLiteral("open");
1071 wireless_security["wep-key0"] = password;
1072 wireless_security["wep-key-type"] = QVariant(uint(1));
1073+ } else if (security == 2) {
1074+ wireless_security["key-mgmt"] = QStringLiteral("wpa-eap");
1075+ } else if (security == 4) {
1076+ wireless_security["key-mgmt"] = QStringLiteral("ieee8021x");
1077+ /* leave disabled as hopefully not needed:
1078+ QStringList wep_pairwise, wep_group;
1079+ wep_pairwise[0] ="wep40"; wep_pairwise[1] ="wep104";
1080+ wep_group[0] ="wep40"; wep_group[1] ="wep104";
1081+ wireless_security["pairwise"] = wep_pairwise;
1082+ wireless_security["group"] = wep_group; */
1083+ } else if (security == 5) {
1084+ wireless_security["key-mgmt"] = QStringLiteral("ieee8021x");
1085+ wireless_security["auth-alg"] = QStringLiteral("leap");
1086+ wireless_security["leap-username"] = usernames[0];
1087+ wireless_security["leap-password"] = password;
1088 }
1089 configuration["802-11-wireless-security"] = wireless_security;
1090 }
1091
1092 configuration["802-11-wireless"] = wireless;
1093
1094+ if (security == 2 || security == 4){
1095+
1096+ QVariantMap wireless_802_1x;
1097+ // [802-1x]
1098+ /*TLS // index: 0
1099+ TTLS // index: 1
1100+ LEAP // index: 2
1101+ FAST // index: 3
1102+ PEAP // index: 4 */
1103+
1104+ wireless_802_1x["identity"] = usernames[0];
1105+ if (auth != 0) {
1106+ wireless_802_1x["password"] = password;
1107+ }
1108+
1109+ QByteArray cacert_a, clientcert, privatekey, pacFile;
1110+
1111+ if (certs[0].left(1) == "/"){
1112+ cacert_a = getCertContent(certs[0]);
1113+ }
1114+ else {
1115+ cacert_a.append(certs[0]);
1116+ }
1117+
1118+ if (auth == 0) { // TLS
1119+ wireless_802_1x["eap"] = QStringList("tls");
1120+ wireless_802_1x["ca-cert"] = cacert_a;
1121+
1122+ if (certs[1].left(1) == "/"){
1123+ clientcert = getCertContent(certs[1]);
1124+ }
1125+ else {
1126+ clientcert.append(certs[1]);
1127+ }
1128+ wireless_802_1x["client-cert"] = clientcert;
1129+ if (certs[2].left(1) == "/"){
1130+ privatekey = getCertContent(certs[2]);
1131+ }
1132+ else {
1133+ privatekey.append(certs[2]);
1134+ }
1135+ wireless_802_1x["private-key"] = privatekey;
1136+ wireless_802_1x["private-key-password"] = password;
1137+ } else if (auth == 1) { // TTLS
1138+ wireless_802_1x["eap"] = QStringList("ttls");
1139+ wireless_802_1x["ca-cert"] = cacert_a;
1140+ wireless_802_1x["anonymous-identity"] = usernames[1];
1141+ } else if (auth == 2) { // LEAP
1142+ wireless_802_1x["eap"] = QStringList("leap");
1143+ } else if (auth == 3) { // FAST
1144+ wireless_802_1x["eap"] = QStringList("fast");
1145+ wireless_802_1x["ca-cert"] = cacert_a;
1146+ wireless_802_1x["anonymous-identity"] = usernames[1];
1147+
1148+ if (certs[3].left(1) == "/"){
1149+ pacFile = getCertContent(certs[3]);
1150+ }
1151+ else {
1152+ pacFile.append(certs[3]);
1153+ }
1154+ wireless_802_1x["pac-file"] = pacFile;
1155+ // wireless_802_1x["phase1-fast-provisioning"] = QString("0");
1156+ } else if (auth == 4) { // PEAP
1157+ wireless_802_1x["eap"] = QStringList("peap");
1158+ wireless_802_1x["phase1-peaplabel"] = QString("1");
1159+ wireless_802_1x["anonymous-identity"] = usernames[1];
1160+ //wireless_802_1x["phase1-peapver"] = QString("0"); #jkb:let us unset this until problems are reported.
1161+ }
1162+
1163+ if (auth == 1 || auth == 3 || auth == 4 ){ // only for TTLS, FAST and PEAP
1164+ /* PAP // index: 0
1165+ MSCHAPv2 // index: 1
1166+ MSCHAP // index: 2
1167+ CHAP // index: 3
1168+ GTC // index: 4
1169+ MD5 // index: 5 */
1170+ if (p2auth == 0) {
1171+ wireless_802_1x["phase2-auth"] = QStringLiteral("pap");
1172+ } else if (p2auth == 1) {
1173+ wireless_802_1x["phase2-auth"] = QStringLiteral("mschapv2");
1174+ } else if (p2auth == 2) {
1175+ wireless_802_1x["phase2-auth"] = QStringLiteral("mschap");
1176+ } else if (p2auth == 3) {
1177+ wireless_802_1x["phase2-auth"] = QStringLiteral("chap");
1178+ } else if (p2auth == 4) {
1179+ wireless_802_1x["phase2-auth"] = QStringLiteral("gtc");
1180+ } else if (p2auth == 5) {
1181+ wireless_802_1x["phase2-auth"] = QStringLiteral("md5");
1182+ }
1183+ }
1184+ configuration["802-1x"] = wireless_802_1x;
1185+ }
1186
1187 // find the first wlan adapter for now
1188 auto reply1 = mgr.GetDevices();
1189@@ -142,6 +266,7 @@
1190 }
1191 }
1192
1193+
1194 void WifiDbusHelper::nmDeviceStateChanged(uint newState,
1195 uint oldState,
1196 uint reason)
1197@@ -150,6 +275,7 @@
1198 Q_EMIT (deviceStateChanged(newState, reason));
1199 }
1200
1201+
1202 QString WifiDbusHelper::getWifiIpAddress()
1203 {
1204 OrgFreedesktopNetworkManagerInterface mgr(NM_SERVICE,
1205@@ -193,6 +319,7 @@
1206 return QString(inet_ntoa(ip_addr));
1207 }
1208
1209+
1210 struct Network : public QObject
1211 {
1212 struct DontCare : public std::exception {};
1213@@ -345,6 +472,7 @@
1214 QMap<QString, QVariantMap> settings;
1215 };
1216
1217+
1218 QList<QStringList> WifiDbusHelper::getPreviouslyConnectedWifiNetworks() {
1219 QList<QStringList> networks;
1220
1221@@ -383,6 +511,7 @@
1222 return networks;
1223 }
1224
1225+
1226 void WifiDbusHelper::forgetConnection(const QString dbus_path) {
1227 OrgFreedesktopNetworkManagerSettingsConnectionInterface bar
1228 (NM_SERVICE,
1229@@ -395,6 +524,7 @@
1230 }
1231 }
1232
1233+
1234 bool WifiDbusHelper::forgetActiveDevice() {
1235 OrgFreedesktopNetworkManagerInterface mgr(NM_SERVICE,
1236 NM_PATH,
1237
1238=== modified file 'plugins/wifi/wifidbushelper.h'
1239--- plugins/wifi/wifidbushelper.h 2014-10-10 14:10:52 +0000
1240+++ plugins/wifi/wifidbushelper.h 2015-05-12 23:13:53 +0000
1241@@ -37,7 +37,7 @@
1242 explicit WifiDbusHelper(QObject *parent = nullptr);
1243 ~WifiDbusHelper() {};
1244
1245- Q_INVOKABLE void connect(QString ssid, int security, QString password);
1246+ Q_INVOKABLE void connect(QString ssid, int security, int auth, QStringList usernames, QString password, QStringList certs, int p2auth);
1247 Q_INVOKABLE QList<QStringList> getPreviouslyConnectedWifiNetworks();
1248 Q_INVOKABLE void forgetConnection(const QString dbus_path);
1249 Q_INVOKABLE bool forgetActiveDevice();
1250@@ -52,6 +52,7 @@
1251 private:
1252 QDBusConnection m_systemBusConnection;
1253 QString getWifiIpAddress();
1254+ QByteArray getCertContent(QString filename);
1255 };
1256
1257

Subscribers

People subscribed via source and target branches