summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorJan Nordqvist <jannq@google.com>2015-03-25 18:56:30 -0700
committerVinit Deshpande <vinitd@google.com>2015-04-07 22:14:24 +0000
commit994932f1949316fe5520d6c690e6bd9b49b88ba6 (patch)
tree9285b2b3766d2e9979cb860e417f352b2ca3f681 /src
parent33c0a544f35937a5175e45dea1c71d37595c4d3f (diff)
downloadandroid_packages_apps_CertInstaller-994932f1949316fe5520d6c690e6bd9b49b88ba6.tar.gz
android_packages_apps_CertInstaller-994932f1949316fe5520d6c690e6bd9b49b88ba6.tar.bz2
android_packages_apps_CertInstaller-994932f1949316fe5520d6c690e6bd9b49b88ba6.zip
Basic WiFi config installer app.
Change-Id: I12e26955f4057db7a1772eacfec6ce9fa58f4437
Diffstat (limited to 'src')
-rw-r--r--src/com/android/certinstaller/CertInstallerMain.java97
-rw-r--r--src/com/android/certinstaller/WiFiInstaller.java228
2 files changed, 290 insertions, 35 deletions
diff --git a/src/com/android/certinstaller/CertInstallerMain.java b/src/com/android/certinstaller/CertInstallerMain.java
index e184ae6..f95bb84 100644
--- a/src/com/android/certinstaller/CertInstallerMain.java
+++ b/src/com/android/certinstaller/CertInstallerMain.java
@@ -28,11 +28,14 @@ import android.security.KeyChain;
import android.util.Log;
import android.widget.Toast;
-import libcore.io.IoUtils;
-import libcore.io.Streams;
-
+import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
+import java.util.HashMap;
+import java.util.Map;
+
+import libcore.io.IoUtils;
+import libcore.io.Streams;
/**
* The main class for installing certificates to the system keystore. It reacts
@@ -46,19 +49,28 @@ public class CertInstallerMain extends PreferenceActivity {
private static final String INSTALL_CERT_AS_USER_CLASS = ".InstallCertAsUser";
- private static final String[] ACCEPT_MIME_TYPES = {
- "application/x-pkcs12",
- "application/x-x509-ca-cert",
- "application/x-x509-user-cert",
- "application/x-x509-server-cert",
- "application/x-pem-file",
- "application/pkix-cert"
- };
+ public static final String WIFI_CONFIG = "wifi-config";
+ public static final String WIFI_CONFIG_DATA = "wifi-config-data";
+ public static final String WIFI_CONFIG_FILE = "wifi-config-file";
+
+ private static Map<String,String> MIME_MAPPINGS = new HashMap<>();
+
+ static {
+ MIME_MAPPINGS.put("application/x-x509-ca-cert", KeyChain.EXTRA_CERTIFICATE);
+ MIME_MAPPINGS.put("application/x-x509-user-cert", KeyChain.EXTRA_CERTIFICATE);
+ MIME_MAPPINGS.put("application/x-x509-server-cert", KeyChain.EXTRA_CERTIFICATE);
+ MIME_MAPPINGS.put("application/x-pem-file", KeyChain.EXTRA_CERTIFICATE);
+ MIME_MAPPINGS.put("application/pkix-cert", KeyChain.EXTRA_CERTIFICATE);
+ MIME_MAPPINGS.put("application/x-pkcs12", KeyChain.EXTRA_PKCS12);
+ MIME_MAPPINGS.put("application/x-wifi-config", WIFI_CONFIG);
+ }
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
+ Log.d("WFII", "Created!");
+
setResult(RESULT_CANCELED);
UserManager userManager = (UserManager) getSystemService(Context.USER_SERVICE);
@@ -96,7 +108,7 @@ public class CertInstallerMain extends PreferenceActivity {
|| bundle.containsKey(Credentials.EXTRA_INSTALL_AS_UID)))) {
final Intent openIntent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
openIntent.setType("*/*");
- openIntent.putExtra(Intent.EXTRA_MIME_TYPES, ACCEPT_MIME_TYPES);
+ openIntent.putExtra(Intent.EXTRA_MIME_TYPES, MIME_MAPPINGS.keySet().toArray());
openIntent.putExtra(DocumentsContract.EXTRA_SHOW_ADVANCED, true);
startActivityForResult(openIntent, REQUEST_OPEN_DOCUMENT);
} else {
@@ -114,38 +126,53 @@ public class CertInstallerMain extends PreferenceActivity {
mimeType = getContentResolver().getType(uri);
}
- InputStream in = null;
- try {
- in = getContentResolver().openInputStream(uri);
-
- final byte[] raw = Streams.readFully(in);
- startInstallActivity(mimeType, raw);
+ String target = MIME_MAPPINGS.get(mimeType);
+ if (target == null) {
+ throw new IllegalArgumentException("Unknown MIME type: " + mimeType);
+ }
- } catch (IOException e) {
- Log.e(TAG, "Failed to read certificate: " + e);
- Toast.makeText(this, R.string.cert_read_error, Toast.LENGTH_LONG).show();
- } finally {
- IoUtils.closeQuietly(in);
+ if (WIFI_CONFIG.equals(target)) {
+ startWifiInstallActivity(mimeType, uri);
+ }
+ else {
+ InputStream in = null;
+ try {
+ in = getContentResolver().openInputStream(uri);
+
+ final byte[] raw = Streams.readFully(in);
+ startInstallActivity(target, raw);
+
+ } catch (IOException e) {
+ Log.e(TAG, "Failed to read certificate: " + e);
+ Toast.makeText(this, R.string.cert_read_error, Toast.LENGTH_LONG).show();
+ } finally {
+ IoUtils.closeQuietly(in);
+ }
}
}
- private void startInstallActivity(String mimeType, byte[] value) {
+ private void startInstallActivity(String target, byte[] value) {
Intent intent = new Intent(this, CertInstaller.class);
- if ("application/x-pkcs12".equals(mimeType)) {
- intent.putExtra(KeyChain.EXTRA_PKCS12, value);
- } else if ("application/x-x509-ca-cert".equals(mimeType)
- || "application/x-x509-user-cert".equals(mimeType)
- || "application/x-x509-server-cert".equals(mimeType)
- || "application/x-pem-file".equals(mimeType)
- || "application/pkix-cert".equals(mimeType)) {
- intent.putExtra(KeyChain.EXTRA_CERTIFICATE, value);
- } else {
- throw new IllegalArgumentException("Unknown MIME type: " + mimeType);
- }
+ intent.putExtra(target, value);
startActivityForResult(intent, REQUEST_INSTALL);
}
+ private void startWifiInstallActivity(String mimeType, Uri uri) {
+ Intent intent = new Intent(this, WiFiInstaller.class);
+ try (BufferedInputStream in =
+ new BufferedInputStream(getContentResolver().openInputStream(uri))) {
+ byte[] data = Streams.readFully(in);
+ intent.putExtra(WIFI_CONFIG_FILE, uri.toString());
+ intent.putExtra(WIFI_CONFIG_DATA, data);
+ intent.putExtra(WIFI_CONFIG, mimeType);
+ startActivityForResult(intent, REQUEST_INSTALL);
+ } catch (IOException e) {
+ Log.e(TAG, "Failed to read wifi config: " + e);
+ Toast.makeText(this, R.string.cert_read_error, Toast.LENGTH_LONG).show();
+ }
+ }
+
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == REQUEST_OPEN_DOCUMENT) {
diff --git a/src/com/android/certinstaller/WiFiInstaller.java b/src/com/android/certinstaller/WiFiInstaller.java
new file mode 100644
index 0000000..727134f
--- /dev/null
+++ b/src/com/android/certinstaller/WiFiInstaller.java
@@ -0,0 +1,228 @@
+package com.android.certinstaller;
+
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.content.res.Resources;
+import android.net.wifi.WifiConfiguration;
+import android.net.wifi.WifiEnterpriseConfig;
+import android.net.wifi.WifiManager;
+import android.os.Bundle;
+import android.util.Log;
+import android.view.View;
+import android.widget.Button;
+import android.widget.TextView;
+
+import java.security.PrivateKey;
+import java.security.interfaces.RSAPrivateKey;
+import java.util.Collection;
+
+public class WiFiInstaller extends Activity {
+
+ @Override
+ protected void onCreate(Bundle savedStates) {
+ super.onCreate(savedStates);
+
+ Bundle bundle = getIntent().getExtras();
+ String uriString = bundle.getString(CertInstallerMain.WIFI_CONFIG_FILE);
+ String mimeType = bundle.getString(CertInstallerMain.WIFI_CONFIG);
+ byte[] data = bundle.getByteArray(CertInstallerMain.WIFI_CONFIG_DATA);
+
+ Log.d("WFII", "WiFi data for " + CertInstallerMain.WIFI_CONFIG + ": " +
+ mimeType + " is " + (data != null ? data.length : "-"));
+
+ WifiManager wifiManager = (WifiManager) getSystemService(Context.WIFI_SERVICE);
+ WifiConfiguration wifiConfiguration = wifiManager.buildWifiConfig(uriString, mimeType, data);
+ createMainDialog(wifiManager, wifiConfiguration);
+ }
+
+ private static String roamingConsortiumsToString(Collection<Long> ois) {
+ StringBuilder sb = new StringBuilder();
+ boolean first = true;
+ for (long oi : ois) {
+ if (first) {
+ first = false;
+ } else {
+ sb.append(", ");
+ }
+ if (Long.numberOfLeadingZeros(oi) > 40) {
+ sb.append(String.format("%06x", oi));
+ } else {
+ sb.append(String.format("%010x", oi));
+ }
+ }
+ return sb.toString();
+ }
+
+ private static String mapEAPMethod(WifiEnterpriseConfig config) {
+ switch (config.getEapMethod()) {
+ case WifiEnterpriseConfig.Eap.TTLS:
+ return "TTLS+" + mapInnerMethod(config.getPhase2Method());
+ case WifiEnterpriseConfig.Eap.TLS:
+ return "TLS";
+ case WifiEnterpriseConfig.Eap.SIM:
+ return "SIM";
+ case WifiEnterpriseConfig.Eap.AKA:
+ return "AKA";
+ case WifiEnterpriseConfig.Eap.AKA_PRIME:
+ return "AKA'";
+ default:
+ return String.format("Unsupported method %d", config.getEapMethod());
+ }
+ }
+
+ private static String mapInnerMethod(int id) {
+ switch (id) {
+ case WifiEnterpriseConfig.Phase2.NONE:
+ return "none";
+ case WifiEnterpriseConfig.Phase2.PAP:
+ return "PAP";
+ case WifiEnterpriseConfig.Phase2.MSCHAP:
+ return "MS-CHAP";
+ case WifiEnterpriseConfig.Phase2.MSCHAPV2:
+ return "MS-CHAPv2";
+ case WifiEnterpriseConfig.Phase2.GTC:
+ return "GTC";
+ default:
+ return String.format("Unsupported inner method %d", id);
+ }
+ }
+
+ private void createMainDialog(final WifiManager wifiManager, final WifiConfiguration config) {
+ Resources res = getResources();
+ AlertDialog.Builder builder = new AlertDialog.Builder(this);
+ View layout = getLayoutInflater().inflate(R.layout.wifi_main_dialog, null);
+ builder.setView(layout);
+
+ TextView text = (TextView) layout.findViewById(R.id.wifi_info);
+ text.setText(String.format("WiFi configuration from %s (%s)",
+ config.providerFriendlyName, config.FQDN));
+
+ Button detailButton = (Button) layout.findViewById(R.id.wifi_detail);
+
+ detailButton.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ createDetailDialog(config);
+ }
+ });
+
+ builder.setTitle(res.getString(R.string.wifi_title));
+
+ builder.setPositiveButton(R.string.wifi_install_label, new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ Log.d("WFDL", "OK");
+ wifiManager.addNetwork(config);
+ wifiManager.saveConfiguration();
+ dialog.dismiss();
+ finish();
+ }
+ });
+
+ builder.setNegativeButton(R.string.wifi_cancel_label, new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ Log.d("WFDL", "Cancel");
+ dialog.dismiss();
+ finish();
+ }
+ });
+
+ builder.create().show();
+ }
+
+ private void createDetailDialog(WifiConfiguration config) {
+ Resources res = getResources();
+ AlertDialog.Builder builder = new AlertDialog.Builder(this);
+ View layout = getLayoutInflater().inflate(R.layout.wifi_detail_dialog, null);
+ layout.setHorizontalScrollBarEnabled(true);
+ builder.setView(layout);
+
+ TextView text = (TextView) layout.findViewById(R.id.wifi_detail_text);
+ text.setText(getDetailedInfo(res, config));
+
+ builder.setTitle(String.format(res.getString(R.string.wifi_detail_title),
+ config.providerFriendlyName));
+
+ builder.setPositiveButton(R.string.wifi_dismiss_label,
+ new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ Log.d("WFDL", "detail dismiss");
+ dialog.dismiss();
+ }
+ });
+
+ builder.create().show();
+ }
+
+ private static String getDetailedInfo(Resources res, WifiConfiguration wifiConfiguration) {
+ if (wifiConfiguration == null) {
+ return res.getString(R.string.wifi_no_config);
+ }
+
+ StringBuilder details = new StringBuilder();
+ WifiEnterpriseConfig enterpriseConfig = wifiConfiguration.enterpriseConfig;
+ details.append(String.format(res.getString(R.string.wifi_config_text),
+ wifiConfiguration.providerFriendlyName,
+ wifiConfiguration.FQDN,
+ roamingConsortiumsToString(wifiConfiguration.roamingConsortiumIds),
+ enterpriseConfig.getRealm(),
+ mapEAPMethod(enterpriseConfig)));
+
+ switch (enterpriseConfig.getEapMethod()) {
+ case WifiEnterpriseConfig.Eap.TTLS:
+ details.append(String.format(res.getString(R.string.wifi_ttls_config_text), enterpriseConfig.getIdentity()));
+ details.append("Password: ").append(enterpriseConfig.getPassword()).append('\n'); // !!!
+ if (enterpriseConfig.getCaCertificate() != null) {
+ details.append(String.format(res.getString(R.string.wifi_trust_config_text), enterpriseConfig.getCaCertificate()));
+ }
+ break;
+ case WifiEnterpriseConfig.Eap.TLS:
+ PrivateKey key = enterpriseConfig.getClientPrivateKey();
+ String keyInfo;
+ if (key instanceof RSAPrivateKey) {
+ RSAPrivateKey rsaKey = (RSAPrivateKey) key;
+ int bits = rsaKey.getModulus().bitLength();
+ keyInfo = "RSA " + (((bits + 7) / 8)*8) + " bits";
+ }
+ else {
+ keyInfo = key.getAlgorithm();
+ }
+ details.append(String.format(res.getString(R.string.wifi_tls_config_text), enterpriseConfig.getClientCertificate(), keyInfo));
+ if (enterpriseConfig.getCaCertificate() != null) {
+ details.append(String.format(res.getString(R.string.wifi_trust_config_text), enterpriseConfig.getCaCertificate()));
+ }
+ break;
+ case WifiEnterpriseConfig.Eap.SIM:
+ case WifiEnterpriseConfig.Eap.AKA:
+ case WifiEnterpriseConfig.Eap.AKA_PRIME:
+ details.append(String.format(res.getString(R.string.wifi_sim_config_text), enterpriseConfig.getPlmn()));
+ break;
+ }
+ return details.toString();
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ }
+
+ @Override
+ protected void onPause() {
+ super.onPause();
+ }
+
+ @Override
+ protected void onSaveInstanceState(Bundle outStates) {
+ super.onSaveInstanceState(outStates);
+ }
+
+ @Override
+ protected void onActivityResult(int requestCode, int resultCode, Intent data) {
+ finish();
+ }
+}