fn download_current_revocations()

in cert-storage-inspector/src/main.rs [197:274]


fn download_current_revocations(onecrl_url: &str) -> Result<BTreeSet<Revocation>, SimpleError> {
    let mut easy = Easy::new();
    easy.url(onecrl_url)?;
    let mut data = Vec::new();
    {
        let mut transfer = easy.transfer();
        transfer.write_function(|new_data| {
            data.extend_from_slice(new_data);
            Ok(new_data.len())
        })?;
        transfer.perform()?;
    }
    let records: JsonValue = serde_json::from_slice(&data)?;
    let records = records
        .as_object()
        .ok_or(SimpleError::from("unexpected type"))?;
    let data = records
        .get("data")
        .ok_or(SimpleError::from("missing data key"))?;
    let data = data
        .as_array()
        .ok_or(SimpleError::from("unexpected type"))?;
    let mut revocations: BTreeSet<Revocation> = BTreeSet::new();
    for entry in data {
        let entry = entry
            .as_object()
            .ok_or(SimpleError::from("unexpected type"))?;
        let revocation = if entry.contains_key("issuerName") && entry.contains_key("serialNumber") {
            let issuer = entry
                .get("issuerName")
                .ok_or(SimpleError::from("couldn't get issuerName"))?;
            let issuer = issuer
                .as_str()
                .ok_or(SimpleError::from("issuerName not a string"))?;
            let serial = entry
                .get("serialNumber")
                .ok_or(SimpleError::from("couldn't get serialNumber"))?;
            let serial = serial
                .as_str()
                .ok_or(SimpleError::from("serialNumber not a string"))?;
            Revocation {
                typ: RevocationType::IssuerSerial,
                field1: issuer.to_owned(),
                field2: serial.to_owned(),
            }
        } else if entry.contains_key("subject") && entry.contains_key("pubKeyHash") {
            // TODO: I'm not actually sure about these field names, because there aren't any
            // examples of them in the current data set.
            let subject = entry
                .get("subject")
                .ok_or(SimpleError::from("couldn't get subject"))?;
            let subject = subject
                .as_str()
                .ok_or(SimpleError::from("subject not a string"))?;
            let pub_key_hash = entry
                .get("pubKeyHash")
                .ok_or(SimpleError::from("couldn't get pubKeyHash"))?;
            let pub_key_hash = pub_key_hash
                .as_str()
                .ok_or(SimpleError::from("pubKeyHash not a string"))?;
            Revocation {
                typ: RevocationType::SubjectPublicKey,
                field1: subject.to_owned(),
                field2: pub_key_hash.to_owned(),
            }
        } else {
            eprintln!("entry with no issuer/serial or no subject/pubKeyHash");
            continue;
        };
        if revocations.contains(&revocation) {
  // Commenting this out, because the duplicate entry information is not typically used.
  //          eprintln!("duplicate entry in OneCRL? ({:?})", revocation);
        } else {
            revocations.insert(revocation);
        }
    }
    Ok(revocations)
}