如何更新已经创建的Wi-Fi配置(或"UID XXX无权限更新[Wi-Fi]配置错误")? [英] How to update an already created Wi-Fi configuration (or "UID XXX does not have permission to update [Wi-Fi] configuration error")?

查看:137
本文介绍了如何更新已经创建的Wi-Fi配置(或"UID XXX无权限更新[Wi-Fi]配置错误")?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在开发一个管理Wi-Fi连接的应用程序.我的情况如下:假设整个建筑物都有一个名为"testing-tls"的Wi-Fi网络.我的应用程序应该只能连接到选定的访问点(基于BSSID或MAC ID).我们使用 TLS身份验证机制来验证用户(自定义CA证书).

I am developing an app which manages the Wi-Fi connections. My scenario is as follows: Let's say, the entire building has a Wi-Fi network named "testing-tls". My app should be able to connect to only selected access points (based on BSSID or MAC ID). We use TLS authentication mechanism to verify the user (Custom CA Certificates).

我能够通过该应用建立连接,但是当我尝试连接到其他访问点(不同的BSSID)时失败.即使我以编程方式创建了Wi-Fi配置,但在首次成功建立连接后仍无法更新配置.我已经在奥利奥(Oreo)和棉花糖(Marshmallow)中测试了我的应用程序.但是,我在奥利奥(Oreo)遇到问题(不确定牛轧糖).我开始怀疑创建后是否甚至可以更新配置.

I am able to establish a connection through the app, but failing when I try to connect to a different access point (different BSSID). Even though I created the Wi-Fi configuration programmatically, I am unable to update configuration after a first successful connection. I have tested my app in Oreo and Marshmallow. But, I am facing problems in Oreo (Not sure about Nougat). I am beginning to wonder if it is even possible to update the configuration once it is created.

private WifiConfiguration createWifiConfiguration() {
    WifiConfiguration config = new WifiConfiguration();
    config.SSID = "\"testing-tls\"";
    config.priority = 1;
    config.status = WifiConfiguration.Status.ENABLED;
    config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_EAP;
    config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.IEEE8021X);
    config.enterpriseConfig.setIdentity(identityName);
    config.enterpriseConfig.setEapMethod(WifiEnterpriseConfig.Eap.TLS);

    PKCS12ParseInfo parseInfo;
    try {
        parseInfo = CertificateUtils.parsePKCS12Certificate(
                       certificateFilePath, identityPassword);
        if (parseInfo != null) {
            config.enterpriseConfig.setClientKeyEntry(parseInfo.getPrivateKey(),
                           parseInfo.getCertificate());
            return config;
        }
        return null;
    } catch (KeyStoreException | NoSuchAlgorithmException | IOException |
                   CertificateException | UnrecoverableKeyException | KeyManagementException e1) {
        Timber.e("WifiMonitorService, Fail to parse the input certificate: %s", e1.toString());
        Toast.makeText(this, "Error occurred", Toast.LENGTH_SHORT).show();
        return null;
    }
}

2)尝试建立连接

private void establishWifiConnection(String result) {
    Timber.d("WifiMonitorService, establishing WifiConnection");

    WifiConfiguration configuration = createWifiConfiguration();
    if (configuration != null) {
        // result contains a mac id - 00:45:69:c5:34:f2
        configuration.BSSID = result;

        int networkId = wifiManager.addNetwork(configuration);
        if (networkId == -1) {
            networkId = getExistingNetworkId(wifiSsid);
            // Add a new configuration to the db
            if (networkId == -1) {
                Timber.e("Couldn't add network with SSID");
                Toast.makeText(this, "Wifi configuration error", Toast.LENGTH_SHORT).show();
                return;
            }
        }
        Timber.i("WifiMonitorService, # addNetwork returned: %d", networkId);
        wifiManager.saveConfiguration();
        wifiManager.enableNetwork(networkId, true);
        wifiManager.reassociate();
    } else {
        Toast.makeText(this, "Wifi conf Error occurred", Toast.LENGTH_SHORT).show();
    }
}

3)获取退出网络ID(如果存在)

private int getExistingNetworkId(String ssid) {
    List<WifiConfiguration> configuredNetworks  = 
    wifiManager.getConfiguredNetworks();
    if (configuredNetworks != null) {
        for (WifiConfiguration existingConfig : configuredNetworks) {
            if (existingConfig.SSID.equals("\"testing-tls\"")) {
                return existingConfig.networkId;
            }
        }
    }
    return -1;
}

清单权限如下:

<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WAKE_LOCK" />

<uses-permission android:name="android.permission.OVERRIDE_WIFI_CONFIG" />
<uses-permission android:name="android.permission.NETWORK_SETTINGS" />

