D-Bus: Interworking/Hotspot 2.0 credential operations
Add "AddCred", "RemoveCred", and "RemoveAllCreds" methods to the D-Bus API of the network interface to allow the caller to manipulate a set of Interworking credentials similarly to the way this was enabled through the control interface. Signed-off-by: Damien Dejean <damiendejean@chromium.org>
This commit is contained in:
parent
4262e6ca49
commit
b44e199676
6 changed files with 366 additions and 0 deletions
|
@ -552,6 +552,28 @@ fi.w1.wpa_supplicant1.CreateInterface.
|
|||
<h3>AbortScan ( ) --> nothing</h3>
|
||||
<p>Abort ongoing scan operation.</p>
|
||||
</li>
|
||||
<li>
|
||||
<h3>AddCred ( a{sv} : args ) --> o : path</h3>
|
||||
<p>Add an Interworking/Hotspot 2.0 credential.</p>
|
||||
<h4>Arguments</h4>
|
||||
<dl>
|
||||
<dt>a{sv} : args</dt>
|
||||
<dd>A dictionary with credential configuration. Dictionary entries are equivalent to entries in the "cred" block in wpa_supplicant configuration file.</dd>
|
||||
</dl>
|
||||
<h4>Returns</h4>
|
||||
<dl>
|
||||
<dt>o : path</dt>
|
||||
<dd>A D-Bus path to an object representing the added credential</dd>
|
||||
</dl>
|
||||
</li>
|
||||
<li>
|
||||
<h3>RemoveCred ( o : path ) --> nothing</h3>
|
||||
<p>Remove the specified Interworking/Hotspot 2.0 credential.</p>
|
||||
</li>
|
||||
<li>
|
||||
<h3>RemoveAllCreds ( ) --> nothing</h3>
|
||||
<p>Remove all configured Interworking/Hotspot 2.0 credentials.</p>
|
||||
</li>
|
||||
<li>
|
||||
<h3>EAPLogoff ( ) --> nothing</h3>
|
||||
<p>IEEE 802.1X EAPOL state machine logoff.</p>
|
||||
|
|
|
@ -6091,3 +6091,48 @@ def test_dbus_roam(dev, apdev):
|
|||
with TestDbusConnect(bus) as t:
|
||||
if not t.success():
|
||||
raise Exception("Expected signals not seen")
|
||||
|
||||
def test_dbus_creds(dev, apdev):
|
||||
"D-Bus interworking credentials"
|
||||
(bus, wpas_obj, path, if_obj) = prepare_dbus(dev[0])
|
||||
iface = dbus.Interface(if_obj, WPAS_DBUS_IFACE)
|
||||
|
||||
args = {'domain': 'server.w1.fi',
|
||||
'realm': 'server.w1.fi',
|
||||
'roaming_consortium': '50a9bf',
|
||||
'required_roaming_consortium': '23bf50',
|
||||
'eap': 'TTLS',
|
||||
'phase2': 'auth=MSCHAPV2',
|
||||
'username': 'user',
|
||||
'password': 'password',
|
||||
'domain_suffix_match': 'server.w1.fi',
|
||||
'ca_cert': 'auth_serv/ca.pem'}
|
||||
|
||||
path = iface.AddCred(dbus.Dictionary(args, signature='sv'))
|
||||
for k, v in args.items():
|
||||
if k == 'password':
|
||||
continue
|
||||
prop = dev[0].get_cred(0, k)
|
||||
if prop != v:
|
||||
raise Exception('Credential add failed: %s does not match %s' % (prop, v))
|
||||
|
||||
iface.RemoveCred(path)
|
||||
if not "FAIL" in dev[0].get_cred(0, 'domain'):
|
||||
raise Exception("Credential remove failed")
|
||||
|
||||
# Removal of multiple credentials
|
||||
cred1 = {'domain': 'server1.w1.fi','realm': 'server1.w1.fi','eap': 'TTLS'}
|
||||
iface.AddCred(dbus.Dictionary(cred1, signature='sv'))
|
||||
if "FAIL" in dev[0].get_cred(0, 'domain'):
|
||||
raise Exception("Failed to add credential")
|
||||
|
||||
cred2 = {'domain': 'server2.w1.fi','realm': 'server2.w1.fi','eap': 'TTLS'}
|
||||
iface.AddCred(dbus.Dictionary(cred2, signature='sv'))
|
||||
if "FAIL" in dev[0].get_cred(1, 'domain'):
|
||||
raise Exception("Failed to add credential")
|
||||
|
||||
iface.RemoveAllCreds()
|
||||
if not "FAIL" in dev[0].get_cred(0, 'domain'):
|
||||
raise Exception("Credential remove failed")
|
||||
if not "FAIL" in dev[0].get_cred(1, 'domain'):
|
||||
raise Exception("Credential remove failed")
|
||||
|
|
|
@ -3570,6 +3570,29 @@ static const struct wpa_dbus_method_desc wpas_dbus_interface_methods[] = {
|
|||
END_ARGS
|
||||
}
|
||||
},
|
||||
#ifdef CONFIG_INTERWORKING
|
||||
{ "AddCred", WPAS_DBUS_NEW_IFACE_INTERFACE,
|
||||
(WPADBusMethodHandler) wpas_dbus_handler_add_cred,
|
||||
{
|
||||
{ "args", "a{sv}", ARG_IN },
|
||||
{ "path", "o", ARG_OUT },
|
||||
END_ARGS
|
||||
}
|
||||
},
|
||||
{ "RemoveCred", WPAS_DBUS_NEW_IFACE_INTERFACE,
|
||||
(WPADBusMethodHandler) wpas_dbus_handler_remove_cred,
|
||||
{
|
||||
{ "path", "o", ARG_IN },
|
||||
END_ARGS
|
||||
}
|
||||
},
|
||||
{ "RemoveAllCreds", WPAS_DBUS_NEW_IFACE_INTERFACE,
|
||||
(WPADBusMethodHandler) wpas_dbus_handler_remove_all_creds,
|
||||
{
|
||||
END_ARGS
|
||||
}
|
||||
},
|
||||
#endif /* CONFIG_INTERWORKING */
|
||||
{ NULL, NULL, NULL, { END_ARGS } }
|
||||
};
|
||||
|
||||
|
|
|
@ -96,6 +96,9 @@ enum wpas_dbus_sta_prop {
|
|||
#define WPAS_DBUS_NEW_P2P_PEERS_PART "Peers"
|
||||
#define WPAS_DBUS_NEW_IFACE_P2P_PEER WPAS_DBUS_NEW_INTERFACE ".Peer"
|
||||
|
||||
#define WPAS_DBUS_NEW_CREDENTIALS_PART "Credentials"
|
||||
#define WPAS_DBUS_NEW_IFACE_CREDENTIAL WPAS_DBUS_NEW_INTERFACE ".Credential"
|
||||
|
||||
/* Top-level Errors */
|
||||
#define WPAS_DBUS_ERROR_UNKNOWN_ERROR \
|
||||
WPAS_DBUS_NEW_INTERFACE ".UnknownError"
|
||||
|
|
|
@ -148,6 +148,9 @@ static const char * const dont_quote[] = {
|
|||
#ifdef CONFIG_P2P
|
||||
"go_p2p_dev_addr", "p2p_client_list", "psk_list",
|
||||
#endif /* CONFIG_P2P */
|
||||
#ifdef CONFIG_INTERWORKING
|
||||
"roaming_consortium", "required_roaming_consortium",
|
||||
#endif /* CONFIG_INTERWORKING */
|
||||
NULL
|
||||
};
|
||||
|
||||
|
@ -328,6 +331,110 @@ error:
|
|||
}
|
||||
|
||||
|
||||
/**
|
||||
* set_cred_properties - Set the properties of a configured credential
|
||||
* @wpa_s: wpa_supplicant structure for a network interface
|
||||
* @cred: wpa_cred structure for a configured credential
|
||||
* @iter: DBus message iterator containing dictionary of network
|
||||
* properties to set.
|
||||
* @error: On failure, an error describing the failure
|
||||
* Returns: TRUE if the request succeeds, FALSE if it failed
|
||||
*/
|
||||
static dbus_bool_t set_cred_properties(struct wpa_supplicant *wpa_s,
|
||||
struct wpa_cred *cred,
|
||||
DBusMessageIter *iter,
|
||||
DBusError *error)
|
||||
{
|
||||
struct wpa_dbus_dict_entry entry = { .type = DBUS_TYPE_STRING };
|
||||
DBusMessageIter iter_dict;
|
||||
char *value = NULL;
|
||||
|
||||
if (!wpa_dbus_dict_open_read(iter, &iter_dict, error))
|
||||
return FALSE;
|
||||
|
||||
while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
|
||||
size_t size = 50;
|
||||
int ret;
|
||||
|
||||
if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
|
||||
goto error;
|
||||
|
||||
value = NULL;
|
||||
if (entry.type == DBUS_TYPE_ARRAY &&
|
||||
entry.array_type == DBUS_TYPE_BYTE) {
|
||||
if (entry.array_len <= 0)
|
||||
goto error;
|
||||
|
||||
size = entry.array_len * 2 + 1;
|
||||
value = os_zalloc(size);
|
||||
if (!value)
|
||||
goto error;
|
||||
|
||||
ret = wpa_snprintf_hex(value, size,
|
||||
(u8 *) entry.bytearray_value,
|
||||
entry.array_len);
|
||||
if (ret <= 0)
|
||||
goto error;
|
||||
} else if (entry.type == DBUS_TYPE_STRING) {
|
||||
if (should_quote_opt(entry.key)) {
|
||||
size = os_strlen(entry.str_value);
|
||||
|
||||
size += 3;
|
||||
value = os_zalloc(size);
|
||||
if (!value)
|
||||
goto error;
|
||||
|
||||
ret = os_snprintf(value, size, "\"%s\"",
|
||||
entry.str_value);
|
||||
if (os_snprintf_error(size, ret))
|
||||
goto error;
|
||||
} else {
|
||||
value = os_strdup(entry.str_value);
|
||||
if (!value)
|
||||
goto error;
|
||||
}
|
||||
} else if (entry.type == DBUS_TYPE_UINT32) {
|
||||
value = os_zalloc(size);
|
||||
if (!value)
|
||||
goto error;
|
||||
|
||||
ret = os_snprintf(value, size, "%u",
|
||||
entry.uint32_value);
|
||||
if (os_snprintf_error(size, ret))
|
||||
goto error;
|
||||
} else if (entry.type == DBUS_TYPE_INT32) {
|
||||
value = os_zalloc(size);
|
||||
if (!value)
|
||||
goto error;
|
||||
|
||||
ret = os_snprintf(value, size, "%d",
|
||||
entry.int32_value);
|
||||
if (os_snprintf_error(size, ret))
|
||||
goto error;
|
||||
} else {
|
||||
goto error;
|
||||
}
|
||||
|
||||
ret = wpa_config_set_cred(cred, entry.key, value, 0);
|
||||
if (ret < 0)
|
||||
goto error;
|
||||
|
||||
os_free(value);
|
||||
value = NULL;
|
||||
wpa_dbus_dict_entry_clear(&entry);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
|
||||
error:
|
||||
os_free(value);
|
||||
wpa_dbus_dict_entry_clear(&entry);
|
||||
dbus_set_error_const(error, DBUS_ERROR_INVALID_ARGS,
|
||||
"invalid message format");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* wpas_dbus_simple_property_getter - Get basic type property
|
||||
* @iter: Message iter to use when appending arguments
|
||||
|
@ -1515,6 +1622,163 @@ DBusMessage * wpas_dbus_handler_abort_scan(DBusMessage *message,
|
|||
}
|
||||
|
||||
|
||||
/**
|
||||
* wpas_dbus_new_iface_add_cred - Add a new credential
|
||||
* @message: Pointer to incoming dbus message
|
||||
* @wpa_s: wpa_supplicant structure for a network interface
|
||||
* Returns: A dbus message containing the object path of the new credential
|
||||
*
|
||||
* Handler function for "AddCred" method call of a network interface.
|
||||
*/
|
||||
DBusMessage * wpas_dbus_handler_add_cred(DBusMessage *message,
|
||||
struct wpa_supplicant *wpa_s)
|
||||
{
|
||||
DBusMessage *reply = NULL;
|
||||
DBusMessageIter iter;
|
||||
struct wpa_cred *cred = NULL;
|
||||
char path_buf[WPAS_DBUS_OBJECT_PATH_MAX], *path = path_buf;
|
||||
DBusError error;
|
||||
|
||||
dbus_message_iter_init(message, &iter);
|
||||
|
||||
if (wpa_s->dbus_new_path)
|
||||
cred = wpa_config_add_cred(wpa_s->conf);
|
||||
if (!cred) {
|
||||
wpa_printf(MSG_ERROR, "%s[dbus]: can't add new credential.",
|
||||
__func__);
|
||||
reply = wpas_dbus_error_unknown_error(
|
||||
message,
|
||||
"wpa_supplicant could not add a credential on this interface.");
|
||||
goto err;
|
||||
}
|
||||
|
||||
dbus_error_init(&error);
|
||||
if (!set_cred_properties(wpa_s, cred, &iter, &error)) {
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"%s[dbus]: control interface couldn't set credential properties",
|
||||
__func__);
|
||||
reply = wpas_dbus_reply_new_from_error(message, &error,
|
||||
DBUS_ERROR_INVALID_ARGS,
|
||||
"Failed to add credential");
|
||||
dbus_error_free(&error);
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* Construct the object path for this network. */
|
||||
os_snprintf(path, WPAS_DBUS_OBJECT_PATH_MAX,
|
||||
"%s/" WPAS_DBUS_NEW_CREDENTIALS_PART "/%d",
|
||||
wpa_s->dbus_new_path, cred->id);
|
||||
|
||||
reply = dbus_message_new_method_return(message);
|
||||
if (!reply) {
|
||||
reply = wpas_dbus_error_no_memory(message);
|
||||
goto err;
|
||||
}
|
||||
if (!dbus_message_append_args(reply, DBUS_TYPE_OBJECT_PATH, &path,
|
||||
DBUS_TYPE_INVALID)) {
|
||||
dbus_message_unref(reply);
|
||||
reply = wpas_dbus_error_no_memory(message);
|
||||
goto err;
|
||||
}
|
||||
|
||||
return reply;
|
||||
|
||||
err:
|
||||
if (cred)
|
||||
wpa_config_remove_cred(wpa_s->conf, cred->id);
|
||||
return reply;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* wpas_dbus_handler_remove_cred - Remove a configured credential
|
||||
* @message: Pointer to incoming dbus message
|
||||
* @wpa_s: wpa_supplicant structure for a network interface
|
||||
* Returns: NULL on success or dbus error on failure
|
||||
*
|
||||
* Handler function for "RemoveCred" method call of a network interface.
|
||||
*/
|
||||
DBusMessage * wpas_dbus_handler_remove_cred(DBusMessage *message,
|
||||
struct wpa_supplicant *wpa_s)
|
||||
{
|
||||
DBusMessage *reply = NULL;
|
||||
const char *op;
|
||||
char *iface, *cred_id;
|
||||
int id;
|
||||
struct wpa_cred *cred;
|
||||
|
||||
dbus_message_get_args(message, NULL, DBUS_TYPE_OBJECT_PATH, &op,
|
||||
DBUS_TYPE_INVALID);
|
||||
|
||||
/* Extract the network ID and ensure the network is actually a child of
|
||||
* this interface */
|
||||
iface = wpas_dbus_new_decompose_object_path(
|
||||
op, WPAS_DBUS_NEW_CREDENTIALS_PART, &cred_id);
|
||||
if (!iface || !cred_id || !wpa_s->dbus_new_path ||
|
||||
os_strcmp(iface, wpa_s->dbus_new_path) != 0) {
|
||||
reply = wpas_dbus_error_invalid_args(message, op);
|
||||
goto out;
|
||||
}
|
||||
|
||||
errno = 0;
|
||||
id = strtoul(cred_id, NULL, 10);
|
||||
if (errno != 0) {
|
||||
reply = wpas_dbus_error_invalid_args(message, op);
|
||||
goto out;
|
||||
}
|
||||
|
||||
cred = wpa_config_get_cred(wpa_s->conf, id);
|
||||
if (!cred) {
|
||||
wpa_printf(MSG_ERROR, "%s[dbus]: could not find credential %s",
|
||||
__func__, op);
|
||||
reply = wpas_dbus_error_invalid_args(
|
||||
message, "could not find credential");
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (wpas_remove_cred(wpa_s, cred) < 0) {
|
||||
wpa_printf(MSG_ERROR,
|
||||
"%s[dbus]: error occurred when removing cred %d",
|
||||
__func__, id);
|
||||
reply = wpas_dbus_error_unknown_error(
|
||||
message,
|
||||
"error removing the specified credential on its interface.");
|
||||
goto out;
|
||||
}
|
||||
|
||||
out:
|
||||
os_free(iface);
|
||||
return reply;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* wpas_dbus_handler_remove_all_creds - Remove all the configured credentials
|
||||
* @message: Pointer to incoming dbus message
|
||||
* @wpa_s: wpa_supplicant structure for a network interface
|
||||
* Returns: NULL indicating success or DBus error message on failure
|
||||
*
|
||||
* Handler function for "RemoveAllCreds" method call of a network interface.
|
||||
*/
|
||||
DBusMessage * wpas_dbus_handler_remove_all_creds(DBusMessage *message,
|
||||
struct wpa_supplicant *wpa_s)
|
||||
{
|
||||
int res;
|
||||
DBusMessage *reply = NULL;
|
||||
|
||||
res = wpas_remove_all_creds(wpa_s);
|
||||
if (res < 0) {
|
||||
wpa_printf(MSG_ERROR,
|
||||
"%s[dbus]: failed to remove all credentials",
|
||||
__func__);
|
||||
reply = wpas_dbus_error_unknown_error(
|
||||
message, "failed to remove all credentials");
|
||||
}
|
||||
|
||||
return reply;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* wpas_dbus_handler_signal_poll - Request immediate signal properties
|
||||
* @message: Pointer to incoming dbus message
|
||||
|
|
|
@ -144,6 +144,15 @@ DBusMessage * wpas_dbus_handler_eap_logoff(DBusMessage *message,
|
|||
DBusMessage * wpas_dbus_handler_eap_logon(DBusMessage *message,
|
||||
struct wpa_supplicant *wpa_s);
|
||||
|
||||
DBusMessage * wpas_dbus_handler_add_cred(DBusMessage *message,
|
||||
struct wpa_supplicant *wpa_s);
|
||||
|
||||
DBusMessage * wpas_dbus_handler_remove_cred(DBusMessage *message,
|
||||
struct wpa_supplicant *wpa_s);
|
||||
|
||||
DBusMessage * wpas_dbus_handler_remove_all_creds(DBusMessage *message,
|
||||
struct wpa_supplicant *wpa_s);
|
||||
|
||||
DECLARE_ACCESSOR(wpas_dbus_getter_capabilities);
|
||||
DECLARE_ACCESSOR(wpas_dbus_getter_state);
|
||||
DECLARE_ACCESSOR(wpas_dbus_getter_scanning);
|
||||
|
|
Loading…
Reference in a new issue