Skip to content

Commit

Permalink
Check for apex cert when deciding if ADB cert reinstall is required
Browse files Browse the repository at this point in the history
Aiming to avoid issues where upgrades/remounts/other weirdness results
in a broken setup (no APEX cert even though it's used) because the
/system cert hides the issue.
  • Loading branch information
pimterry committed Apr 9, 2024
1 parent fb5cb5b commit f05c380
Showing 1 changed file with 58 additions and 11 deletions.
69 changes: 58 additions & 11 deletions src/interceptors/android/adb-commands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -234,26 +234,69 @@ export async function getRootCommand(adbClient: Adb.DeviceClient): Promise<RootC
export async function hasCertInstalled(
adbClient: Adb.DeviceClient,
certHash: string,
certFingerprint: string
expectedFingerprint: string
) {
try {
const certPath = `/system/etc/security/cacerts/${certHash}.0`;
const certStream = await adbClient.pull(certPath);
// We have to check both of these paths. If /system exists but /apex does not, then something
// has gone wrong and we need to reinstall the cert to fix it.
const systemCertPath = `/system/etc/security/cacerts/${certHash}.0`;
const apexCertPath = `/apex/com.android.conscrypt/cacerts/${certHash}.0`;

// Wait until it's clear that the read is successful
const data = await streamToBuffer(certStream);
try {
const existingCertChecks = await Promise.all([
adbClient.pull(systemCertPath)
.then(async (certStream) => {
if (await isMatchingCert(certStream, expectedFingerprint)) {
console.log('Matching /system cacert exists');
return true;
} else {
console.log('/system cacert exists but mismatched');
return false;
}
}),

run(adbClient, ['ls', '/apex/com.android.conscrypt'])
.then(async (lsOutput) => {
if (lsOutput.includes('cacerts')) {
const certStream = await adbClient.pull(apexCertPath);
if (await isMatchingCert(certStream, expectedFingerprint)) {
console.log('Matching /apex cacert exists');
return true;
} else {
console.log('/apex cacert exists but mismatched');
return false;
}
} else {
console.log('No need for /apex cacerts injection');
// If apex dir doesn't exist, we don't need to inject anything
return true;
}
})
]);

// The device already has an HTTP Toolkit cert. But is it the right one?
const existingCert = parseCert(data.toString('utf8'));
const existingFingerprint = getCertificateFingerprint(existingCert);
return certFingerprint === existingFingerprint;
} catch (e) {
return existingCertChecks.every(result => result === true);
} catch (e: any) {
// Couldn't read the cert, or some other error - either way, we probably
// don't have a working system cert installed.
console.log(`Couldn't detect cert via ADB: ${e.message}`);
return false;
}
}

// The device already has an HTTP Toolkit cert. But is it the right one?
const isMatchingCert = async (certStream: stream.Readable, expectedFingerprint: string) => {
// Wait until it's clear that the read is successful
const data = await streamToBuffer(certStream);

// Note that due to https://github.com/DeviceFarmer/adbkit/issues/464 we may see
// 'empty' data for files that are actually missing entirely.
if (data.byteLength === 0) return false;

const certData = data.toString('utf8');
const existingCert = parseCert(certData);
const existingFingerprint = getCertificateFingerprint(existingCert);
return expectedFingerprint === existingFingerprint;
}

export async function injectSystemCertificate(
adbClient: Adb.DeviceClient,
runAsRoot: RootCmd,
Expand Down Expand Up @@ -306,6 +349,10 @@ export async function injectSystemCertificate(
# this globally as APEX mounts are namespaced per process, so we need to inject a
# bind mount for this directory into every mount namespace.
# First we mount for the shell itself, for completeness and so we can see this
# when we check for correct installation on later runs
mount --bind /system/etc/security/cacerts /apex/com.android.conscrypt/cacerts
# First we get the Zygote process(es), which launch each app
ZYGOTE_PID=$(pidof zygote || true)
ZYGOTE64_PID=$(pidof zygote64 || true)
Expand Down

0 comments on commit f05c380

Please sign in to comment.