"use strict";
/**
 * OCSP (Online Certificate Status Protocol) verification
 */
Object.defineProperty(exports, "__esModule", { value: true });
exports.verifyOCSP = verifyOCSP;
exports.performOCSPCheck = performOCSPCheck;
// Apply PKI.js Ed25519 patch before importing easy-ocsp
require("./pkijs-ed25519-patch.js");
const easy_ocsp_1 = require("easy-ocsp");
const logger_ts_1 = require("../../utility/logging/logger.js");
const verificationUtils_ts_1 = require("./verificationUtils.js");
const logger = (0, logger_ts_1.loggerWithTag)('ocsp-verification');
// Import the shared source
const certificateVerificationSource_ts_1 = require("./certificateVerificationSource.js");
// Lazy-load the certificate verification cache table
let certCacheTable;
function getCertificateCacheTable() {
    if (!certCacheTable) {
        certCacheTable = (0, verificationUtils_ts_1.getCertificateCacheTable)();
        // Configure the caching source using the shared CertificateVerificationSource class
        certCacheTable.sourcedFrom(certificateVerificationSource_ts_1.CertificateVerificationSource);
    }
    return certCacheTable;
}
/**
 * Verify OCSP status of a client certificate
 * @param certPem - Client certificate as Buffer (DER format)
 * @param issuerPem - Issuer (CA) certificate as Buffer (DER format)
 * @param config - OCSP configuration
 * @param ocspUrls - Optional pre-extracted OCSP responder URLs (avoids re-parsing)
 * @returns Promise resolving to verification result
 */
async function verifyOCSP(certPem, issuerPem, config, ocspUrls) {
    // Check if OCSP verification is disabled
    if (config?.enabled === false) {
        return { valid: true, status: 'disabled', method: 'disabled' };
    }
    try {
        // Convert DER buffers to PEM strings for certificate parsing libraries
        // PKI.js and easy-ocsp expect PEM format for extension extraction and OCSP requests
        const certPemStr = (0, verificationUtils_ts_1.bufferToPem)(certPem, 'CERTIFICATE');
        const issuerPemStr = (0, verificationUtils_ts_1.bufferToPem)(issuerPem, 'CERTIFICATE');
        // Create a cache key that includes all verification parameters
        const cacheKey = (0, verificationUtils_ts_1.createCacheKey)(certPemStr, issuerPemStr, 'ocsp');
        // Get the cache table - Harper will automatically handle
        // concurrent requests and cache stampede prevention
        // Pass certificate data as context - Harper will make it available as requestContext in the source
        const cacheEntry = await getCertificateCacheTable().get(cacheKey, {
            certPem: certPemStr,
            issuerPem: issuerPemStr,
            ocspUrls,
            config: { ocsp: config ?? {} },
        });
        if (!cacheEntry) {
            // This should not happen if the source is configured correctly
            // but handle it gracefully
            if (config.failureMode === 'fail-closed') {
                return { valid: false, status: 'error', error: 'Cache fetch failed', method: 'ocsp' };
            }
            logger.warn?.('OCSP cache fetch failed, allowing connection (fail-open mode)');
            return { valid: true, status: 'error-allowed', method: 'ocsp' };
        }
        const cached = cacheEntry;
        const wasLoadedFromSource = cacheEntry.wasLoadedFromSource?.();
        logger.trace?.(`OCSP ${wasLoadedFromSource ? 'source fetch' : 'cache hit'} for certificate`);
        return {
            valid: cached.status === 'good',
            status: cached.status,
            cached: !wasLoadedFromSource,
            method: cached.method || 'ocsp',
        };
    }
    catch (error) {
        logger.error?.(`OCSP verification error:`, error);
        // Check failure mode
        if (config.failureMode === 'fail-closed') {
            return { valid: false, status: 'error', error: error.message, method: 'ocsp' };
        }
        // Fail open - allow connection on OCSP errors
        logger.warn?.('OCSP check failed, allowing connection (fail-open mode)');
        return { valid: true, status: 'error-allowed', method: 'ocsp' };
    }
}
/**
 * Perform the actual OCSP check using easy-ocsp
 * @param certPem - Certificate in PEM format
 * @param issuerPem - Issuer certificate in PEM format
 * @param config - OCSP configuration
 * @param ocspUrls - Optional pre-extracted OCSP responder URLs (avoids re-parsing)
 * @returns OCSP check result
 */
async function performOCSPCheck(certPem, issuerPem, config, ocspUrls) {
    try {
        const response = await (0, easy_ocsp_1.getCertStatus)(certPem, {
            ca: issuerPem,
            timeout: config.timeout,
            ...(ocspUrls?.length && { ocspUrl: ocspUrls[0] }),
        });
        // Map response status to internal format
        switch (response.status) {
            case 'good':
                return { status: 'good' };
            case 'revoked':
                return { status: 'revoked', reason: response.revocationReason?.toString() || 'unspecified' };
            default:
                return { status: 'unknown', reason: 'unknown-status' };
        }
    }
    catch (error) {
        const err = error;
        // Return appropriate error based on type
        const reason = err.name === 'AbortError' ? 'timeout' : 'ocsp-error';
        return { status: 'unknown', reason };
    }
}
//# sourceMappingURL=ocspVerification.js.map