public BodyHasher newBodyHasher()

in main/src/main/java/org/apache/james/jdkim/DKIMVerifier.java [232:325]


    public BodyHasher newBodyHasher(Headers messageHeaders) throws FailException {
        List<String> fields = messageHeaders.getFields("DKIM-Signature");
        if (fields == null || fields.isEmpty()) {
            return null;
        }

        // For each DKIM-signature we prepare an hashjob.
        // We calculate all hashes concurrently so to read
        // the inputstream only once.
        Map<String, BodyHasherImpl> bodyHashJobs = new HashMap<String, BodyHasherImpl>();
        Hashtable<String, FailException> signatureExceptions = new Hashtable<String, FailException>();
        for (String signatureField : fields) {
            try {
                int pos = signatureField.indexOf(':');
                if (pos > 0) {
                    String v = signatureField.substring(pos + 1, signatureField
                            .length());
                    SignatureRecord signatureRecord;
                    try {
                        signatureRecord = newSignatureRecord(v);
                        // validate
                        signatureRecord.validate();
                    } catch (IllegalStateException e) {
                        throw new PermFailException("Invalid signature record: " + e.getMessage(), e);
                    }

                    // Specification say we MAY refuse to verify the signature.
                    if (signatureRecord.getSignatureTimestamp() != null) {
                        long signedTime = signatureRecord.getSignatureTimestamp();
                        long elapsed = (System.currentTimeMillis() / 1000 - signedTime);
                        if (elapsed < -3600 * 24 * 365 * 3) {
                            throw new PermFailException("Signature date is more than "
                                    + -elapsed / (3600 * 24 * 365) + " years in the future.");
                        } else if (elapsed < -3600 * 24 * 30 * 3) {
                            throw new PermFailException("Signature date is more than "
                                    + -elapsed / (3600 * 24 * 30) + " months in the future.");
                        } else if (elapsed < -3600 * 24 * 3) {
                            throw new PermFailException("Signature date is more than "
                                    + -elapsed / (3600 * 24) + " days in the future.");
                        } else if (elapsed < -3600 * 3) {
                            throw new PermFailException("Signature date is more than "
                                    + -elapsed / 3600 + " hours in the future.");
                        } else if (elapsed < -60 * 3) {
                            throw new PermFailException("Signature date is more than "
                                    + -elapsed / 60 + " minutes in the future.");
                        } else if (elapsed < 0) {
                            throw new PermFailException("Signature date is "
                                    + elapsed + " seconds in the future.");
                        }
                    }

                    // TODO here we could check more parameters for
                    // validation before running a network operation like the
                    // dns lookup.
                    // e.g: the canonicalization method could be checked now.
                    PublicKeyRecord publicKeyRecord = publicRecordLookup(signatureRecord);

                    List<CharSequence> signedHeadersList = signatureRecord.getHeaders();

                    byte[] decoded = signatureRecord.getSignature();
                    signatureVerify(messageHeaders, signatureRecord, decoded,
                            publicKeyRecord, signedHeadersList);

                    // we track all canonicalizations+limit+bodyHash we
                    // see so to be able to check all of them in a single
                    // stream run.
                    BodyHasherImpl bhj = newBodyHasher(signatureRecord);

                    bodyHashJobs.put(signatureField, bhj);

                } else {
                    throw new PermFailException(
                            "unexpected bad signature field");
                }
            } catch (TempFailException e) {
                signatureExceptions.put(signatureField, e);
            } catch (PermFailException e) {
                signatureExceptions.put(signatureField, e);
            } catch (RuntimeException e) {
                signatureExceptions.put(signatureField, new PermFailException(
                        "Unexpected exception processing signature", e));
            }
        }

        if (bodyHashJobs.isEmpty()) {
            if (signatureExceptions.size() > 0) {
                throw prepareException(signatureExceptions);
            } else {
                throw new PermFailException("Unexpected condition with " + fields);
            }
        }

        return new CompoundBodyHasher(bodyHashJobs, signatureExceptions);
    }