Search in sources :

Example 66 with OperationException

use of org.xipki.ca.api.OperationException in project xipki by xipki.

the class CertStoreQueryExecutor method addCert.

// constructor
void addCert(NameId ca, X509CertWithDbId certificate, byte[] encodedSubjectPublicKey, NameId certProfile, NameId requestor, Integer userId, RequestType reqType, byte[] transactionId, X500Name reqSubject) throws DataAccessException, OperationException {
    ParamUtil.requireNonNull("ca", ca);
    ParamUtil.requireNonNull("certificate", certificate);
    ParamUtil.requireNonNull("certProfile", certProfile);
    ParamUtil.requireNonNull("requestor", requestor);
    long certId = idGenerator.nextId();
    X509Certificate cert = certificate.getCert();
    long fpPk = FpIdCalculator.hash(encodedSubjectPublicKey);
    String subjectText = X509Util.cutText(certificate.getSubject(), maxX500nameLen);
    long fpSubject = X509Util.fpCanonicalizedName(cert.getSubjectX500Principal());
    String reqSubjectText = null;
    Long fpReqSubject = null;
    if (reqSubject != null) {
        fpReqSubject = X509Util.fpCanonicalizedName(reqSubject);
        if (fpSubject == fpReqSubject) {
            fpReqSubject = null;
        } else {
            reqSubjectText = X509Util.cutX500Name(CaUtil.sortX509Name(reqSubject), maxX500nameLen);
        }
    }
    String b64FpCert = base64Fp(certificate.getEncodedCert());
    String b64Cert = Base64.encodeToString(certificate.getEncodedCert());
    String tid = (transactionId == null) ? null : Base64.encodeToString(transactionId);
    long currentTimeSeconds = System.currentTimeMillis() / 1000;
    BigInteger serialNumber = cert.getSerialNumber();
    long notBeforeSeconds = cert.getNotBefore().getTime() / 1000;
    long notAfterSeconds = cert.getNotAfter().getTime() / 1000;
    Connection conn = null;
    PreparedStatement[] pss = borrowPreparedStatements(SQLs.SQL_ADD_CERT, SQLs.SQL_ADD_CRAW);
    try {
        PreparedStatement psAddcert = pss[0];
        // all statements have the same connection
        conn = psAddcert.getConnection();
        // cert
        int idx = 2;
        psAddcert.setInt(idx++, CertArt.X509PKC.getCode());
        psAddcert.setLong(idx++, currentTimeSeconds);
        psAddcert.setString(idx++, serialNumber.toString(16));
        psAddcert.setString(idx++, subjectText);
        psAddcert.setLong(idx++, fpSubject);
        setLong(psAddcert, idx++, fpReqSubject);
        psAddcert.setLong(idx++, notBeforeSeconds);
        psAddcert.setLong(idx++, notAfterSeconds);
        setBoolean(psAddcert, idx++, false);
        psAddcert.setInt(idx++, certProfile.getId());
        psAddcert.setInt(idx++, ca.getId());
        setInt(psAddcert, idx++, requestor.getId());
        setInt(psAddcert, idx++, userId);
        psAddcert.setLong(idx++, fpPk);
        boolean isEeCert = cert.getBasicConstraints() == -1;
        psAddcert.setInt(idx++, isEeCert ? 1 : 0);
        psAddcert.setInt(idx++, reqType.getCode());
        psAddcert.setString(idx++, tid);
        // rawcert
        PreparedStatement psAddRawcert = pss[1];
        idx = 2;
        psAddRawcert.setString(idx++, b64FpCert);
        psAddRawcert.setString(idx++, reqSubjectText);
        psAddRawcert.setString(idx++, b64Cert);
        certificate.setCertId(certId);
        psAddcert.setLong(1, certId);
        psAddRawcert.setLong(1, certId);
        final boolean origAutoCommit = conn.getAutoCommit();
        conn.setAutoCommit(false);
        String sql = null;
        try {
            sql = SQLs.SQL_ADD_CERT;
            psAddcert.executeUpdate();
            sql = SQLs.SQL_ADD_CRAW;
            psAddRawcert.executeUpdate();
            sql = "(commit add cert to CA certstore)";
            conn.commit();
        } catch (Throwable th) {
            conn.rollback();
            // more secure
            datasource.deleteFromTable(null, "CRAW", "CID", certId);
            datasource.deleteFromTable(null, "CERT", "ID", certId);
            if (th instanceof SQLException) {
                LOG.error("datasource {} could not add certificate with id {}: {}", datasource.getName(), certId, th.getMessage());
                throw datasource.translate(sql, (SQLException) th);
            } else {
                throw new OperationException(ErrorCode.SYSTEM_FAILURE, th);
            }
        } finally {
            conn.setAutoCommit(origAutoCommit);
        }
    } catch (SQLException ex) {
        throw datasource.translate(null, ex);
    } finally {
        try {
            for (PreparedStatement ps : pss) {
                releaseStatement(ps);
            }
        } finally {
            if (conn != null) {
                datasource.returnConnection(conn);
            }
        }
    }
}
Also used : SQLException(java.sql.SQLException) Connection(java.sql.Connection) PreparedStatement(java.sql.PreparedStatement) DERPrintableString(org.bouncycastle.asn1.DERPrintableString) DEROctetString(org.bouncycastle.asn1.DEROctetString) X509Certificate(java.security.cert.X509Certificate) BigInteger(java.math.BigInteger) OperationException(org.xipki.ca.api.OperationException)

