Hello everybody,
We would like to propose a RFC to change the way to manage the WPS
connections. Following we present our proposal and the reasons for
suggesting it:
Current implementation of WPS connection requires to specify the service to
which the user wants to connect, and when the connection is going to
finalize, a verification is done in *handle_wps_completion* function to
ensure that the SSID of the AP actually being connected was the one
specified by the user. This violates the WiFi Alliance specification over
WPS and the WPS Certification plan because:
1. WiFi Alliance admits to certify devices that have no mean for the
user to choose an AP to connect to, they define them as "Client devices
with only a simple display or a fixed label containing a setup password"
(Pag. 12 of Wi-Fi Simple Configuration Technical Specification Version
2.0.5)
1. The WPS protocol includes the transition from un-configured to
configured state of the AP when the first Enrollee connects, some Access
Points change their SSID during this transition, that would cause the
ConnMan to invalidate the connection. A tipical example of such Access
Point is the Atheros used in test 5.4.2 of Wi-Fi CERTIFIED™ Wi-Fi Protected
Setup™ Interoperability Test Plan – Version 2.0.15
After having performed a detailed study of the wpa_supplicant
implementation for the WPS, we propose to implement a solution with the
following general characteristics:
1. The new implementation must keep current WPS implementation for
compatibility support, but as deprecated.
2. In order to meet the specifications of Wi-Fi Alliance and based on
what the WPS D-Bus Interface of wpa_supplicant offers (Documented in
https://w1.fi/wpa_supplicant/devel/dbus.html#dbus_wps) we propose to add
two methods to the Technology D-Bus Interface: *StartWPS* and *CancelWPS*,
analogous to functions WPS.Start and WPS.Cancel provided by
wpa_supplicant. In this way there is no service specified enabling simple
devices to offer a very basic interface to the user for starting the WPS
session. Both methods would be supported only by WiFi technology.
3. On the other hand, some advanced WiFi modules expose more than one
network interface (one for P2P, one for STA, one for AP ..) that can be
active at the same time, and it is then desirable to not let connman
randomly choose on which start WPS, thus we propose also to add the
possibility to specify the interface over which either the start or cancel
action will be performed. This would not be a mandatory parameter in order
to keep the things easy for more simple systems.
Please find below the implementation proposal:
*StartWPS:*
Following the approach of wpa_supplicant, we propose to add the possibility
to choose which role to assume (enrollee, registrar), which authentication
type use (pin, pbc) and get back the pin to be used (if required), as well
as wpa_supplicant does. At this point, we can briefly define a possible
prototype of the method:
dict StartWPS(dict parameters)
Where the returned dictionary could be empty or composed by at most one
entry, which will be the just generated PIN by the wpa_supplicant, in case
it was requested. On the other hand, the function would receive a
dictionary with possible keys: “Ifname", "Role", "Type" and
"Pin"; where
“Ifame” is an optional parameters covering previous defined characteristic
for complex systems. Whereas, parameters "Role", "Type" and
"Pin" follow
exactly the same behavior of the table presented in
https://w1.fi/wpa_supplicant/devel/dbus.html#dbus_wps for method Start
of fi.w1.wpa_supplicant1.Interface.WPS
Interface.
When the *StartWPS* method gets called, it should verify if interface was
specified through “Ifname” entry key. If so, WPS Session will be started in
that specific interface, otherwise we suggest to look for the first
available interface with the capabilities to start a WPS Session among the
device_list of the Wi-Fi Technology. If it is found, then use it, if not
return "[service].Error.NotSupported”.
Additionally, current implementation does not allow to start a WPS Session
when the device is playing as Access Point (Tethering). On the contrary,
wpa_supplicant does. Therefore, we propose to also add this possibility to
the new implementation. It would be possible if a Service D-Bus Object is
not required for starting a WPS Session, which would be true if the new
methods are added to the Technology D-Bus Interface, as we propose.
*CancelWPS:*
This function does not require for any particular parameter. So, we propose
to only continue giving the option to specify the interface. Therefore, the
possible prototype of the method would be:
void CancelWPS(dict parameters)
Where the received dictionary could be empty or composed by at most one
single entry if the user wants to specify the interface using the key
“Ifname”. If so, the *CancelWPS* function should cancel the ongoing WPS
Session running in that specific interface. Otherwise, we suggest to do it
over all the Device of the Wi-Fi Technology (device_list).
*Going into details of implementation*:
After having studied the ConnMan architecture we think to associate the WPS
concept to the Device Infrastructure because if we want to add the
possibility of specify the interface (“Ifname”), the Device is the
corresponding represents of a real device inside the ConnMan. Therefore, we
think it is the best choice. Additionally, *StartWPS* and *CancelWPS*
should be added to the device driver:
*static* *struct* connman_device_driver wifi_ng_driver = {
.name = "*wifi*",
.type = *CONNMAN_DEVICE_TYPE_WIFI*,
...
.start_wps = wifi_start_wps,
.cancel_wps = wifi_cancel_wps,
};
It means that WiFi plugging must implements both methods wifi_start_wps and
wifi_cancel_wps. In particular, wifi_start_wps will need to receive the WPS
parameters to then pass them to the ConnMan’s supplicant handler
(gsuppicant/supplicant.c), which is the only one that interacts directly
with the wpa_supplicant.
Next, the supplicant handler will call methods Start or Cancel of the
fi.w1.wpa_supplicant1.Interface.WPS
D-Bus Interface of the wpa_supplicant, with the required parameters. In
case the method Start returns the newly generated PIN it has to be
forwarded towards the Technology to then be added as an entry in the
directory that would be returned by the *StartWPS* method. It would imply
that we have to store the request message of the *StartWPS* method in order
to reply possibly with a the PIN generated by the wpa_supplicant. To do it,
we propose to store that message in the Device structure in order to be
coherent with the association we previously proposed between the WPS and
Device.
Once the WPS Session has been initiated, it could finalize successfully or
fail. The current implementation does not provide further information about
such a events. Given that, we propose to notify the following events (Just
the most commons):
- Success: WPS provisioning has finished successfully.
- Password Authentication Fail: When pin entered in the registrar was
wrong.
- PBC-Overlap: When an enrollee detects two registrars with PBC session
active.
We think to perform those notifications using a D-Bus Signal added to the
Technology Interface, let’s call it *WPSEvent*. It would simply indicate
when one of the described event takes place. We propose to just provide a
string with the name of the event: "success", "pwd-auth-fail" or
"pbc-overlap", following the wpa_supplicant notation. All this information
is already provided by the wpa_supplicant in the event
fi.w1.wpa_supplicant1.Interface.WPS.Event, thus it just need to be
forwarded to the Technology in order to be emitted.
In order to forward WPS events, we propose to follow the implementation of
the communication between the plug-in and the supplicant handler, it means
to use the callback mechanism adding a new callback:
*static* *const* GSupplicantCallbacks callbacks = {
...
.wps_event = wps_event,
};
Thus the wifi plug-in must implement the wps_event function that will
basically just call a Technology function that will emit the proposed
signal.
What do you think about our proposal? Of course, everybody is welcome to
give feedbacks and suggestions.
Best regards,
Jose Blanquicet