The Certificate Nobody Renewed — Java Bug Hunt
Modelled on the Ericsson outage of 6 December 2018: an expired certificate in Ericsson's SGSN-MME core-network software took mobile data down for millions…
- Language: Java
- Layer: Backend
- Difficulty: Medium
- Concepts: Time, Config, Security
- Modelled on: Ericsson · O2 UK 2018
- Visible tests: a certificate with 100 days left is fine; ten days left is ten days, and due for renewal
- Reward: 50 XP for a complete fix
Briefing
Modelled on the Ericsson outage of 6 December 2018: an expired certificate in Ericsson's SGSN-MME core-network software took mobile data down for millions of customers of O2 in the UK and SoftBank in Japan, among other operators, for most of a day. Ericsson said the cause was an expired certificate in the software versions installed with those customers.
This project is a reconstruction of the safeguard that should have caught it: a renewal check that flags a certificate once it enters its renewal window. CertRenewal.java computes how many days a certificate has left — and the renewal alert never fires.
Fix CertRenewal so the days-to-expiry figure, and everything built on it, follows the spec.
Bug report
BUG-CERT-1206 · Priority: Critical · Reported by: network operations
All times are epoch milliseconds (long).
daysUntilExpiry(now, notAfter)
- whole days between now and notAfter, rounded toward negative infinity: floor((notAfter - now) / CertPolicy.MILLIS_PER_DAY)
- 10 days left -> 10; 29 days 23 hours left -> 29; 1 ms past expiry -> -1
shouldRenew(now, notAfter)
- true when daysUntilExpiry <= CertPolicy.RENEW_WINDOW_DAYS (30), including after expiry
status(now, notAfter)
- "EXPIRED" when daysUntilExpiry < 0
- "RENEW" when 0 <= daysUntilExpiry <= 30
- "OK" otherwise
Observed: a certificate with 10 days left reports 240 days, status "OK"; nobody is paged until the node refuses to start.
Logs
[certwatch] sgsn-mme-07 cert notAfter=2018-12-06T00:00Z days_left=240 status=OK
[certwatch] no renewals due
[sgsn-mme-07] TLS handshake failed: certificate has expiredThe code as shipped
CertRenewal.java (editable)
class CertRenewal {
// Whole days before the certificate expires; negative once it has.
static long daysUntilExpiry(long nowMillis, long notAfterMillis) {
return (notAfterMillis - nowMillis) / CertPolicy.MILLIS_PER_HOUR;
}
static boolean shouldRenew(long nowMillis, long notAfterMillis) {
return daysUntilExpiry(nowMillis, notAfterMillis) <= CertPolicy.RENEW_WINDOW_DAYS;
}
static String status(long nowMillis, long notAfterMillis) {
long days = daysUntilExpiry(nowMillis, notAfterMillis);
if (days < 0) return "EXPIRED";
if (days <= CertPolicy.RENEW_WINDOW_DAYS) return "RENEW";
return "OK";
}
}Read-only context: CertPolicy.java.
Open the hunt to edit the files, run the visible tests and submit against the hidden ones. More Java bug hunts.