Example 67 with OperationException

use of org.xipki.ca.api.OperationException in project xipki by xipki.

the class CertStoreQueryExecutor method getCertForId.

// method getCertForId
X509CertWithDbId getCertForId(long certId) throws DataAccessException, OperationException {
    final String sql = sqls.sqlRawCertForId;
    String b64Cert;
    ResultSet rs = null;
    PreparedStatement ps = borrowPreparedStatement(sql);
    try {
        ps.setLong(1, certId);
        rs = ps.executeQuery();
        if (!rs.next()) {
            return null;
        }
        b64Cert = rs.getString("CERT");
    } catch (SQLException ex) {
        throw datasource.translate(sql, ex);
    } finally {
        releaseDbResources(ps, rs);
    }
    if (b64Cert == null) {
        return null;
    }
    byte[] encodedCert = Base64.decodeFast(b64Cert);
    X509Certificate cert;
    try {
        cert = X509Util.parseCert(encodedCert);
    } catch (CertificateException ex) {
        throw new OperationException(ErrorCode.SYSTEM_FAILURE, ex);
    }
    return new X509CertWithDbId(cert, encodedCert);
}
Also used : SQLException(java.sql.SQLException) ResultSet(java.sql.ResultSet) PreparedStatement(java.sql.PreparedStatement) CertificateException(java.security.cert.CertificateException) X509CertWithDbId(org.xipki.ca.api.X509CertWithDbId) DERPrintableString(org.bouncycastle.asn1.DERPrintableString) DEROctetString(org.bouncycastle.asn1.DEROctetString) X509Certificate(java.security.cert.X509Certificate) OperationException(org.xipki.ca.api.OperationException)

Example 68 with OperationException

use of org.xipki.ca.api.OperationException in project xipki by xipki.

the class CertStoreQueryExecutor method getCertificateInfo.

