/* Copyright (C) 2003 Frédéric Giudicelli (contact_nos@yahoo.com). All rights reserved. This product includes cryptographic software written by Eric Young (eay@cryptsoft.com) This program is released under the GPL with the additional exemption that compiling, linking, and/or using OpenSSL is allowed. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ // Entity_PUBLICATION.cpp: implementation of the Entity_PUBLICATION class. // ////////////////////////////////////////////////////////////////////// #include "Entity_PUBLICATION.h" #include "svintl.h" ////////////////////////////////////////////////////////////////////// // Construction/Destruction ////////////////////////////////////////////////////////////////////// Entity_PUBLICATION::Entity_PUBLICATION(ENTITY_CONSTRUCTOR_PARAMETERS): Entity(ENTITY_CONSTRUCTOR_PARAM_PASSTHRU, &myConf, &PublicationStore), PublicationStore(EntityName, e) { m_OcspServersHandler = NULL; } Entity_PUBLICATION::~Entity_PUBLICATION() { m_Jobs.StopAll(); UnloadAllPub(); } bool Entity_PUBLICATION::Create(const EntityCreationDatas & Params, AdminResponseBody & response) { if(!Params) { NEWPKIerr(PKI_ERROR_TXT, ERROR_BAD_PARAM); return false; } if(Params.get_type() != ENTITY_TYPE_PUBLICATION) { NEWPKIerr(PKI_ERROR_TXT, ERROR_BAD_PARAM); return false; } if(!Params.get_pubCreate()) { NEWPKIerr(PKI_ERROR_TXT, ERROR_BAD_PARAM); return false; } const char * InitialCreates[]={PUB_ENTITY_CREATE_1, NULL}; //We create the database if(!Common_Create(Params.get_pubCreate().get_entityKey(), InitialCreates)) { NEWPKIerr(PKI_ERROR_TXT, ERROR_ABORT); return false; } const char * keyPem; SQL sql(m_DbConn); mString req; //OCSP key switch(Params.get_pubCreate().get_ocspKey().get_type()) { case GEN_PRIVATE_KEY_TYPE_ENGINE: keyPem = Params.get_pubCreate().get_ocspKey().get_keyid().c_str(); if(!m_OcspKey.SetKey(keyPem, m_Engine)) { NEWPKIerr(PKI_ERROR_TXT, ERROR_ABORT); Destroy(); return false; } case GEN_PRIVATE_KEY_TYPE_KEYLEN: if(!m_OcspKey.GenerateKey(Params.get_pubCreate().get_ocspKey().get_keylen(), m_Engine)) { NEWPKIerr(PKI_ERROR_TXT, ERROR_ABORT); Destroy(); return false; } keyPem = m_OcspKey.GetRsaKeyPem().c_str(); break; default: NEWPKIerr(PKI_ERROR_TXT, ERROR_BAD_DATAS); Destroy(); return false; break; } //Insert key in DB if(req.sprintf(PUB_ENTITY_SET_OCSP, "", keyPem) <= 0) { NEWPKIerr(PKI_ERROR_TXT, ERROR_UNKNOWN); Destroy(); return false; } if(!sql.Execute(req)) { NEWPKIerr(PKI_ERROR_TXT, ERROR_ABORT); Destroy(); return false; } if(!response.get_creEntity().set_type(ENTITY_TYPE_PUBLICATION)) { NEWPKIerr(PKI_ERROR_TXT, ERROR_ABORT); Destroy(); return false; } if(!response.get_creEntity().get_pubCreate().set_entityKey(m_EntityKey.GetPublicKey())) { NEWPKIerr(PKI_ERROR_TXT, ERROR_MALLOC); Destroy(); return false; } if(!response.get_creEntity().get_pubCreate().set_ocspKey(m_OcspKey.GetPublicKey())) { NEWPKIerr(PKI_ERROR_TXT, ERROR_MALLOC); Destroy(); return false; } return true; } bool Entity_PUBLICATION::Load() { SQL sql(m_DbConn); mString cert; mString key; long NumRows; if(!Common_Load()) { NEWPKIerr(PKI_ERROR_TXT, ERROR_ABORT); return false; } if(!IsFullyInit()) { return true; } // We get the ocsp certificate if(!sql.Execute(PUB_ENTITY_GET_OCSP)) { NEWPKIerr(PKI_ERROR_TXT, ERROR_ABORT); return false; } if(!sql.NumRows(&NumRows)) { NEWPKIerr(PKI_ERROR_TXT, ERROR_ABORT); return false; } if(NumRows) { if(!sql.Value(0, "ocsp_cert", cert) || !sql.Value(0, "ocsp_key", key)) { NEWPKIerr(PKI_ERROR_TXT, ERROR_ABORT); return false; } //Did we get our ocsp certificate yet ? if(cert.size()) { if(!m_OcspCert.SetCert(cert.c_str())) { NEWPKIerr(PKI_ERROR_TXT, ERROR_ABORT); return false; } if(!m_OcspKey.SetKey(key.c_str(), m_Engine)) { NEWPKIerr(PKI_ERROR_TXT, ERROR_ABORT); return false; } if(!m_OcspCert.SetPrivateKey(m_OcspKey)) { NEWPKIerr(PKI_ERROR_TXT, ERROR_ABORT); return false; } } } //Start the conf synch if(!m_Jobs.StartConfSync()) { NEWPKIerr(PKI_ERROR_TXT, ERROR_ABORT); return false; } return true; } bool Entity_PUBLICATION::Init(const EntitySignatureResp & init_datas) { if(IsFullyInit()) { NEWPKIerr(PKI_ERROR_TXT, ERROR_NOT_ALLOWED); return false; } if(!init_datas) { NEWPKIerr(PKI_ERROR_TXT, ERROR_BAD_PARAM); return false; } if(init_datas.get_body().get_type() != ENTITY_TYPE_PUBLICATION) { NEWPKIerr(PKI_ERROR_TXT, ERROR_BAD_PARAM); return false; } if(!Common_Init(init_datas.get_body().get_signPub().get_entitycert(), init_datas)) { NEWPKIerr(PKI_ERROR_TXT, ERROR_ABORT); return false; } // Insert the OCSP Cert mString key; long NumRows; SQL sql(m_DbConn); mString req; // We get the ocsp key if(!sql.Execute(PUB_ENTITY_GET_OCSP)) { NEWPKIerr(PKI_ERROR_TXT, ERROR_ABORT); return false; } if(!sql.NumRows(&NumRows)) { NEWPKIerr(PKI_ERROR_TXT, ERROR_ABORT); return false; } if(!NumRows) { NEWPKIerr(PKI_ERROR_TXT, ERROR_BAD_DATAS); return false; } if(!sql.Value(0, "ocsp_key", key)) { NEWPKIerr(PKI_ERROR_TXT, ERROR_ABORT); return false; } if(! (m_OcspCert = init_datas.get_body().get_signPub().get_ocspcert()) ) { NEWPKIerr(PKI_ERROR_TXT, ERROR_ABORT); return false; } if(!m_OcspKey.SetKey(key.c_str(), m_Engine)) { NEWPKIerr(PKI_ERROR_TXT, ERROR_ABORT); return false; } if(!m_OcspCert.SetPrivateKey(m_OcspKey)) { NEWPKIerr(PKI_ERROR_TXT, ERROR_ABORT); return false; } //We now insert the OCSP cert in the database if(req.sprintf(PUB_ENTITY_SET_OCSP, m_OcspCert.GetCertPEM().c_str(), key.c_str()) <= 0) { NEWPKIerr(PKI_ERROR_TXT, ERROR_UNKNOWN); return false; } if(!sql.Execute(req)) { NEWPKIerr(PKI_ERROR_TXT, ERROR_ABORT); return false; } return true; } bool Entity_PUBLICATION::LoginUser(UserHandle & hUser, int & UserType) { if(!AclValidator.CanUserPerform(hUser.GetUserCert(), ACL_TYPE_AUTHENTICATE_ON_ENTITY)) { NEWPKIerr(PKI_ERROR_TXT, ERROR_NOT_ALLOWED); return false; } UserType = USER_TYPE_KEYSTORE; return true; } void Entity_PUBLICATION::LogoutUser(const UserHandle & hUser) { } bool Entity_PUBLICATION::ParseNewConf() { PublicationMethod * newMethod; size_t i, j; mString Err; mString Name; // We load the OCSP LoadOcsp(); // We now load all the publicatins methods ListPublicationsLock.LockWrite(); UnloadAllPub(); for(i=0; iLogMessage(LOG_STATUS_TYPE_FAILURE, LOG_MESSAGE_TYPE_LOADING_PUB_METH, 0, _sv("none"), LOG_NO_OBJECTID, Name.c_str(), Err.c_str()); } } catch(ExceptionNewPKI e) { Name.sprintf("%s - %s", myConf.get_conf().get_body().get_pubConf().PUB_CONF_PTR.get_publications()[i].get_caname().c_str(), myConf.get_conf().get_body().get_pubConf().PUB_CONF_PTR.get_publications()[i].get_methods()[j].get_name().c_str()); ERR_to_mstring(Err); m_Logging->LogMessage(LOG_STATUS_TYPE_FAILURE, LOG_MESSAGE_TYPE_LOADING_PUB_METH, 0, _sv("none"), LOG_NO_OBJECTID, Name.c_str(), Err.c_str()); } if(newMethod) ListPublications.push_back(newMethod); } } ListPublicationsLock.UnlockWrite(); return true; } bool Entity_PUBLICATION::Upgrade(const char * Version) { return true; } void Entity_PUBLICATION::GetACL_List(mVector & acl_list) { int i; static ACL_TYPE list_acls[] = { ACL_TYPE_VIEW_LOGS, (ACL_TYPE)0 }; for(i=0; list_acls[i]; i++) { acl_list.push_back(list_acls[i]); } } bool Entity_PUBLICATION::ParseAdminCommand(AdminResponseBody & response, const PKI_CERT & ClientCert, const AdminRequest & AdminRequest) { //We only accept SSLv3 connection if(!ClientCert) { NEWPKIerr(PKI_ERROR_TXT, ERROR_NOT_ALLOWED); ERR_to_ADMIN_RESPONSE(response); return false; } return Private_ParseAdminCommand(true, this, LogsType, response, ClientCert, AdminRequest, GetUserHandle()); } bool Entity_PUBLICATION::Private_ParseAdminCommand(bool ExecuteCmd, Entity * me_this, mVector & mLogsType, AdminResponseBody & response, const PKI_CERT & ClientCert, const AdminRequest & AdminRequest, UserHandle & hUser) { PARSER_COMMAND_BEGIN(Entity_PUBLICATION, response, 0, AdminRequest, ClientCert, hUser, ExecuteCmd, me_this, mLogsType) PARSER_ADD_LOG_ENTRY(LOG_MESSAGE_TYPE_ENTITY_GET_MY_CONF) PARSER_ADD_LOG_ENTRY(LOG_MESSAGE_TYPE_SEND_ADMIN_MAIL) PARSER_ADD_LOG_ENTRY(LOG_MESSAGE_TYPE_SEND_MAIL) PARSER_ADD_LOG_ENTRY(LOG_MESSAGE_TYPE_NEW_REQUEST) PARSER_ADD_LOG_ENTRY(LOG_MESSAGE_TYPE_LOADING_PUB_METH) PARSER_ADD_LOG_ENTRY(LOG_MESSAGE_TYPE_CERT_PUBLICATION) PARSER_ADD_LOG_ENTRY(LOG_MESSAGE_TYPE_REV_PUBLICATION) PARSER_ADD_LOG_ENTRY(LOG_MESSAGE_TYPE_CRL_PUBLICATION) PARSER_ADD_LOG_ENTRY(LOG_MESSAGE_TYPE_OCSP_REQUEST) PARSER_ADD_LOG_ENTRY(LOG_MESSAGE_TYPE_OCSP_STOP) PARSER_ADD_LOG_ENTRY(LOG_MESSAGE_TYPE_OCSP_START) PARSER_COMMAND_ENTRY_LOG( ADMIN_REQ_TYPE_LOGIN, Entity_PUBLICATION::UserLogin, LOG_MESSAGE_TYPE_USER_LOGIN, (ClientCert)?(char*)ClientCert.GetStringName():NULL, LOG_NO_OBJECTID) PARSER_COMMAND_ENTRY( ADMIN_REQ_TYPE_ENUM_LOGS, Entity_PUBLICATION::EnumLogs) PARSER_COMMAND_ENTRY( ADMIN_REQ_TYPE_GET_LOGS_COUNT, Entity_PUBLICATION::GetLogsCount) PARSER_COMMAND_ENTRY( ADMIN_REQ_TYPE_GET_MY_ACL, Entity_PUBLICATION::GetMyACL) PARSER_COMMAND_ENTRY( ADMIN_REQ_TYPE_GET_LOGS_TYPE, Entity_PUBLICATION::GetLogsType) PARSER_COMMAND_ENTRY_LOG( ADMIN_REQ_TYPE_SEND_ADMIN_MAIL, Entity_PUBLICATION::AdminSendMail, LOG_MESSAGE_TYPE_ADD_ADMIN_MAIL_QUEUE, _sv("none"), LOG_NO_OBJECTID) PARSER_COMMAND_ENTRY( ADMIN_REQ_TYPE_CHECK_LOGS, Entity_PUBLICATION::CheckLogsIntegrity) PARSER_COMMAND_END(Entity_PUBLICATION) } void Entity_PUBLICATION::LogsTypeGet(mVector & cLogsType) { Private_ParseAdminCommand(false, NULL, cLogsType, AdminResponseBody::EmptyInstance, PKI_CERT::EmptyInstance, AdminRequest::EmptyInstance, UserHandle::EmptyInstance); } bool Entity_PUBLICATION::Responder_TreatRequest(const NewpkiRequest & Request, const mString & SenderName, NewpkiResponse & Response) { size_t i, j; PublicationMethod * currMethod; mString ldap_uid; mString Err; PKI_P7B p7b; X509 * currCert; LOG_MESSAGE_TYPE LogType; bool PublicationResult; mString PubName; time_t revdate; PKI_CERT cert; PKI_CRL crl; if(Request.get_type() != NEWPKI_REQUEST_TYPE_PUB) { NEWPKIerr(PKI_ERROR_TXT, ERROR_BAD_DATAS); ERR_to_mstring(Err); m_Logging->LogMessage(LOG_STATUS_TYPE_FAILURE, LOG_MESSAGE_TYPE_CERT_PUBLICATION, 0, SenderName.c_str(), LOG_NO_OBJECTID, _sv("Unknown"), Err.c_str()); return false; } // Proceed with publication request ldap_uid = Request.get_pubRequest().get_ldapUid(); AddUnknownCAs(Request.get_pubRequest().get_parentcerts()); // We make the certificate info available to the OCSP responder // even if we don't have a publication method for this CA switch(Request.get_pubRequest().get_body().get_type()) { case NEWPKI_PUB_REQUEST_REV: if( (cert = Request.get_pubRequest().get_body().get_rev().get_cert()) ) { currCert = GetIssuer(Request.get_pubRequest().get_parentcerts(), cert.GetX509(), NULL); if(!currCert) { // TODO insérer un log spécifique } else { revdate = ASN1_TIME_to_timet((char*)Request.get_pubRequest().get_body().get_rev().get_revdate()->data); if(!PublicationStore.OnNewRevocation(cert.GetSerial(), revdate, currCert->cert_info->subject, currCert->cert_info->key)) { // TODO insérer un log spécifique } } } else { // TODO insérer un log spécifique } break; case NEWPKI_PUB_REQUEST_CERT: if( (cert = Request.get_pubRequest().get_body().get_cert()) ) { currCert = GetIssuer(Request.get_pubRequest().get_parentcerts(), cert.GetX509(), NULL); if(!currCert) { // TODO insérer un log spécifique } else { if(!PublicationStore.OnNewCertificate(cert.GetSerial(), currCert->cert_info->subject, currCert->cert_info->key)) { // TODO insérer un log spécifique } } } else { // TODO insérer un log spécifique } break; case NEWPKI_PUB_REQUEST_CRL: if( (crl = Request.get_pubRequest().get_body().get_crl()) ) { currCert = GetIssuer(Request.get_pubRequest().get_parentcerts(), NULL, crl.GetX509_CRL()); if(!currCert) { // TODO insérer un log spécifique } else { if(!PublicationStore.OnNewCrl(crl, currCert->cert_info->subject, currCert->cert_info->key)) { // TODO insérer un log spécifique } } } else { // TODO insérer un log spécifique } break; } PublicationResult = true; ListPublicationsLock.LockRead(); for(i=0; iGetCaName() == SenderName.c_str()) ) continue; ERR_clear_error(); PubName.sprintf("%s : %s", currMethod->GetName().c_str(), Request.get_pubRequest().get_object().c_str()); // Is it the right kind ? switch(Request.get_pubRequest().get_body().get_type()) { case NEWPKI_PUB_REQUEST_CERT: if(currMethod->GetType() != PUBLICATION_METHOD_INFO_TYPE_CERT) continue; LogType = LOG_MESSAGE_TYPE_CERT_PUBLICATION; // Generating the PKCS7 for(j=0; jOnNewCertificate(cert, p7b, ldap_uid); if(!PublicationResult) { NEWPKIerr(PKI_ERROR_TXT, ERROR_ABORT); } } break; case NEWPKI_PUB_REQUEST_REV: if(currMethod->GetType() != PUBLICATION_METHOD_INFO_TYPE_CERT) continue; LogType = LOG_MESSAGE_TYPE_REV_PUBLICATION; PublicationResult = currMethod->OnNewRevocation(cert, ldap_uid); if(!PublicationResult) { NEWPKIerr(PKI_ERROR_TXT, ERROR_ABORT); } break; case NEWPKI_PUB_REQUEST_CRL: if(currMethod->GetType() != PUBLICATION_METHOD_INFO_TYPE_CRL) continue; LogType = LOG_MESSAGE_TYPE_CRL_PUBLICATION; PublicationResult = currMethod->OnNewCrl(crl); if(!PublicationResult) { NEWPKIerr(PKI_ERROR_TXT, ERROR_ABORT); } break; default: continue; break; } if(PublicationResult) { m_Logging->LogMessage(LOG_STATUS_TYPE_SUCCESS, LogType, 0, SenderName.c_str(), LOG_NO_OBJECTID, PubName.c_str()); } else { ERR_to_mstring(Err); m_Logging->LogMessage(LOG_STATUS_TYPE_FAILURE, LogType, 0, SenderName.c_str(), LOG_NO_OBJECTID, PubName.c_str(), Err.c_str()); } } ListPublicationsLock.UnlockRead(); if(!Response.set_type(NEWPKI_RESPONSE_TYPE_PUB)) { return false; } Response.get_pubResponse().set_type(Request.get_pubRequest().get_body().get_type()); Response.get_pubResponse().set_object(Request.get_pubRequest().get_object()); if(PublicationResult) { Response.get_pubResponse().set_status(PUB_RESPONSE_PUBLISHED); } else { Response.get_pubResponse().set_status(PUB_RESPONSE_ERROR); ERR_to_ERROR_ENTRIES(Response.get_pubResponse().get_errors()); } return true; } bool Entity_PUBLICATION::Responder_ValidateRequest(const NewpkiRequest & Request, const X509_PUBKEY * Requester, mString & SenderName) { size_t i; ConfAccessLock.LockRead(); // We need to search that the CA has the right // to publish on us for(i=0; i < myConf.get_conf().get_cas().get_list().size(); i++) { //Is it the same public key if(myConf.get_conf().get_cas().get_list()[i].get_cassl() == Requester) { SenderName = myConf.get_conf().get_cas().get_list()[i].get_name(); break; } } if(i == myConf.get_conf().get_cas().get_list().size()) { ConfAccessLock.UnlockRead(); NEWPKIerr(PKI_ERROR_TXT, ERROR_NOT_ALLOWED); return false; } ConfAccessLock.UnlockRead(); // Is it the right type of request ? if(Request.get_type() != NEWPKI_REQUEST_TYPE_PUB) { NEWPKIerr(PKI_ERROR_TXT, ERROR_BAD_DATAS); return false; } return true; } bool Entity_PUBLICATION::Requester_OnNewResponse(const Asn1OctetString & transactionID, const X509_PUBKEY * sender, const NewpkiResponse & Response) { return true; } void Entity_PUBLICATION::UnloadAllPub() { size_t i; PublicationMethod * currMethod; ListPublicationsLock.LockWrite(); for(i=0; iserialNumber) { NEWPKIerr(OCSP_ERROR_TXT, ERROR_BAD_DATAS_FORMAT); ERR_add_error_data(1, "serialNumber"); OcspStatus = V_OCSP_CERTSTATUS_UNKNOWN; return false; } dgst = EVP_get_digestbyobj(cid->hashAlgorithm->algorithm); if(!dgst) { NEWPKIerr(OCSP_ERROR_TXT, ERROR_BAD_DATAS_FORMAT); if(OBJ_obj2txt(oid, sizeof(oid), cid->hashAlgorithm->algorithm, 1) <= 0) { strcpy(oid, "unknown"); } ERR_add_error_data(2, "hashAlgorithm->algorithm : ", oid); OcspStatus = V_OCSP_CERTSTATUS_UNKNOWN; return false; } ConfAccessLock.LockRead(); // We search if we know this CA (might come latter) for(i=0; i < myConf.get_knownCas().size(); i++) { if( !(ca_id = OCSP_cert_to_id(dgst, NULL, myConf.get_knownCas()[i].GetX509())) ) continue; // Is it for this CA ? if (OCSP_id_issuer_cmp(ca_id, cid) != 0) { OCSP_CERTID_free(ca_id); continue; } OCSP_CERTID_free(ca_id); RequestSerial = ASN1_INTEGER_GET(cid->serialNumber); if(PublicationStore.GetCertStatus(RequestSerial, myConf.get_knownCas()[i].GetX509()->cert_info->subject, myConf.get_knownCas()[i].GetX509()->cert_info->key, OcspStatus, rev_date)) { ConfAccessLock.UnlockRead(); return true; } else { NEWPKIerr(OCSP_ERROR_TXT, ERROR_ABORT); ConfAccessLock.UnlockRead(); return false; } } ConfAccessLock.UnlockRead(); OcspStatus = V_OCSP_CERTSTATUS_UNKNOWN; return true; } void Entity_PUBLICATION::AddUnknownCAs(const mVector & CAs) { size_t i, j, ctr; ctr = myConf.get_knownCas().size(); // We add to our list all the unknown CAs ConfAccessLock.LockWrite(); for(i=0; i < CAs.size(); i++) { for(j=0; j < myConf.get_knownCas().size(); j++) { if(CAs[i] == myConf.get_knownCas()[j]) break; } // The CA is not known if(j == myConf.get_knownCas().size()) { myConf.get_knownCas().push_back(CAs[i]); } } // Did we add some entries ? if(ctr != myConf.get_knownCas().size()) { WritePersonnalConf(); } ConfAccessLock.UnlockWrite(); } X509 * Entity_PUBLICATION::GetIssuer(const mVector & ParentCerts, X509 * Cert, X509_CRL * Crl) { size_t i; EVP_PKEY * pubkey; if(!Cert && !Crl) return NULL; for(i=ParentCerts.size()-1; i >= 0 ; i--) { if( (pubkey = X509_get_pubkey(ParentCerts[i].GetX509())) ) { if(Cert) { if(X509_verify(Cert, pubkey) == 1) { EVP_PKEY_free(pubkey); return ParentCerts[i].GetX509(); } } else if(Crl) { if(X509_CRL_verify(Crl, pubkey) == 1) { EVP_PKEY_free(pubkey); return ParentCerts[i].GetX509(); } } EVP_PKEY_free(pubkey); } } return NULL; } bool Entity_PUBLICATION::OnNewOCSP(const char * Ip, const OCSP_REQUEST *request, OCSP_RESPONSE **response) { mString Err; if(!Private_OnNewOCSP(Ip, request, response)) { ERR_to_mstring(Err); m_Logging->LogMessage(LOG_STATUS_TYPE_FAILURE, LOG_MESSAGE_TYPE_OCSP_REQUEST, 0, _sv("none"), LOG_NO_OBJECTID, m_EntityName.c_str(), Err.c_str()); return false; } return true; } bool Entity_PUBLICATION::Private_OnNewOCSP(const char * Ip, const OCSP_REQUEST *request, OCSP_RESPONSE **response) { ASN1_TIME *thisupd; OCSP_CERTID *cid; OCSP_BASICRESP *bs; int i, id_count; int cert_status; ASN1_TIME *revtm; OCSP_ONEREQ *one; STACK_OF(X509) * ParentCerts; time_t rev_date; mString CaName; unsigned long RequestSerial; id_count = OCSP_request_onereq_count((OCSP_REQUEST*)request); if (id_count <= 0) { *response = OCSP_response_create(OCSP_RESPONSE_STATUS_MALFORMEDREQUEST, NULL); NEWPKIerr(OCSP_ERROR_TXT, ERROR_BAD_DATAS_FORMAT); return false; } bs = OCSP_BASICRESP_new(); if(!bs) { *response = OCSP_response_create(OCSP_RESPONSE_STATUS_INTERNALERROR, NULL); NEWPKIerr(OCSP_ERROR_TXT, ERROR_MALLOC); return false; } thisupd = X509_gmtime_adj(NULL, 0); if(!thisupd) { *response = OCSP_response_create(OCSP_RESPONSE_STATUS_INTERNALERROR, NULL); NEWPKIerr(OCSP_ERROR_TXT, ERROR_MALLOC); OCSP_BASICRESP_free(bs); return false; } // Examine each certificate id in the request for (i = 0; i < id_count; i++) { // Get request one = OCSP_request_onereq_get0((OCSP_REQUEST*)request, i); if(!one) { *response = OCSP_response_create(OCSP_RESPONSE_STATUS_INTERNALERROR, NULL); NEWPKIerr(OCSP_ERROR_TXT, ERROR_ABORT); OCSP_BASICRESP_free(bs); ASN1_TIME_free(thisupd); return false; } // Get certificate info cid = OCSP_onereq_get0_id(one); if(!cid) { *response = OCSP_response_create(OCSP_RESPONSE_STATUS_INTERNALERROR, NULL); NEWPKIerr(OCSP_ERROR_TXT, ERROR_ABORT); OCSP_BASICRESP_free(bs); ASN1_TIME_free(thisupd); return false; } // Get its state if(!GetOcspCertStatus(cid, cert_status, rev_date, CaName, RequestSerial)) { *response = OCSP_response_create(OCSP_RESPONSE_STATUS_INTERNALERROR, NULL); NEWPKIerr(OCSP_ERROR_TXT, ERROR_ABORT); OCSP_BASICRESP_free(bs); ASN1_TIME_free(thisupd); return false; } CaName += ":"; CaName += RequestSerial; m_Logging->LogMessage(LOG_STATUS_TYPE_REQUEST, LOG_MESSAGE_TYPE_OCSP_REQUEST, 0, Ip, LOG_NO_OBJECTID, CaName.c_str()); if(cert_status == V_OCSP_CERTSTATUS_REVOKED) { revtm = ASN1_TIME_set_localtime(NULL, rev_date); if(!revtm) { *response = OCSP_response_create(OCSP_RESPONSE_STATUS_INTERNALERROR, NULL); NEWPKIerr(OCSP_ERROR_TXT, ERROR_ABORT); OCSP_BASICRESP_free(bs); ASN1_TIME_free(thisupd); return false; } } else { revtm = NULL; } // Add the status for the current certificate if(!OCSP_basic_add1_status(bs, cid, cert_status, 0, revtm, thisupd, NULL)) { *response = OCSP_response_create(OCSP_RESPONSE_STATUS_INTERNALERROR, NULL); NEWPKIerr(OCSP_ERROR_TXT, ERROR_ABORT); OCSP_BASICRESP_free(bs); ASN1_TIME_free(thisupd); if(revtm) ASN1_TIME_free(revtm); return false; } if(revtm) ASN1_TIME_free(revtm); } ASN1_TIME_free(thisupd); if(OCSP_copy_nonce(bs, (OCSP_REQUEST*)(OCSP_REQUEST*)request) <= 0) { *response = OCSP_response_create(OCSP_RESPONSE_STATUS_INTERNALERROR, NULL); NEWPKIerr(OCSP_ERROR_TXT, ERROR_ABORT); OCSP_BASICRESP_free(bs); return false; } ConfAccessLock.LockRead(); X509 * currParentCert; ParentCerts = SKM_sk_new_null(X509); if(ParentCerts) { currParentCert = myConf.get_cas().get_rootca().GetX509(true); if(currParentCert) { if(SKM_sk_push(X509, ParentCerts, currParentCert) < 0) { X509_free(currParentCert); } } currParentCert = myConf.get_cas().get_ocspca().GetX509(true); if(currParentCert) { if(SKM_sk_push(X509, ParentCerts, currParentCert) < 0) { X509_free(currParentCert); } } } if(OCSP_basic_sign(bs, m_OcspCert.GetX509(), (EVP_PKEY*)m_OcspKey.GetRsaKey(), EVP_sha1(), ParentCerts, 0) <= 0) { *response = OCSP_response_create(OCSP_RESPONSE_STATUS_INTERNALERROR, NULL); NEWPKIerr(OCSP_ERROR_TXT, ERROR_ABORT); OCSP_BASICRESP_free(bs); ConfAccessLock.UnlockRead(); SKM_sk_pop_free(X509, ParentCerts, X509_free); return false; } SKM_sk_pop_free(X509, ParentCerts, X509_free); ConfAccessLock.UnlockRead(); *response = OCSP_response_create(OCSP_RESPONSE_STATUS_SUCCESSFUL, bs); OCSP_BASICRESP_free(bs); return true; } void Entity_PUBLICATION::SetOcspServersHandler(OcspServers *OcspServersHandler) { m_OcspServersHandler = OcspServersHandler; ConfAccessLock.LockRead(); LoadOcsp(); ConfAccessLock.UnlockRead(); } void Entity_PUBLICATION::LoadOcsp() { ServerConf Conf; mString Name; mString Err; if(!m_OcspServersHandler || !myConf || !m_Logging) return; if(!myConf.get_conf().get_body().get_pubConf().PUB_CONF_PTR.get_ocspenabled()) { if(m_OcspServersHandler->IsRunning(m_EntityName)) { // Unload the server m_OcspServersHandler->StopServer(m_EntityName); m_Logging->LogMessage(LOG_STATUS_TYPE_SUCCESS, LOG_MESSAGE_TYPE_OCSP_STOP, 0, _sv("none"), LOG_NO_OBJECTID, m_EntityName.c_str()); } } else { if(myConf.get_conf().get_body().get_pubConf().PUB_CONF_PTR.get_bindaddress().size()) Conf.set_BindAddress(myConf.get_conf().get_body().get_pubConf().PUB_CONF_PTR.get_bindaddress()); Conf.set_LocalPort(myConf.get_conf().get_body().get_pubConf().PUB_CONF_PTR.get_port()); Name.sprintf("OCSP - %s", m_EntityName.c_str()); Conf.set_ServerName(Name); if(!m_OcspServersHandler->StartServer(m_EntityName, Conf)) { ERR_to_mstring(Err); m_Logging->LogMessage(LOG_STATUS_TYPE_FAILURE, LOG_MESSAGE_TYPE_OCSP_START, 0, _sv("none"), LOG_NO_OBJECTID, m_EntityName.c_str(), Err.c_str()); } else { m_Logging->LogMessage(LOG_STATUS_TYPE_SUCCESS, LOG_MESSAGE_TYPE_OCSP_START, 0, _sv("none"), LOG_NO_OBJECTID, m_EntityName.c_str()); } } } bool Entity_PUBLICATION::PrepareConfToWrite() { return true; }