static gboolean
connection_compatible (NMBluezDevice *self, NMConnection *connection)
{
	NMBluezDevicePrivate *priv = NM_BLUEZ_DEVICE_GET_PRIVATE (self);
	NMSettingBluetooth *s_bt;
	const char *bt_type;
	const char *bdaddr;

	if (!nm_connection_is_type (connection, NM_SETTING_BLUETOOTH_SETTING_NAME))
		return FALSE;

	s_bt = nm_connection_get_setting_bluetooth (connection);
	if (!s_bt)
		return FALSE;

	if (!priv->address)
		return FALSE;

	bdaddr = nm_setting_bluetooth_get_bdaddr (s_bt);
	if (!bdaddr)
		return FALSE;
	if (!nm_utils_hwaddr_matches (bdaddr, -1, priv->address, -1))
		return FALSE;

	bt_type = nm_setting_bluetooth_get_connection_type (s_bt);
	if (   g_str_equal (bt_type, NM_SETTING_BLUETOOTH_TYPE_DUN)
	    && !(priv->capabilities & NM_BT_CAPABILITY_DUN))
		return FALSE;

	if (   g_str_equal (bt_type, NM_SETTING_BLUETOOTH_TYPE_PANU)
	    && !(priv->capabilities & NM_BT_CAPABILITY_NAP))
		return FALSE;

	return TRUE;
}
static void
recheck_services_enabled (NmaBtDevice *self)
{
	NmaBtDevicePrivate *priv = NMA_BT_DEVICE_GET_PRIVATE (self);
	GSList *list, *iter;
	gboolean pan = FALSE, dun = FALSE;

	/* Retrieve initial enabled state for both PAN and DUN; if there are any
	 * existing Bluetooth connections for the given device for either PAN
	 * or DUN, then we consider that service enabled.
	 */
	list = nm_remote_settings_list_connections (priv->settings);
	for (iter = list; iter != NULL; iter = g_slist_next (iter)) {
		NMConnection *connection = iter->data;

		if (match_connection_bdaddr (connection, priv->bdaddr_array)) {
			NMSettingBluetooth *s_bt;
			const char *type;

			s_bt = nm_connection_get_setting_bluetooth (connection);
			g_assert (s_bt);
			type = nm_setting_bluetooth_get_connection_type (s_bt);
			if (priv->has_pan && g_strcmp0 (type, NM_SETTING_BLUETOOTH_TYPE_PANU) == 0)
				pan = TRUE;
			else if (priv->has_dun && g_strcmp0 (type, NM_SETTING_BLUETOOTH_TYPE_DUN) == 0)
				dun =  TRUE;
		}
	}
	g_slist_free (list);

	_set_pan_enabled (self, pan);
	_set_dun_enabled (self, dun);
}
static void
get_property (GObject *object, guint prop_id,
              GValue *value, GParamSpec *pspec)
{
	NMSettingBluetooth *setting = NM_SETTING_BLUETOOTH (object);

	switch (prop_id) {
	case PROP_BDADDR:
		g_value_set_string (value, nm_setting_bluetooth_get_bdaddr (setting));
		break;
	case PROP_TYPE:
		g_value_set_string (value, nm_setting_bluetooth_get_connection_type (setting));
		break;
	default:
		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
		break;
	}
}
示例#4
0
static NMBluetoothCapabilities
get_connection_bt_type (NMConnection *connection)
{
	NMSettingBluetooth *s_bt;
	const char *bt_type;

	s_bt = nm_connection_get_setting_bluetooth (connection);
	if (!s_bt)
		return NM_BT_CAPABILITY_NONE;

	bt_type = nm_setting_bluetooth_get_connection_type (s_bt);
	g_assert (bt_type);

	if (!strcmp (bt_type, NM_SETTING_BLUETOOTH_TYPE_DUN))
		return NM_BT_CAPABILITY_DUN;
	else if (!strcmp (bt_type, NM_SETTING_BLUETOOTH_TYPE_PANU))
		return NM_BT_CAPABILITY_NAP;

	return NM_BT_CAPABILITY_NONE;
}
static gboolean
match_connection_service (NMConnection *connection,
                          const GByteArray *bdaddr,
                          gboolean pan)
{
	NMSettingBluetooth *s_bt;
	const char *type;

	if (!match_connection_bdaddr (connection, bdaddr))
		return FALSE;

	s_bt = nm_connection_get_setting_bluetooth (connection);
	g_assert (s_bt);
	type = nm_setting_bluetooth_get_connection_type (s_bt);
	if (pan) {
		if (g_strcmp0 (type, NM_SETTING_BLUETOOTH_TYPE_PANU) != 0)
			return FALSE;
	} else {
		if (g_strcmp0 (type, NM_SETTING_BLUETOOTH_TYPE_DUN) != 0)
			return FALSE;
	}

	return TRUE;
}
static gboolean
nm_connection_editor_set_connection (NMConnectionEditor *editor,
                                     NMConnection *orig_connection,
                                     GError **error)
{
	NMSettingConnection *s_con;
	const char *connection_type;
	const char *slave_type;
	gboolean success = FALSE;
	GSList *iter, *copy;

	g_return_val_if_fail (NM_IS_CONNECTION_EDITOR (editor), FALSE);
	g_return_val_if_fail (NM_IS_CONNECTION (orig_connection), FALSE);

	/* clean previous connection */
	if (editor->connection)
		g_object_unref (editor->connection);

	editor->connection = nm_simple_connection_new_clone (orig_connection);

	editor->orig_connection = g_object_ref (orig_connection);
	nm_connection_editor_update_title (editor);

	/* Handle CA cert ignore stuff */
	eap_method_ca_cert_ignore_load (editor->connection);

	s_con = nm_connection_get_setting_connection (editor->connection);
	g_assert (s_con);

	connection_type = nm_setting_connection_get_connection_type (s_con);
	if (!add_page (editor, ce_page_general_new, editor->connection, error))
		goto out;
	if (!strcmp (connection_type, NM_SETTING_WIRED_SETTING_NAME)) {
		if (!add_page (editor, ce_page_ethernet_new, editor->connection, error))
			goto out;
		if (!add_page (editor, ce_page_8021x_security_new, editor->connection, error))
			goto out;
		if (!add_page (editor, ce_page_dcb_new, editor->connection, error))
			goto out;
	} else if (!strcmp (connection_type, NM_SETTING_WIRELESS_SETTING_NAME)) {
		if (!add_page (editor, ce_page_wifi_new, editor->connection, error))
			goto out;
		if (!add_page (editor, ce_page_wifi_security_new, editor->connection, error))
			goto out;
	} else if (!strcmp (connection_type, NM_SETTING_VPN_SETTING_NAME)) {
		if (!add_page (editor, ce_page_vpn_new, editor->connection, error))
			goto out;
	} else if (!strcmp (connection_type, NM_SETTING_IP_TUNNEL_SETTING_NAME)) {
		if (!add_page (editor, ce_page_ip_tunnel_new, editor->connection, error))
			goto out;
	} else if (!strcmp (connection_type, NM_SETTING_PPPOE_SETTING_NAME)) {
		if (!add_page (editor, ce_page_dsl_new, editor->connection, error))
			goto out;
		if (!add_page (editor, ce_page_ethernet_new, editor->connection, error))
			goto out;
		if (!add_page (editor, ce_page_ppp_new, editor->connection, error))
			goto out;
	} else if (!strcmp (connection_type, NM_SETTING_GSM_SETTING_NAME) || 
	           !strcmp (connection_type, NM_SETTING_CDMA_SETTING_NAME)) {
		if (!add_page (editor, ce_page_mobile_new, editor->connection, error))
			goto out;
		if (!add_page (editor, ce_page_ppp_new, editor->connection, error))
			goto out;
	} else if (!strcmp (connection_type, NM_SETTING_BLUETOOTH_SETTING_NAME)) {
		NMSettingBluetooth *s_bt = nm_connection_get_setting_bluetooth (editor->connection);
		const char *type = nm_setting_bluetooth_get_connection_type (s_bt);
		g_assert (type);

		if (!add_page (editor, ce_page_bluetooth_new, editor->connection, error))
			goto out;
		if (!g_strcmp0 (type, "dun")) {
			if (!add_page (editor, ce_page_mobile_new, editor->connection, error))
				goto out;
			if (!add_page (editor, ce_page_ppp_new, editor->connection, error))
				goto out;
		}
	} else if (!strcmp (connection_type, NM_SETTING_INFINIBAND_SETTING_NAME)) {
		if (!add_page (editor, ce_page_infiniband_new, editor->connection, error))
			goto out;
	} else if (!strcmp (connection_type, NM_SETTING_BOND_SETTING_NAME)) {
		if (!add_page (editor, ce_page_bond_new, editor->connection, error))
			goto out;
	} else if (!strcmp (connection_type, NM_SETTING_TEAM_SETTING_NAME)) {
		if (!add_page (editor, ce_page_team_new, editor->connection, error))
			goto out;
	} else if (!strcmp (connection_type, NM_SETTING_BRIDGE_SETTING_NAME)) {
		if (!add_page (editor, ce_page_bridge_new, editor->connection, error))
			goto out;
	} else if (!strcmp (connection_type, NM_SETTING_VLAN_SETTING_NAME)) {
		if (!add_page (editor, ce_page_vlan_new, editor->connection, error))
			goto out;
	} else {
		g_warning ("Unhandled setting type '%s'", connection_type);
	}

	slave_type = nm_setting_connection_get_slave_type (s_con);
	if (!g_strcmp0 (slave_type, NM_SETTING_TEAM_SETTING_NAME)) {
		if (!add_page (editor, ce_page_team_port_new, editor->connection, error))
			goto out;
	} else if (!g_strcmp0 (slave_type, NM_SETTING_BRIDGE_SETTING_NAME)) {
		if (!add_page (editor, ce_page_bridge_port_new, editor->connection, error))
			goto out;
	}

	if (   nm_connection_get_setting_ip4_config (editor->connection)
	    && !add_page (editor, ce_page_ip4_new, editor->connection, error))
		goto out;
	if (   nm_connection_get_setting_ip6_config (editor->connection)
	    && !add_page (editor, ce_page_ip6_new, editor->connection, error))
		goto out;

	/* After all pages are created, then kick off secrets requests that any
	 * the pages may need to make; if they don't need any secrets, then let
	 * them finish initialization.  The list might get modified during the loop
	 * which is why copy the list here.
	 */
	copy = g_slist_copy (editor->initializing_pages);
	for (iter = copy; iter; iter = g_slist_next (iter)) {
		CEPage *page = CE_PAGE (iter->data);
		const char *setting_name = g_object_get_data (G_OBJECT (page), SECRETS_TAG);

		if (!setting_name) {
			/* page doesn't need any secrets */
			ce_page_complete_init (page, NULL, NULL, NULL);
		} else if (!NM_IS_REMOTE_CONNECTION (editor->orig_connection)) {
			/* We want to get secrets using ->orig_connection, since that's the
			 * remote connection which can actually respond to secrets requests.
			 * ->connection is a plain NMConnection copy of ->orig_connection
			 * which is what gets changed when users modify anything.  But when
			 * creating or importing, ->orig_connection will be an NMConnection
			 * since the new connection hasn't been added to NetworkManager yet.
			 * So basically, skip requesting secrets if the connection can't
			 * handle a secrets request.
			 */
			ce_page_complete_init (page, setting_name, NULL, NULL);
		} else {
			/* Page wants secrets, get them */
			get_secrets_for_page (editor, page, setting_name);
		}
		g_object_set_data (G_OBJECT (page), SECRETS_TAG, NULL);
	}
	g_slist_free (copy);

	/* set the UI */
	recheck_initialization (editor);
	success = TRUE;

out:
	return success;
}
NMConnection *
connection_from_file (const char *filename, GError **error)
{
	GKeyFile *key_file;
	struct stat statbuf;
	gboolean bad_owner, bad_permissions;
	NMConnection *connection = NULL;
	NMSettingConnection *s_con;
	NMSettingBluetooth *s_bt;
	NMSetting *setting;
	gchar **groups;
	gsize length;
	int i;
	gboolean vpn_secrets = FALSE;
	const char *ctype, *tmp;
	GError *verify_error = NULL;

	if (stat (filename, &statbuf) != 0 || !S_ISREG (statbuf.st_mode)) {
		g_set_error_literal (error, KEYFILE_PLUGIN_ERROR, 0,
		                     "File did not exist or was not a regular file");
		return NULL;
	}

	bad_owner = getuid () != statbuf.st_uid;
	bad_permissions = statbuf.st_mode & 0077;

	if (bad_owner || bad_permissions) {
		g_set_error (error, KEYFILE_PLUGIN_ERROR, 0,
		             "File permissions (%o) or owner (%d) were insecure",
		             statbuf.st_mode, statbuf.st_uid);
		return NULL;
	}

	key_file = g_key_file_new ();
	if (!g_key_file_load_from_file (key_file, filename, G_KEY_FILE_NONE, error))
		goto out;

	connection = nm_connection_new ();

	groups = g_key_file_get_groups (key_file, &length);
	for (i = 0; i < length; i++) {
		/* Only read out secrets when needed */
		if (!strcmp (groups[i], VPN_SECRETS_GROUP)) {
			vpn_secrets = TRUE;
			continue;
		}

		setting = read_setting (key_file, groups[i]);
		if (setting)
			nm_connection_add_setting (connection, setting);
	}

	/* Make sure that we have the base device type setting even if
	 * the keyfile didn't include it, which can happen when the base
	 * device type setting is all default values (like ethernet).
	 */
	s_con = (NMSettingConnection *) nm_connection_get_setting (connection, NM_TYPE_SETTING_CONNECTION);
	if (s_con) {
		ctype = nm_setting_connection_get_connection_type (s_con);
		setting = nm_connection_get_setting_by_name (connection, ctype);
		if (ctype) {
			gboolean add_serial = FALSE;
			NMSetting *new_setting = NULL;

			if (!setting && !strcmp (ctype, NM_SETTING_WIRED_SETTING_NAME))
				new_setting = nm_setting_wired_new ();
			else if (!strcmp (ctype, NM_SETTING_BLUETOOTH_SETTING_NAME)) {
				s_bt = (NMSettingBluetooth *) nm_connection_get_setting (connection, NM_TYPE_SETTING_BLUETOOTH);
				if (s_bt) {
					tmp = nm_setting_bluetooth_get_connection_type (s_bt);
					if (tmp && !strcmp (tmp, NM_SETTING_BLUETOOTH_TYPE_DUN))
						add_serial = TRUE;
				}
			} else if (!strcmp (ctype, NM_SETTING_GSM_SETTING_NAME))
				add_serial = TRUE;
			else if (!strcmp (ctype, NM_SETTING_CDMA_SETTING_NAME))
				add_serial = TRUE;

			/* Bluetooth DUN, GSM, and CDMA connections require a serial setting */
			if (add_serial && !nm_connection_get_setting (connection, NM_TYPE_SETTING_SERIAL))
				new_setting = nm_setting_serial_new ();

			if (new_setting)
				nm_connection_add_setting (connection, new_setting);
		}
	}

	/* Serial connections require a PPP setting too */
	if (nm_connection_get_setting (connection, NM_TYPE_SETTING_SERIAL)) {
		if (!nm_connection_get_setting (connection, NM_TYPE_SETTING_PPP))
			nm_connection_add_setting (connection, nm_setting_ppp_new ());
	}

	/* Handle vpn secrets after the 'vpn' setting was read */
	if (vpn_secrets) {
		NMSettingVPN *s_vpn;

		s_vpn = (NMSettingVPN *) nm_connection_get_setting (connection, NM_TYPE_SETTING_VPN);
		if (s_vpn)
			read_vpn_secrets (key_file, s_vpn);
	}

	g_strfreev (groups);

	/* Verify the connection */
	if (!nm_connection_verify (connection, &verify_error)) {
		g_set_error (error, KEYFILE_PLUGIN_ERROR, 0,
			         "invalid or missing connection property '%s'",
			         (verify_error && verify_error->message) ? verify_error->message : "(unknown)");
		g_clear_error (&verify_error);
		g_object_unref (connection);
		connection = NULL;
	}

out:
	g_key_file_free (key_file);
	return connection;
}
static gboolean
check_bt_compatible (NMDeviceBt *device, NMConnection *connection, GError **error)
{
        NMSettingConnection *s_con;
        NMSettingBluetooth *s_bt;
        const GByteArray *array;
        char *str;
        const char *device_hw_str;
        int addr_match = FALSE;
        const char *bt_type_str;
        guint32 bt_type, bt_capab;

        g_return_val_if_fail (error == NULL || *error == NULL, FALSE);

        s_con = NM_SETTING_CONNECTION (nm_connection_get_setting (connection, NM_TYPE_SETTING_CONNECTION));
        g_assert (s_con);

        if (strcmp (nm_setting_connection_get_connection_type (s_con), NM_SETTING_BLUETOOTH_SETTING_NAME)) {
                g_set_error (error, 0, 0,
                             "The connection was not a Bluetooth connection.");
                return FALSE;
        }

        s_bt = NM_SETTING_BLUETOOTH (nm_connection_get_setting (connection, NM_TYPE_SETTING_BLUETOOTH));
        if (!s_bt) {
                g_set_error (error, 0, 0,
                             "The connection was not a valid Bluetooth connection.");
                return FALSE;
        }

        array = nm_setting_bluetooth_get_bdaddr (s_bt);
        if (!array || (array->len != ETH_ALEN)) {
                g_set_error (error, 0, 0,
                             "The connection did not contain a valid Bluetooth address.");
                return FALSE;
        }

        bt_type_str = nm_setting_bluetooth_get_connection_type (s_bt);
        g_assert (bt_type_str);

        bt_type = NM_BT_CAPABILITY_NONE;
        if (!strcmp (bt_type_str, NM_SETTING_BLUETOOTH_TYPE_DUN))
                bt_type = NM_BT_CAPABILITY_DUN;
        else if (!strcmp (bt_type_str, NM_SETTING_BLUETOOTH_TYPE_PANU))
                bt_type = NM_BT_CAPABILITY_NAP;

        bt_capab = nm_device_bt_get_capabilities (device);
        if (!(bt_type & bt_capab)) {
                g_set_error (error, 0, 0,
                             "The connection was not compatible with the device's capabilities.");
                return FALSE;
        }

        device_hw_str = nm_device_bt_get_hw_address (device);

        str = g_strdup_printf ("%02X:%02X:%02X:%02X:%02X:%02X",
                               array->data[0], array->data[1], array->data[2],
                               array->data[3], array->data[4], array->data[5]);
        addr_match = !strcmp (device_hw_str, str);
        g_free (str);

        return addr_match;
}
static gboolean
complete_connection (NMDevice *device,
                     NMConnection *connection,
                     const char *specific_object,
                     const GSList *existing_connections,
                     GError **error)
{
    NMDeviceBtPrivate *priv = NM_DEVICE_BT_GET_PRIVATE (device);
    NMSettingBluetooth *s_bt;
    const GByteArray *setting_bdaddr;
    struct ether_addr *devaddr = ether_aton (priv->bdaddr);
    const char *ctype;
    gboolean is_dun = FALSE, is_pan = FALSE;
    NMSettingGsm *s_gsm;
    NMSettingCdma *s_cdma;
    NMSettingSerial *s_serial;
    NMSettingPPP *s_ppp;
    const char *format = NULL, *preferred = NULL;

    s_gsm = nm_connection_get_setting_gsm (connection);
    s_cdma = nm_connection_get_setting_cdma (connection);
    s_serial = nm_connection_get_setting_serial (connection);
    s_ppp = nm_connection_get_setting_ppp (connection);

    s_bt = nm_connection_get_setting_bluetooth (connection);
    if (!s_bt) {
        s_bt = (NMSettingBluetooth *) nm_setting_bluetooth_new ();
        nm_connection_add_setting (connection, NM_SETTING (s_bt));
    }

    ctype = nm_setting_bluetooth_get_connection_type (s_bt);
    if (ctype) {
        if (!strcmp (ctype, NM_SETTING_BLUETOOTH_TYPE_DUN))
            is_dun = TRUE;
        else if (!strcmp (ctype, NM_SETTING_BLUETOOTH_TYPE_PANU))
            is_pan = TRUE;
    } else {
        if (s_gsm || s_cdma)
            is_dun = TRUE;
        else if (priv->capabilities & NM_BT_CAPABILITY_NAP)
            is_pan = TRUE;
    }

    if (is_pan) {
        /* Make sure the device supports PAN */
        if (!(priv->capabilities & NM_BT_CAPABILITY_NAP)) {
            g_set_error_literal (error,
                                 NM_SETTING_BLUETOOTH_ERROR,
                                 NM_SETTING_BLUETOOTH_ERROR_INVALID_PROPERTY,
                                 "PAN required but Bluetooth device does not support NAP");
            return FALSE;
        }

        /* PAN can't use any DUN-related settings */
        if (s_gsm || s_cdma || s_serial || s_ppp) {
            g_set_error_literal (error,
                                 NM_SETTING_BLUETOOTH_ERROR,
                                 NM_SETTING_BLUETOOTH_ERROR_INVALID_PROPERTY,
                                 "PAN incompatible with GSM, CDMA, or serial settings");
            return FALSE;
        }

        g_object_set (G_OBJECT (s_bt),
                      NM_SETTING_BLUETOOTH_TYPE, NM_SETTING_BLUETOOTH_TYPE_PANU,
                      NULL);

        format = _("PAN connection %d");
    } else if (is_dun) {
        /* Make sure the device supports PAN */
        if (!(priv->capabilities & NM_BT_CAPABILITY_DUN)) {
            g_set_error_literal (error,
                                 NM_SETTING_BLUETOOTH_ERROR,
                                 NM_SETTING_BLUETOOTH_ERROR_INVALID_PROPERTY,
                                 "DUN required but Bluetooth device does not support DUN");
            return FALSE;
        }

        /* Need at least a GSM or a CDMA setting */
        if (!s_gsm && !s_cdma) {
            g_set_error_literal (error,
                                 NM_SETTING_BLUETOOTH_ERROR,
                                 NM_SETTING_BLUETOOTH_ERROR_INVALID_PROPERTY,
                                 "Setting requires DUN but no GSM or CDMA setting is present");
            return FALSE;
        }

        g_object_set (G_OBJECT (s_bt),
                      NM_SETTING_BLUETOOTH_TYPE, NM_SETTING_BLUETOOTH_TYPE_DUN,
                      NULL);

        if (s_gsm) {
            format = _("GSM connection %d");
            if (!nm_setting_gsm_get_number (s_gsm))
                g_object_set (G_OBJECT (s_gsm), NM_SETTING_GSM_NUMBER, "*99#", NULL);
        } else if (s_cdma) {
            format = _("CDMA connection %d");
            if (!nm_setting_cdma_get_number (s_cdma))
                g_object_set (G_OBJECT (s_cdma), NM_SETTING_GSM_NUMBER, "#777", NULL);
        } else
            format = _("DUN connection %d");
    } else {
        g_set_error_literal (error,
                             NM_SETTING_BLUETOOTH_ERROR,
                             NM_SETTING_BLUETOOTH_ERROR_INVALID_PROPERTY,
                             "Unknown/unhandled Bluetooth connection type");
        return FALSE;
    }

    nm_utils_complete_generic (connection,
                               NM_SETTING_BLUETOOTH_SETTING_NAME,
                               existing_connections,
                               format,
                               preferred,
                               is_dun ? FALSE : TRUE); /* No IPv6 yet for DUN */

    setting_bdaddr = nm_setting_bluetooth_get_bdaddr (s_bt);
    if (setting_bdaddr) {
        /* Make sure the setting BT Address (if any) matches the device's */
        if (memcmp (setting_bdaddr->data, devaddr->ether_addr_octet, ETH_ALEN)) {
            g_set_error_literal (error,
                                 NM_SETTING_BLUETOOTH_ERROR,
                                 NM_SETTING_BLUETOOTH_ERROR_INVALID_PROPERTY,
                                 NM_SETTING_BLUETOOTH_BDADDR);
            return FALSE;
        }
    } else {
        GByteArray *bdaddr;
        const guint8 null_mac[ETH_ALEN] = { 0, 0, 0, 0, 0, 0 };

        /* Lock the connection to this device by default */
        if (memcmp (devaddr->ether_addr_octet, null_mac, ETH_ALEN)) {
            bdaddr = g_byte_array_sized_new (ETH_ALEN);
            g_byte_array_append (bdaddr, devaddr->ether_addr_octet, ETH_ALEN);
            g_object_set (G_OBJECT (s_bt), NM_SETTING_BLUETOOTH_BDADDR, bdaddr, NULL);
            g_byte_array_free (bdaddr, TRUE);
        }
    }

    return TRUE;
}