// method getCertWithRevocationInfo
X509CertificateInfo getCertificateInfo(NameId ca, X509Cert caCert, BigInteger serial, CaIdNameMap idNameMap) throws DataAccessException, OperationException, CertificateException {
    ParamUtil.requireNonNull("ca", ca);
    ParamUtil.requireNonNull("caCert", caCert);
    ParamUtil.requireNonNull("idNameMap", idNameMap);
    ParamUtil.requireNonNull("serial", serial);
    final String sql = sqls.sqlCertInfo;
    String b64Cert;
    boolean revoked;
    int revReason = 0;
    long revTime = 0;
    long revInvTime = 0;
    int certprofileId;
    int requestorId;
    ResultSet rs = null;
    PreparedStatement ps = borrowPreparedStatement(sql);
    try {
        int idx = 1;
        ps.setInt(idx++, ca.getId());
        ps.setString(idx++, serial.toString(16));
        rs = ps.executeQuery();
        if (!rs.next()) {
            return null;
        }
        b64Cert = rs.getString("CERT");
        certprofileId = rs.getInt("PID");
        requestorId = rs.getInt("RID");
        revoked = rs.getBoolean("REV");
        if (revoked) {
            revReason = rs.getInt("RR");
            revTime = rs.getLong("RT");
            revInvTime = rs.getLong("RIT");
        }
    } catch (SQLException ex) {
        throw datasource.translate(sql, ex);
    } finally {
        releaseDbResources(ps, rs);
    }
    try {
        byte[] encodedCert = Base64.decodeFast(b64Cert);
        X509Certificate cert = X509Util.parseCert(encodedCert);
        X509CertWithDbId certWithMeta = new X509CertWithDbId(cert, encodedCert);
        byte[] subjectPublicKeyInfo = Certificate.getInstance(encodedCert).getTBSCertificate().getSubjectPublicKeyInfo().getEncoded();
        X509CertificateInfo certInfo = new X509CertificateInfo(certWithMeta, ca, caCert, subjectPublicKeyInfo, idNameMap.getCertprofile(certprofileId), idNameMap.getRequestor(requestorId));
        if (!revoked) {
            return certInfo;
        }
        Date invalidityTime = (revInvTime == 0) ? null : new Date(revInvTime * 1000);
        CertRevocationInfo revInfo = new CertRevocationInfo(revReason, new Date(revTime * 1000), invalidityTime);
        certInfo.setRevocationInfo(revInfo);
        return certInfo;
    } catch (IOException ex) {
        LOG.warn("getCertificateInfo()", ex);
        throw new OperationException(ErrorCode.SYSTEM_FAILURE, ex);
    }
}
Also used : SQLException(java.sql.SQLException) PreparedStatement(java.sql.PreparedStatement) X509CertWithDbId(org.xipki.ca.api.X509CertWithDbId) X509CertificateInfo(org.xipki.ca.api.publisher.x509.X509CertificateInfo) DERPrintableString(org.bouncycastle.asn1.DERPrintableString) DEROctetString(org.bouncycastle.asn1.DEROctetString) IOException(java.io.IOException) X509Certificate(java.security.cert.X509Certificate) Date(java.util.Date) CertRevocationInfo(org.xipki.security.CertRevocationInfo) ResultSet(java.sql.ResultSet) OperationException(org.xipki.ca.api.OperationException)

Example 69 with OperationException

use of org.xipki.ca.api.OperationException in project xipki by xipki.

the class CertStoreQueryExecutor method unrevokeCert.