<uses-feature android:name="android.hardware.wifi" />
<uses-feature android:name="android.hardware.camera" />

<permission
   android:name="android.permission.INTERACT_ACROSS_USERS"
   android:protectionLevel="signature" />

错误:我总是在奥利奥(Oreo)中得到UID 10189 does not have permission to update configuration error

2018-12-28 12:23:44.571 1320-1847/? E/WifiConfigManager: UID 10189 does not have permission to update configuration "testing-tls"WPA_EAP
2018-12-28 12:23:44.571 1320-1847/? I/WifiStateMachine: connectToUserSelectNetwork Allowing uid 10189 with insufficient permissions to connect=1

调查

在仔细研究了源代码之后,我在实现

  • 首先检查我们是否已经有一个具有提供的网络ID或configKey的网络
  • 如果未找到现有网络,请验证配置并添加.
  • 如果找到现有网络,请更新网络配置.在此之前,请检查应用程序是否具有更新网络所需的权限.
  • AddOrUpdateNetwork内部调用名为

    AddOrUpdateNetwork internally calls a function called canModifyNetwork:

    /**
     * Checks if |uid| has permission to modify the provided configuration.
     *
     * @param config         WifiConfiguration object corresponding to the network to be modified.
     * @param uid            UID of the app requesting the modification.
     * @param ignoreLockdown Ignore the configuration lockdown checks for connection attempts.
     */
    private boolean canModifyNetwork(WifiConfiguration config, int uid, boolean ignoreLockdown) {
        // Passpoint configurations are generated and managed by PasspointManager. They can be
        // added by either PasspointNetworkEvaluator (for auto connection) or Settings app
        // (for manual connection), and need to be removed once the connection is completed.
        // Since it is "owned" by us, so always allow us to modify them.
        if (config.isPasspoint() && uid == Process.WIFI_UID) {
            return true;
        }
        // EAP-SIM/AKA/AKA' network needs framework to update the anonymous identity provided
        // by authenticator back to the WifiConfiguration object.
        // Since it is "owned" by us, so always allow us to modify them.
        if (config.enterpriseConfig != null
                && uid == Process.WIFI_UID
                && TelephonyUtil.isSimEapMethod(config.enterpriseConfig.getEapMethod())) {
            return true;
        }
        final DevicePolicyManagerInternal dpmi = LocalServices.getService(
                DevicePolicyManagerInternal.class);
        final boolean isUidDeviceOwner = dpmi != null && dpmi.isActiveAdminWithPolicy(uid,
                DeviceAdminInfo.USES_POLICY_DEVICE_OWNER);
        // If |uid| corresponds to the device owner, allow all modifications.
        if (isUidDeviceOwner) {
            return true;
        }
        final boolean isCreator = (config.creatorUid == uid);
        // Check if the |uid| holds the |NETWORK_SETTINGS| permission if the caller asks us to
        // bypass the lockdown checks.
        if (ignoreLockdown) {
            return mWifiPermissionsUtil.checkNetworkSettingsPermission(uid);
        }
        // Check if device has DPM capability. If it has and |dpmi| is still null, then we
        // treat this case with suspicion and bail out.
        if (mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_DEVICE_ADMIN)
                && dpmi == null) {
            Log.w(TAG, "Error retrieving DPMI service.");
            return false;
        }
        // WiFi config lockdown related logic. At this point we know uid is NOT a Device Owner.
        final boolean isConfigEligibleForLockdown = dpmi != null && dpmi.isActiveAdminWithPolicy(
                config.creatorUid, DeviceAdminInfo.USES_POLICY_DEVICE_OWNER);
        if (!isConfigEligibleForLockdown) {
            return isCreator || mWifiPermissionsUtil.checkNetworkSettingsPermission(uid);
        }
        final ContentResolver resolver = mContext.getContentResolver();
        final boolean isLockdownFeatureEnabled = Settings.Global.getInt(resolver,
                Settings.Global.WIFI_DEVICE_OWNER_CONFIGS_LOCKDOWN, 0) != 0;
        return !isLockdownFeatureEnabled
                && mWifiPermissionsUtil.checkNetworkSettingsPermission(uid);
    }
    

    据我所知,只有以下uid有权访问修改网络配置.

    As far I can see, only the following uids have access to modify network configurations.

    1. 系统应用
    2. 设备所有者
    3. Creator(由于某种原因而失败)

    这两部手机的行为相同.

    I am getting the same behaviour in these two phones.

    1. 像素2(Oreo 8.0.0)
    2. 三星J8(Oreo 8.0.0)

    此外,三星J8始终显示以下警告:

    Additionally, Samsung J8 always shows this warning:

    CertificateException: java.security.cert.CertPathValidatorException: Trust anchor for certificate path not found
    

    问题:

    查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