[PATCH v2 2/3] DBus: add interworking credentials.
damiendejean at google.com
damiendejean at google.com
Fri Sep 24 04:44:48 PDT 2021
From: Damien Dejean <damiendejean at google.com>
Add "AddCred" and "RemoveCred" methods to the D-Bus API of the network
interface to allow the caller to manipulate a set of interworking
credentials.
Signed-off-by: Damien Dejean <damiendejean at google.com>
---
tests/hwsim/test_dbus.py | 26 +++
wpa_supplicant/dbus/dbus_new.c | 17 ++
wpa_supplicant/dbus/dbus_new.h | 4 +
wpa_supplicant/dbus/dbus_new_handlers.c | 228 ++++++++++++++++++++++++
wpa_supplicant/dbus/dbus_new_handlers.h | 11 ++
5 files changed, 286 insertions(+)
diff --git a/tests/hwsim/test_dbus.py b/tests/hwsim/test_dbus.py
index 1143802c6..1822e0a2c 100644
--- a/tests/hwsim/test_dbus.py
+++ b/tests/hwsim/test_dbus.py
@@ -6091,3 +6091,29 @@ 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',
+ '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")
diff --git a/wpa_supplicant/dbus/dbus_new.c b/wpa_supplicant/dbus/dbus_new.c
index 2c01943f7..413396a9f 100644
--- a/wpa_supplicant/dbus/dbus_new.c
+++ b/wpa_supplicant/dbus/dbus_new.c
@@ -3570,6 +3570,23 @@ 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
+ }
+ },
+#endif /* CONFIG_INTERWORKING */
{ NULL, NULL, NULL, { END_ARGS } }
};
diff --git a/wpa_supplicant/dbus/dbus_new.h b/wpa_supplicant/dbus/dbus_new.h
index 42db3892e..8ae0afeaa 100644
--- a/wpa_supplicant/dbus/dbus_new.h
+++ b/wpa_supplicant/dbus/dbus_new.h
@@ -16,6 +16,7 @@
struct wpa_global;
struct wpa_supplicant;
struct wpa_ssid;
+struct wpa_cred;
struct wps_event_m2d;
struct wps_event_fail;
struct wps_credential;
@@ -96,6 +97,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"
diff --git a/wpa_supplicant/dbus/dbus_new_handlers.c b/wpa_supplicant/dbus/dbus_new_handlers.c
index db9f30c9a..2b2cefb76 100644
--- a/wpa_supplicant/dbus/dbus_new_handlers.c
+++ b/wpa_supplicant/dbus/dbus_new_handlers.c
@@ -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",
+#endif /* CONFIG_INTERWORKING */
NULL
};
@@ -328,6 +331,110 @@ error:
}
+/**
+ * set_cred_properties - Set the properties of a configured set of
+ * crendentials.
+ * @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
+ */
+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 == NULL)
+ 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 == NULL)
+ 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 == NULL)
+ goto error;
+ }
+ } else if (entry.type == DBUS_TYPE_UINT32) {
+ value = os_zalloc(size);
+ if (value == NULL)
+ 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 == NULL)
+ 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
@@ -1514,6 +1621,127 @@ DBusMessage * wpas_dbus_handler_abort_scan(DBusMessage *message,
return NULL;
}
+/**
+ * wpas_dbus_new_iface_add_cred - Add a new set of credentials
+ * @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 == NULL) {
+ wpa_printf(MSG_ERROR, "%s[dbus]: can't add new interface.",
+ __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 == NULL) {
+ 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 set of credentials
+ * @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;
+ int result;
+
+ 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 == NULL || cred_id == NULL || !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;
+ }
+
+ result = wpa_config_remove_cred(wpa_s->conf, id);
+ if (result == -1) {
+ 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_signal_poll - Request immediate signal properties
diff --git a/wpa_supplicant/dbus/dbus_new_handlers.h b/wpa_supplicant/dbus/dbus_new_handlers.h
index c36383f05..5b01ab527 100644
--- a/wpa_supplicant/dbus/dbus_new_handlers.h
+++ b/wpa_supplicant/dbus/dbus_new_handlers.h
@@ -144,6 +144,17 @@ DBusMessage * wpas_dbus_handler_eap_logoff(DBusMessage *message,
DBusMessage * wpas_dbus_handler_eap_logon(DBusMessage *message,
struct wpa_supplicant *wpa_s);
+dbus_bool_t set_cred_properties(struct wpa_supplicant *wpa_s,
+ struct wpa_cred *cred,
+ DBusMessageIter *iter,
+ DBusError *error);
+
+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);
+
DECLARE_ACCESSOR(wpas_dbus_getter_capabilities);
DECLARE_ACCESSOR(wpas_dbus_getter_state);
DECLARE_ACCESSOR(wpas_dbus_getter_scanning);
--
2.33.0.685.g46640cef36-goog
More information about the Hostap
mailing list