// method revokeSuspendedCert
X509CertWithDbId unrevokeCert(NameId ca, BigInteger serialNumber, boolean force, boolean publishToDeltaCrlCache, CaIdNameMap idNamMap) throws OperationException, DataAccessException {
    ParamUtil.requireNonNull("ca", ca);
    ParamUtil.requireNonNull("serialNumber", serialNumber);
    X509CertWithRevocationInfo certWithRevInfo = getCertWithRevocationInfo(ca, serialNumber, idNamMap);
    if (certWithRevInfo == null) {
        LOG.warn("certificate with CA={} and serialNumber={} does not exist", ca.getName(), LogUtil.formatCsn(serialNumber));
        return null;
    }
    CertRevocationInfo currentRevInfo = certWithRevInfo.getRevInfo();
    if (currentRevInfo == null) {
        throw new OperationException(ErrorCode.CERT_UNREVOKED, "certificate is not revoked");
    }
    CrlReason currentReason = currentRevInfo.getReason();
    if (!force) {
        if (currentReason != CrlReason.CERTIFICATE_HOLD) {
            throw new OperationException(ErrorCode.NOT_PERMITTED, "could not unrevoke certificate revoked with reason " + currentReason.getDescription());
        }
    }
    final String sql = "UPDATE CERT SET LUPDATE=?,REV=?,RT=?,RIT=?,RR=? WHERE ID=?";
    long certId = certWithRevInfo.getCert().getCertId().longValue();
    long currentTimeSeconds = System.currentTimeMillis() / 1000;
    PreparedStatement ps = borrowPreparedStatement(sql);
    try {
        int idx = 1;
        ps.setLong(idx++, currentTimeSeconds);
        setBoolean(ps, idx++, false);
        ps.setNull(idx++, Types.INTEGER);
        ps.setNull(idx++, Types.INTEGER);
        ps.setNull(idx++, Types.INTEGER);
        ps.setLong(idx++, certId);
        int count = ps.executeUpdate();
        if (count != 1) {
            String message = (count > 1) ? count + " rows modified, but exactly one is expected" : "no row is modified, but exactly one is expected";
            throw new OperationException(ErrorCode.SYSTEM_FAILURE, message);
        }
    } catch (SQLException ex) {
        throw datasource.translate(sql, ex);
    } finally {
        releaseDbResources(ps, null);
    }
    if (publishToDeltaCrlCache) {
        publishToDeltaCrlCache(ca, certWithRevInfo.getCert().getCert().getSerialNumber());
    }
    return certWithRevInfo.getCert();
}
Also used : CertRevocationInfo(org.xipki.security.CertRevocationInfo) SQLException(java.sql.SQLException) PreparedStatement(java.sql.PreparedStatement) CrlReason(org.xipki.security.CrlReason) DERPrintableString(org.bouncycastle.asn1.DERPrintableString) DEROctetString(org.bouncycastle.asn1.DEROctetString) OperationException(org.xipki.ca.api.OperationException)

Example 70 with OperationException

use of org.xipki.ca.api.OperationException in project xipki by xipki.

the class HttpScepServlet method service.

