ttyd uses client cert
Bug: 363235314
Test: terminal app can show ttyd page, but the others cannot access to
the page
Change-Id: I60e4249f0170caa54e6c6777e9fc03cff176541c
diff --git a/android/TerminalApp/Android.bp b/android/TerminalApp/Android.bp
index d91af2f..932ca76 100644
--- a/android/TerminalApp/Android.bp
+++ b/android/TerminalApp/Android.bp
@@ -9,6 +9,7 @@
"java/**/*.kt",
],
resource_dirs: ["res"],
+ asset_dirs: ["assets"],
static_libs: [
"vm_launcher_lib",
"androidx-constraintlayout_constraintlayout",
diff --git a/android/TerminalApp/assets/client.p12 b/android/TerminalApp/assets/client.p12
new file mode 100644
index 0000000..f1f5820
--- /dev/null
+++ b/android/TerminalApp/assets/client.p12
Binary files differ
diff --git a/android/TerminalApp/java/com/android/virtualization/terminal/MainActivity.java b/android/TerminalApp/java/com/android/virtualization/terminal/MainActivity.java
index 1fabf8d..3aca929 100644
--- a/android/TerminalApp/java/com/android/virtualization/terminal/MainActivity.java
+++ b/android/TerminalApp/java/com/android/virtualization/terminal/MainActivity.java
@@ -19,6 +19,7 @@
import android.content.ClipboardManager;
import android.content.Context;
import android.content.Intent;
+import android.net.http.SslError;
import android.os.Bundle;
import android.system.ErrnoException;
import android.system.Os;
@@ -27,6 +28,8 @@
import android.view.MenuItem;
import android.view.View;
import android.view.accessibility.AccessibilityManager;
+import android.webkit.ClientCertRequest;
+import android.webkit.SslErrorHandler;
import android.webkit.WebChromeClient;
import android.webkit.WebResourceError;
import android.webkit.WebResourceRequest;
@@ -44,11 +47,17 @@
import java.io.FileDescriptor;
import java.io.FileNotFoundException;
import java.io.IOException;
+import java.io.InputStream;
import java.io.RandomAccessFile;
import java.net.InetAddress;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.UnknownHostException;
+import java.security.Key;
+import java.security.KeyStore;
+import java.security.PrivateKey;
+import java.security.cert.Certificate;
+import java.security.cert.X509Certificate;
public class MainActivity extends AppCompatActivity
implements VmLauncherServices.VmLauncherServiceCallback,
@@ -57,6 +66,8 @@
private static final String TAG = "VmTerminalApp";
private static final String VM_ADDR = "192.168.0.2";
private static final int TTYD_PORT = 7681;
+ private X509Certificate[] mCertificates;
+ private PrivateKey mPrivateKey;
private WebView mWebView;
private AccessibilityManager mAccessibilityManager;
@@ -92,6 +103,7 @@
mAccessibilityManager.addTouchExplorationStateChangeListener(this);
connectToTerminalService();
+ readClientCertificate();
}
private URL getTerminalServiceUrl() {
@@ -100,13 +112,35 @@
String query = needsAccessibility ? "?screenReaderMode=true" : "";
try {
- return new URL("http", VM_ADDR, TTYD_PORT, file + query);
+ return new URL("https", VM_ADDR, TTYD_PORT, file + query);
} catch (MalformedURLException e) {
// this cannot happen
return null;
}
}
+ private void readClientCertificate() {
+ // TODO(b/363235314): instead of using the key in asset, it should be generated in runtime
+ // and then provisioned in the vm via virtio-fs
+ try (InputStream keystoreFileStream =
+ getClass().getResourceAsStream("/assets/client.p12")) {
+ KeyStore keyStore = KeyStore.getInstance("PKCS12");
+ String password = "1234";
+ String alias = "1";
+
+ keyStore.load(keystoreFileStream, password != null ? password.toCharArray() : null);
+ Key key = keyStore.getKey(alias, password.toCharArray());
+ if (key instanceof PrivateKey) {
+ mPrivateKey = (PrivateKey) key;
+ Certificate cert = keyStore.getCertificate(alias);
+ mCertificates = new X509Certificate[1];
+ mCertificates[0] = (X509Certificate) cert;
+ }
+ } catch (Exception e) {
+ Log.e(TAG, e.getMessage());
+ }
+ }
+
private void connectToTerminalService() {
Log.i(TAG, "URL=" + getTerminalServiceUrl().toString());
mWebView.setWebViewClient(
@@ -146,6 +180,23 @@
view.setVisibility(View.VISIBLE);
}
}
+
+ @Override
+ public void onReceivedClientCertRequest(
+ WebView view, ClientCertRequest request) {
+ if (mPrivateKey != null && mCertificates != null) {
+ request.proceed(mPrivateKey, mCertificates);
+ return;
+ }
+ super.onReceivedClientCertRequest(view, request);
+ }
+
+ @Override
+ public void onReceivedSslError(
+ WebView view, SslErrorHandler handler, SslError error) {
+ // ttyd uses self-signed certificate
+ handler.proceed();
+ }
});
new Thread(
() -> {
diff --git a/build/debian/fai_config/files/etc/systemd/system/ttyd.service/AVF b/build/debian/fai_config/files/etc/systemd/system/ttyd.service/AVF
index 6b932e9..0aab770 100644
--- a/build/debian/fai_config/files/etc/systemd/system/ttyd.service/AVF
+++ b/build/debian/fai_config/files/etc/systemd/system/ttyd.service/AVF
@@ -3,7 +3,7 @@
After=syslog.target
After=network.target
[Service]
-ExecStart=/usr/local/bin/ttyd -W screen -aAxR -S main login -f droid
+ExecStart=/usr/local/bin/ttyd --ssl --ssl-cert /etc/ttyd/server.crt --ssl-key /etc/ttyd/server.key --ssl-ca /etc/ttyd/ca.crt -W screen -aAxR -S main login -f droid
Type=simple
Restart=always
User=root
diff --git a/build/debian/fai_config/files/etc/ttyd/ca.crt/AVF b/build/debian/fai_config/files/etc/ttyd/ca.crt/AVF
new file mode 100644
index 0000000..90d8c0e
--- /dev/null
+++ b/build/debian/fai_config/files/etc/ttyd/ca.crt/AVF
@@ -0,0 +1,21 @@
+-----BEGIN CERTIFICATE-----
+MIIDhzCCAm+gAwIBAgIUQkvURjf6sU5aJ7oK9usHnJHsc/owDQYJKoZIhvcNAQEL
+BQAwUzELMAkGA1UEBhMCQ04xCzAJBgNVBAgMAkdEMQswCQYDVQQHDAJTWjETMBEG
+A1UECgwKQWNtZSwgSW5jLjEVMBMGA1UEAwwMQWNtZSBSb290IENBMB4XDTI0MTAx
+NDAxMjgzN1oXDTI1MTAxNDAxMjgzN1owUzELMAkGA1UEBhMCQ04xCzAJBgNVBAgM
+AkdEMQswCQYDVQQHDAJTWjETMBEGA1UECgwKQWNtZSwgSW5jLjEVMBMGA1UEAwwM
+QWNtZSBSb290IENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtjgS
+ePtWI6xARLzM1bUMvqtWwY4ci4TzcOcfLfV5Eqbb135NSBKQ+Q2IAguc2Bl3ZVRE
+08GhQ9XJOo+mp2SUY/8+SJpCVhVlWvF6LwXd8X5pZ9GCem0FXY02kMr5ZiTs/CN2
+LZIyJKgXCT/5208on+BbiNp0pk2Pz1nDOdpxvkDJ8UKRWLwqCAEM/rcN1Lc00aln
+N/Rfi/CQE+MDAmhuy/nxr37ldqhkN+xM4bhNs1bjyVposKtbmFUY/SD3ca5CMawU
+E3l5hZ5kfua7lelEPVhvNYJcxffVO0fPNEbUKr1WsPLrnidqegcU8bml1BoCphgA
+qzoxD0rZniqMsom/vwIDAQABo1MwUTAdBgNVHQ4EFgQUZOHF7/arn8ODqEj1Wifk
+dEA5TFkwHwYDVR0jBBgwFoAUZOHF7/arn8ODqEj1WifkdEA5TFkwDwYDVR0TAQH/
+BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAVets3IybnIycAtajxpJygdji/95t
+ikdyWbi8lrszC0E5bCR9XPQKnqx/svKYrEVQNihH/nZ6TlTv0f3b77+92sVlmQfl
+a3KKI6qIgcqNEO2lHYsS+cPeBmaM6WXcEPe6gEnan1i5N16B9g9ntY4lOg8Z4roR
+2lVVCCNwabyBxb5oQDsN1IDeJ7JRRZqGGduDSZTvdd36GqNhMvXQjluyJCCFd1Hv
+IwwJmAR2GMUQU8Eoa+zGzW1Inf1YJytTu8SeQ+hYy2QCG88vZigJdifmhETDDz9Q
+xQjp1SCNIBxFHY2voqtiJtfupN5pVieECZS42pbVHMIAUOk7BmNcEWnSKw==
+-----END CERTIFICATE-----
diff --git a/build/debian/fai_config/files/etc/ttyd/server.crt/AVF b/build/debian/fai_config/files/etc/ttyd/server.crt/AVF
new file mode 100644
index 0000000..b4ca829
--- /dev/null
+++ b/build/debian/fai_config/files/etc/ttyd/server.crt/AVF
@@ -0,0 +1,21 @@
+-----BEGIN CERTIFICATE-----
+MIIDiTCCAnGgAwIBAgIUasfD1K/4tJHwNRXL2kdSD9VbeSwwDQYJKoZIhvcNAQEL
+BQAwUzELMAkGA1UEBhMCQ04xCzAJBgNVBAgMAkdEMQswCQYDVQQHDAJTWjETMBEG
+A1UECgwKQWNtZSwgSW5jLjEVMBMGA1UEAwwMQWNtZSBSb290IENBMB4XDTI0MTAx
+NDAxMjgzOFoXDTI1MTAxNDAxMjgzOFowUDELMAkGA1UEBhMCQ04xCzAJBgNVBAgM
+AkdEMQswCQYDVQQHDAJTWjETMBEGA1UECgwKQWNtZSwgSW5jLjESMBAGA1UEAwwJ
+bG9jYWxob3N0MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA3+uVF4TP
+jUjfL8vJlECAN1rLFK8lDuOUv52VCrW7MXMfGYlA4nk1OKDjygnZIpET6I9cTfCG
+Xiwad6bU6Oqy4MZ2i338F+eERrGpkitSQ7QRqZannjBIDFxXZvJpMTJDIWNCmz+P
+K2VcvCh8im2tJA66wJogUcVmJBugNqleqxFcxPvXOdBdWBK7JYOcb4J643eLX6+D
+X6v2QTlKXfihouVC8wAzbw9HHmOVb7ono1rV7xpcFrOyBiDGVSgEteiB8l26iXA9
+fExkb0rUzHjlgvb/l8/nGAaQHd0eE+/SGd4tXvs9KHX6XJh/PI0ExTsDIBDcuVOt
+2YzXeuM6zzrKLQIDAQABo1gwVjAUBgNVHREEDTALgglsb2NhbGhvc3QwHQYDVR0O
+BBYEFHpFYqFC/AEOfWfdZmpy5YBZfgR2MB8GA1UdIwQYMBaAFGThxe/2q5/Dg6hI
+9Von5HRAOUxZMA0GCSqGSIb3DQEBCwUAA4IBAQBQspP3wo3yzcPWuFk4lRyo7zpF
+JfBBX0UU1Z0MQfIGxLC2YtRvxobRqwLcKUKQjBqUuRdukleOaVVFeXb/HI9vY3ji
+9PfUb2UJ4O3z3pdSK0EwXbkCidtUflRLvPG6dgBrXyLOqxBqA5lWR2ds5HRAMRAi
+eXfDkJTmNOAQAnPgM+35FBgmhh6axG+bUudvvVoA8ca+zW9i1R6/vblxYJ6bhmw0
+8s+uoAX6FXcZ0YFOGdhcpJmnbiRd3D0VVacjc3b9pjFOI8d3bh9pR47p0kVOaRsh
+aAG3gZhyMPOgbYceCjfzND5YhycDI+MzPo/JOYdhHGGJawoh1nP94QNPan6J
+-----END CERTIFICATE-----
diff --git a/build/debian/fai_config/files/etc/ttyd/server.key/AVF b/build/debian/fai_config/files/etc/ttyd/server.key/AVF
new file mode 100644
index 0000000..37933b2
--- /dev/null
+++ b/build/debian/fai_config/files/etc/ttyd/server.key/AVF
@@ -0,0 +1,28 @@
+-----BEGIN PRIVATE KEY-----
+MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDf65UXhM+NSN8v
+y8mUQIA3WssUryUO45S/nZUKtbsxcx8ZiUDieTU4oOPKCdkikRPoj1xN8IZeLBp3
+ptTo6rLgxnaLffwX54RGsamSK1JDtBGplqeeMEgMXFdm8mkxMkMhY0KbP48rZVy8
+KHyKba0kDrrAmiBRxWYkG6A2qV6rEVzE+9c50F1YErslg5xvgnrjd4tfr4Nfq/ZB
+OUpd+KGi5ULzADNvD0ceY5VvuiejWtXvGlwWs7IGIMZVKAS16IHyXbqJcD18TGRv
+StTMeOWC9v+Xz+cYBpAd3R4T79IZ3i1e+z0odfpcmH88jQTFOwMgENy5U63ZjNd6
+4zrPOsotAgMBAAECggEAARJYlD12ch5WM2aDrPOGOAtREOfP7CCwWcMiOfBP72iR
+Y9Vipxmuz16nwTJ22F7HvPsdPOUo1cFtWhim2Aqr/ZxuT4Ce9oVrk6iDwRdeuYdY
+cIhtChvJi+p0ggMcuyzp90+3AYXxynsOlCufMjSNGaqvYUsNEXnJFSgiKr7mgbIO
+J0VU1Wrquw7N58RKL+T3xEvE7uO3QpLOim2MbfRSVq/JGNxqAGw0/uxtjFs7Vtf9
+z44e/ULeYDS7zMj6cMggxQp5nfzcboGoNVUEDgYjOzqXCe4cG0n3XfN7GJhaS1ZF
+tPd8l4Ch0IrT4hs5uVFaMdFbj+er7mvmqfTVytrRmQKBgQD2kVB53EKhqxgvz2N7
+bAJglOLd6FWKsWlLMSdER0/4dRVRMIBxnYWgQ0gaRc4TM7oyKOl3MDF9jdDne5KJ
+cnfzFoH2GD6VBQRr0mFmV1UV6oHEjDJBasMo/1Vw3TJ4oZgZpYpJjrDmPWZqHUs4
+I79TdvJrNFSmk3MGVFjatLIq5QKBgQDofHpHfBeRCn2Z3OOkiAN5V53n5deZl6Jt
+lGTsrXKpEzRTre4LWZojoB9hiGjptZkXHA2HW90RiV9OHhTa8W9ZntLnOnWc5RUn
+Tzh14KupjsBQm/gE8SuqHSDx1mxTnIUo0W28d/Beecri5KfaoEY+wxZXOeQy5JFR
+ec/AhU4FqQKBgGhVzUwDnF502+M/SsVrSwY7elSUf74UnI2o2wjVdE2anc6hS3jI
+Q0cxsU0MxMrzVJLtJP2+cvLCE+ggLj3jJkbC+3N7ht/gI6LMf1KjGeoQNaFKAeoU
+l0i94xXDRBwvpQEVP5MowkprKO82PiIfXlKfPq2Gk1t5gW7oOkExvULRAoGBAK7R
+051nec0uJ06I5IE3ae1X7jyP//TWKmTeHpo+vybWcxWth3/va9H4OUC9M67ySGEx
+ThcIBA+IzirOwf31aTbqEEuiEQje1m5NyvYQ8OS6nHDBJ9qHg78S0lAoXiLtYtBT
+04HSauSQDvlY2cOzm77cMjN7K9b9Oy0aPRfW5dmpAoGAGesq4Ojky4crpi0H1O7n
+cMuIAzaPozsMx7iSrhUe69fwVFiMkEKR6ems01DmjYwPb6DtxCieaRlGbd9E8oIZ
+y6n+Uh9Qbc5sDhPMsys6NyKOv/A6rkn49/etr40f0Z5g9g/d2+qtwoAXjo3sSPuW
+7iqbruRjbKUaJKzdpIqOKD0=
+-----END PRIVATE KEY-----