diff options
Diffstat (limited to 'vendor/libadb-android/README.md')
| -rw-r--r-- | vendor/libadb-android/README.md | 240 |
1 files changed, 41 insertions, 199 deletions
diff --git a/vendor/libadb-android/README.md b/vendor/libadb-android/README.md index 815cf46..9a03a59 100644 --- a/vendor/libadb-android/README.md +++ b/vendor/libadb-android/README.md @@ -1,199 +1,41 @@ -# LibADB Android - -ADB library for Android. It enables an app to connect to the ADB daemon (`adbd` process) belonging to the same or a -different device and execute arbitrary services or commands (via `shell:` service). - -**Disclaimer:** This library has never gone through a security audit. Please, proceed with caution if security is -crucial for your app. Avoid using the APIs for reasons other than connecting or using ADB. For the safety of your app -and its users, open a remote service instead of using ADB and ask the user to disconnect Wireless debugging. - -## Getting Started -### Adding Dependencies -LibADB Android is available via JitPack. - -```groovy -// Top level build file -repositories { - mavenCentral() - maven { url "https://jitpack.io" } -} - -// Add to dependencies section -dependencies { - // Add this library - implementation 'com.github.MuntashirAkon:libadb-android:3.1.1' - - // Library to generate X509Certificate. You can also use BouncyCastle for - // this. See example for use-case. - // implementation 'com.github.MuntashirAkon:sun-security-android:1.1' - - // Bypass hidden API if you want to use the Android default Conscrypt in - // Android 9 (Pie) or later. It also requires additional steps. See - // https://github.com/LSPosed/AndroidHiddenApiBypass to find out more about - // this. - // implementation 'org.lsposed.hiddenapibypass:hiddenapibypass:6.1' - - // Use custom Conscrypt library. If you want to connect to a remote ADB - // daemon instead of the device the app is currently running or do not want - // to bypass hidden API, this is the recommended choice. - implementation 'org.conscrypt:conscrypt-android:2.5.3' -} -``` - -If you're using the custom Conscrypt library in order to connect to a remote ADB daemon and the app targets Android -version below 4.4, you have to extend `android.app.Application` to apply fixes for the random number generation: -```java -public class MyAwesomeApp extends Application { - @Override - public void onCreate() { - super.onCreate(); - // Fix random number generation in Android versions below 4.4. - PRNGFixes.apply(); - } - - @Override - protected void attachBaseContext(Context base) { - super.attachBaseContext(base); - // Uncomment the following line if you want to bypass hidden API as - // described above. - // if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { - // HiddenApiBypass.addHiddenApiExemptions("L"); - // } - } -} -``` - -**Notice:** Conscrypt supports only API 9 (Gingerbread) or later, meaning you cannot use ADB pairing or any TLSv1.3 -features in API less than 9. The corresponding methods are already annotated properly. So, you don't have to worry about -compatibility issues that may arise when your app's minimum SDK is set to one of the unsupported versions. - -### Configuring ADB -Instead of doing everything manually, you can create a concrete implementation of the `AbsAdbConnectionManager` class. -Example: - -```java -public class AdbConnectionManager extends AbsAdbConnectionManager { - private static AbsAdbConnectionManager INSTANCE; - - public static AbsAdbConnectionManager getInstance() throws Exception { - if (INSTANCE == null) { - INSTANCE = new AdbConnectionManager(); - } - return INSTANCE; - } - - private PrivateKey mPrivateKey; - private Certificate mCertificate; - - private AdbConnectionManager() throws Exception { - // Set the API version whose `adbd` is running - setApi(Build.VERSION.SDK_INT); - // TODO: Load private key and certificate (along with public key) from - // some place such as KeyStore or file system. - mPrivateKey = ...; - mCertificate = ...; - if (mPrivateKey == null) { - // Generate a new key pair - int keySize = 2048; - KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA"); - keyPairGenerator.initialize(keySize, SecureRandom.getInstance("SHA1PRNG")); - KeyPair generateKeyPair = keyPairGenerator.generateKeyPair(); - PublicKey publicKey = generateKeyPair.getPublic(); - mPrivateKey = generateKeyPair.getPrivate(); - // Generate a certificate - // On Android, it requires sun.security-android library as mentioned - // above. - String subject = "CN=My Awesome App"; - String algorithmName = "SHA512withRSA"; - long expiryDate = System.currentTimeMillis() + 86400000; - CertificateExtensions certificateExtensions = new CertificateExtensions(); - certificateExtensions.set("SubjectKeyIdentifier", new SubjectKeyIdentifierExtension( - new KeyIdentifier(publicKey).getIdentifier())); - X500Name x500Name = new X500Name(subject); - Date notBefore = new Date(); - Date notAfter = new Date(expiryDate); - certificateExtensions.set("PrivateKeyUsage", new PrivateKeyUsageExtension(notBefore, notAfter)); - CertificateValidity certificateValidity = new CertificateValidity(notBefore, notAfter); - X509CertInfo x509CertInfo = new X509CertInfo(); - x509CertInfo.set("version", new CertificateVersion(2)); - x509CertInfo.set("serialNumber", new CertificateSerialNumber(new Random().nextInt() & Integer.MAX_VALUE)); - x509CertInfo.set("algorithmID", new CertificateAlgorithmId(AlgorithmId.get(algorithmName))); - x509CertInfo.set("subject", new CertificateSubjectName(x500Name)); - x509CertInfo.set("key", new CertificateX509Key(publicKey)); - x509CertInfo.set("validity", certificateValidity); - x509CertInfo.set("issuer", new CertificateIssuerName(x500Name)); - x509CertInfo.set("extensions", certificateExtensions); - X509CertImpl x509CertImpl = new X509CertImpl(x509CertInfo); - x509CertImpl.sign(mPrivateKey, algorithmName); - mCertificate = x509CertImpl; - // TODO: Store the key pair to some place else. - } - } - - @NonNull - @Override - protected PrivateKey getPrivateKey() { - return mPrivateKey; - } - - @NonNull - @Override - protected Certificate getCertificate() { - return mCertificate; - } - - @NonNull - @Override - protected String getDeviceName() { - return "MyAwesomeApp"; - } -} -``` - -### Connecting to ADB - -You can connect to ADB in several ways from the `AbsAdbConnectionManager`: - -| Method | Description | -|---------------------------------|---------------------------------------------------------------------------------------------------------------| -| `connect(host, port)` | Connect using a host address and a port number | -| `connect(port)` | Connect using a host address set by `setHostAddress()` and a port number | -| `connectTcp(Context, timeout)` | (SDK 16+) Discover host address and port number automatically for ADB over TCP and connect to it | -| `connectTls(Context, timeout)` | (SDK 16+) Discover host address and port number automatically for TLS (from Android 9) and connect to it | -| `autoConnect(Context, timeout)` | (SDK 16+) Discover host address and port number automatically for both ADB over TCP and TLS and connect to it | - -### Wireless Debugging -Internally, ADB over TCP and Wireless Debugging are very similar except Wireless Debugging requires an extra step of -_pairing_ the device. In order to pair a new device, you can simply invoke `AdbConnectionManager.getInstance().pair(host, port, pairingCode)`. -After the pairing, you can connect to ADB via the usual `connect()` methods without any additional steps. - -### Opening ADB Shell for Executing Arbitrary Commands -Simply use `AdbConnectionManager.getInstance().openStream("shell:")`. This will return an `AdbStream` which can be used -to read/write to the ADB shell via `AdbStream#openInputStream()` and `AdbStream#openOutputStream()` methods -respectively like a normal Java `Process`. While it is possible to read/write in the same thread (first write and then -read), this is not recommended because the shell might be stuck indefinitely for commands such as `top`. - -**NOTE:** If you want to create a full-featured terminal emulator, this approach isn't recommended. Instead, you should -create a remote service via `app_process` or start an SSH server and connect to it. - -### Other services -You can also use other services via the `AdbConnectionManager#openStream()` methods. See [SERVICES.md](./SERVICES.md) -for more information. - -## For Java (non-Android) Projects -It is possible to modify this library to work on non-Android project. But it isn't supported because Spake2-Java only -provides stable releases for Android. However, you can incorporate this library in your project by manually compiling -Spake2 library for your platforms. - -## Contributing -By contributing to this project, you permit your work to be released under the terms of GNU General Public License, -Version 3 or later **or** Apache License, Version 2.0. - -## License -Copyright 2021 © Muntashir Al-Islam - -Dual licensed under the terms of [GPL-3.0-or-later](https://www.gnu.org/licenses/gpl-3.0.html) or -[Apache-2.0 license](https://www.apache.org/licenses/LICENSE-2.0.html). Use whatever license you need for your project. - -_Note regarding the Apache-2.0 license, this library has an LGPL dependency which may go against the policy of some -organizations such as ASF._ +libadb-android subset +===================== +This directory contains the small part of libadb-android used by +scrcpy-android. It is based on upstream 3.1.1 at commit +`c849886ebc6d48e7b46d967e78a6bb65c90c3b74` and carries local protocol, +timeout, TLS enforcement, and stream-flow-control fixes. + + +Scope +----- +Only direct TCP connection, TLS pairing, ADB authentication, and byte streams +are retained. The unused connection manager, mDNS discovery, service catalog, +legacy PRNG workaround, sample code, and publishing configuration are omitted. +The application owns endpoint validation and the persistent ADB identity. + + +Local changes +------------- +- Require TLS and reject legacy authentication. +- Validate packet headers, commands, stream IDs, sizes, and negotiated limits. +- Bound TCP connect, protocol waits, stream opens, and connection close. +- Acknowledge one fully consumed WRTE at a time and drain data before CLSE. +- Serialize WRTE with close so no payload follows CLSE. +- Keep the caller-owned keypair alive across routine disconnects. +- Call the pinned public Conscrypt APIs directly. +- Remove Android services and compatibility paths outside the stated scope. + + +Updating +-------- +Vendor updates are manual because the local security changes overlap the +upstream transport. Compare a new upstream tag against this directory, port +only the required files, and reapply the inventory above. The upstream commit +is the comparison point; source comments are not a complete patch ledger. Run +`./scripts/check` and `./test e2e`, then update the tag and commit above. + + +License +------- +See `COPYING` and `LICENSES/`. Individual source files retain their SPDX +identifiers. |