@Override
public FullHttpResponse service(FullHttpRequest request, ServletURI servletUri, SSLSession sslSession, SslReverseProxyMode sslReverseProxyMode) throws Exception {
    HttpVersion version = request.protocolVersion();
    HttpMethod method = request.method();
    boolean viaPost;
    if (method == HttpMethod.POST) {
        viaPost = true;
    } else if (method == HttpMethod.GET) {
        viaPost = false;
    } else {
        return createErrorResponse(version, HttpResponseStatus.METHOD_NOT_ALLOWED);
    }
    String scepName = null;
    String certProfileName = null;
    if (servletUri.getPath().length() > 1) {
        String scepPath = servletUri.getPath();
        if (scepPath.endsWith(CGI_PROGRAM)) {
            // skip also the first char (which is always '/')
            String path = scepPath.substring(1, scepPath.length() - CGI_PROGRAM_LEN);
            String[] tokens = path.split("/");
            if (tokens.length == 2) {
                scepName = tokens[0];
                certProfileName = tokens[1].toLowerCase();
            }
        }
    // end if
    }
    if (scepName == null || certProfileName == null) {
        return createErrorResponse(version, HttpResponseStatus.NOT_FOUND);
    }
    AuditService auditService = auditServiceRegister.getAuditService();
    AuditEvent event = new AuditEvent(new Date());
    event.setApplicationName("SCEP");
    event.setName(CaAuditConstants.NAME_PERF);
    event.addEventData(CaAuditConstants.NAME_SCEP_name, scepName + "/" + certProfileName);
    event.addEventData(CaAuditConstants.NAME_reqType, RequestType.SCEP.name());
    String msgId = RandomUtil.nextHexLong();
    event.addEventData(CaAuditConstants.NAME_mid, msgId);
    AuditLevel auditLevel = AuditLevel.INFO;
    AuditStatus auditStatus = AuditStatus.SUCCESSFUL;
    String auditMessage = null;
    try {
        if (responderManager == null) {
            auditMessage = "responderManager in servlet not configured";
            LOG.error(auditMessage);
            auditLevel = AuditLevel.ERROR;
            auditStatus = AuditStatus.FAILED;
            return createErrorResponse(version, HttpResponseStatus.INTERNAL_SERVER_ERROR);
        }
        Scep responder = responderManager.getScep(scepName);
        if (responder == null || !responder.isOnService() || !responder.supportsCertProfile(certProfileName)) {
            auditMessage = "unknown SCEP '" + scepName + "/" + certProfileName + "'";
            LOG.warn(auditMessage);
            auditStatus = AuditStatus.FAILED;
            return createErrorResponse(version, HttpResponseStatus.NOT_FOUND);
        }
        String operation = servletUri.getParameter("operation");
        event.addEventData(CaAuditConstants.NAME_SCEP_operation, operation);
        if ("PKIOperation".equalsIgnoreCase(operation)) {
            CMSSignedData reqMessage;
            // parse the request
            try {
                byte[] content;
                if (viaPost) {
                    content = readContent(request);
                } else {
                    String b64 = servletUri.getParameter("message");
                    content = Base64.decode(b64);
                }
                reqMessage = new CMSSignedData(content);
            } catch (Exception ex) {
                final String msg = "invalid request";
                LogUtil.error(LOG, ex, msg);
                auditMessage = msg;
                auditStatus = AuditStatus.FAILED;
                return createErrorResponse(version, HttpResponseStatus.BAD_REQUEST);
            }
            ContentInfo ci;
            try {
                ci = responder.servicePkiOperation(reqMessage, certProfileName, msgId, event);
            } catch (MessageDecodingException ex) {
                final String msg = "could not decrypt and/or verify the request";
                LogUtil.error(LOG, ex, msg);
                auditMessage = msg;
                auditStatus = AuditStatus.FAILED;
                return createErrorResponse(version, HttpResponseStatus.BAD_REQUEST);
            } catch (OperationException ex) {
                ErrorCode code = ex.getErrorCode();
                HttpResponseStatus httpCode;
                switch(code) {
                    case ALREADY_ISSUED:
                    case CERT_REVOKED:
                    case CERT_UNREVOKED:
                        httpCode = HttpResponseStatus.FORBIDDEN;
                        break;
                    case BAD_CERT_TEMPLATE:
                    case BAD_REQUEST:
                    case BAD_POP:
                    case INVALID_EXTENSION:
                    case UNKNOWN_CERT:
                    case UNKNOWN_CERT_PROFILE:
                        httpCode = HttpResponseStatus.BAD_REQUEST;
                        break;
                    case NOT_PERMITTED:
                        httpCode = HttpResponseStatus.UNAUTHORIZED;
                        break;
                    case SYSTEM_UNAVAILABLE:
                        httpCode = HttpResponseStatus.SERVICE_UNAVAILABLE;
                        break;
                    case CRL_FAILURE:
                    case DATABASE_FAILURE:
                    case SYSTEM_FAILURE:
                        httpCode = HttpResponseStatus.INTERNAL_SERVER_ERROR;
                        break;
                    default:
                        httpCode = HttpResponseStatus.INTERNAL_SERVER_ERROR;
                        break;
                }
                auditMessage = ex.getMessage();
                LogUtil.error(LOG, ex, auditMessage);
                auditStatus = AuditStatus.FAILED;
                return createErrorResponse(version, httpCode);
            }
            byte[] bodyBytes = ci.getEncoded();
            return createOKResponse(version, CT_RESPONSE, bodyBytes);
        } else if (Operation.GetCACaps.getCode().equalsIgnoreCase(operation)) {
            // CA-Ident is ignored
            byte[] caCapsBytes = responder.getCaCaps().getBytes();
            return createOKResponse(version, ScepConstants.CT_TEXT_PLAIN, caCapsBytes);
        } else if (Operation.GetCACert.getCode().equalsIgnoreCase(operation)) {
            // CA-Ident is ignored
            byte[] respBytes = responder.getCaCertResp().getBytes();
            return createOKResponse(version, ScepConstants.CT_X509_CA_RA_CERT, respBytes);
        } else if (Operation.GetNextCACert.getCode().equalsIgnoreCase(operation)) {
            auditMessage = "SCEP operation '" + operation + "' is not permitted";
            auditStatus = AuditStatus.FAILED;
            return createErrorResponse(version, HttpResponseStatus.FORBIDDEN);
        } else {
            auditMessage = "unknown SCEP operation '" + operation + "'";
            auditStatus = AuditStatus.FAILED;
            return createErrorResponse(version, HttpResponseStatus.BAD_REQUEST);
        }
    } catch (Throwable th) {
        if (th instanceof EOFException) {
            final String msg = "connection reset by peer";
            if (LOG.isWarnEnabled()) {
                LogUtil.warn(LOG, th, msg);
            }
            LOG.debug(msg, th);
        } else {
            LOG.error("Throwable thrown, this should not happen!", th);
        }
        auditLevel = AuditLevel.ERROR;
        auditStatus = AuditStatus.FAILED;
        auditMessage = "internal error";
        return createErrorResponse(version, HttpResponseStatus.INTERNAL_SERVER_ERROR);
    } finally {
        audit(auditService, event, auditLevel, auditStatus, auditMessage);
    }
}
Also used : HttpResponseStatus(io.netty.handler.codec.http.HttpResponseStatus) AuditLevel(org.xipki.audit.AuditLevel) CMSSignedData(org.bouncycastle.cms.CMSSignedData) Date(java.util.Date) MessageDecodingException(org.xipki.scep.exception.MessageDecodingException) IOException(java.io.IOException) EOFException(java.io.EOFException) OperationException(org.xipki.ca.api.OperationException) AuditStatus(org.xipki.audit.AuditStatus) MessageDecodingException(org.xipki.scep.exception.MessageDecodingException) ContentInfo(org.bouncycastle.asn1.cms.ContentInfo) EOFException(java.io.EOFException) AuditEvent(org.xipki.audit.AuditEvent) ErrorCode(org.xipki.ca.api.OperationException.ErrorCode) Scep(org.xipki.ca.server.api.Scep) HttpVersion(io.netty.handler.codec.http.HttpVersion) AuditService(org.xipki.audit.AuditService) HttpMethod(io.netty.handler.codec.http.HttpMethod) OperationException(org.xipki.ca.api.OperationException)

Aggregations

OperationException (org.xipki.ca.api.OperationException)70 DERPrintableString (org.bouncycastle.asn1.DERPrintableString)20 CaMgmtException (org.xipki.ca.server.mgmt.api.CaMgmtException)19 Date (java.util.Date)16 BigInteger (java.math.BigInteger)15 X509Certificate (java.security.cert.X509Certificate)15 CertificateException (java.security.cert.CertificateException)13 DERUTF8String (org.bouncycastle.asn1.DERUTF8String)13 X509Ca (org.xipki.ca.server.impl.X509Ca)13 PreparedStatement (java.sql.PreparedStatement)12 SQLException (java.sql.SQLException)12 IOException (java.io.IOException)11 X509CertificateInfo (org.xipki.ca.api.publisher.x509.X509CertificateInfo)11 DEROctetString (org.bouncycastle.asn1.DEROctetString)10 X500Name (org.bouncycastle.asn1.x500.X500Name)10 CRLDistPoint (org.bouncycastle.asn1.x509.CRLDistPoint)10 IssuingDistributionPoint (org.bouncycastle.asn1.x509.IssuingDistributionPoint)10 CrlReason (org.xipki.security.CrlReason)10 AuditEvent (org.xipki.audit.AuditEvent)9 NameId (org.xipki.ca.api.NameId)9