/* 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_SERVER.cpp: implementation of the Entity_SERVER class. // ////////////////////////////////////////////////////////////////////// #include "Entity_CA.h" #include "Entity_RA.h" #include "Entity_PKI.h" #include "Entity_REPOSITORY.h" #include "Entity_PUBLICATION.h" #include "Entity_KEYSTORE.h" #include "Entity_BACKUP.h" #include #include "Entity_SERVER.h" #include "svintl.h" ////////////////////////////////////////////////////////////////////// // Construction/Destruction ////////////////////////////////////////////////////////////////////// Entity_SERVER::Entity_SERVER(ENTITY_CONSTRUCTOR_PARAMETERS):Entity(ENTITY_CONSTRUCTOR_PARAM_PASSTHRU, NULL, NULL) { m_ThreadDeleteEntity.Create(ThreadDeleteEntity, this); m_ThreadUnloadEntity.Create(ThreadUnloadEntity, this); } Entity_SERVER::~Entity_SERVER() { std::map::iterator i; m_Jobs.StopAll(); m_ThreadDeleteEntity.Stop(); m_EntitiesLock.LockWrite(); for(i=m_EntitiesList.begin(); i != m_EntitiesList.end(); i++) { if(i->second.entity) { NewpkiDebug(LOG_LEVEL_DEBUG, _sv("NewPKI Server"), _sv("Unloading entity %s"), i->first.c_str()); i->second.entity->WaitForNoClients(); delete i->second.entity; NewpkiDebug(LOG_LEVEL_DEBUG, _sv("NewPKI Server"), _sv("Successfully unloaded entity %s"), i->first.c_str()); } } m_EntitiesList.clear(); m_EntitiesLock.UnlockWrite(); } Entity * Entity_SERVER::Entity_new(const mString & Name, int Type) { switch(Type) { case ENTITY_TYPE_RA: return new Entity_RA(m_Conf, Name, m_Engine, m_AuthModule, Type); break; case ENTITY_TYPE_CA: return new Entity_CA(m_Conf, Name, m_Engine, m_AuthModule, Type); break; case ENTITY_TYPE_PKI: return new Entity_PKI(m_Conf, Name, m_Engine, m_AuthModule, Type); break; case ENTITY_TYPE_REPOSITORY: return new Entity_REPOSITORY(m_Conf, Name, m_Engine, m_AuthModule, Type); break; case ENTITY_TYPE_KEY_STORE: return new Entity_KEYSTORE(m_Conf, Name, m_Engine, m_AuthModule, Type); break; case ENTITY_TYPE_BACKUP: return new Entity_BACKUP(m_Conf, Name, m_Engine, m_AuthModule, Type); break; case ENTITY_TYPE_PUBLICATION: return new Entity_PUBLICATION(m_Conf, Name, m_Engine, m_AuthModule, Type); break; default: return NULL; } } bool Entity_SERVER::Create(const EntityCreationDatas & Params, AdminResponseBody & response) { GenPrivateKey entity_key; const char * InitialCreates[]={INITIAL_CREATE_1, INITIAL_CREATE_2, INITIAL_CREATE_3, INITIAL_CREATE_4, INITIAL_CREATE_5, NULL}; if(m_Conf.get_SSL_KeyId().size()) { if(!entity_key.set_type(GEN_PRIVATE_KEY_TYPE_ENGINE)) { NEWPKIerr(PKI_ERROR_TXT, ERROR_ABORT); return false; } entity_key.set_keyid(m_Conf.get_SSL_KeyId()); } else { if(!entity_key.set_type(GEN_PRIVATE_KEY_TYPE_KEYLEN)) { NEWPKIerr(PKI_ERROR_TXT, ERROR_ABORT); return false; } entity_key.set_keylen(2048); } entity_key.set_isOK(); NewpkiDebug(LOG_LEVEL_DEBUG, _sv("NewPKI Server"), _sv("Creating NewPKI database...")); //We create the database if(!Common_Create(entity_key, InitialCreates)) { NEWPKIerr(PKI_ERROR_TXT, ERROR_ABORT); NewpkiDebug(LOG_LEVEL_ERROR, _sv("NewPKI Server"), _sv("Failed to create NewPKI database")); return false; } entity_key.Clear(); NewpkiDebug(LOG_LEVEL_DEBUG, _sv("NewPKI Server"), _sv("Successfully created NewPKI database")); // Creation of the SSL certificate NewpkiDebug(LOG_LEVEL_DEBUG, _sv("NewPKI Server"), _sv("Creating NewPKI server's SSL certificate...")); if(!CreateSSL_CERT()) { NEWPKIerr(PKI_ERROR_TXT, ERROR_ABORT); NewpkiDebug(LOG_LEVEL_ERROR, _sv("NewPKI Server"), _sv("Failed to create NewPKI server's SSL certificate")); Destroy(); return false; } if(!Common_Init(m_EntityCert, EntitySignatureResp::EmptyInstance)) { NEWPKIerr(PKI_ERROR_TXT, ERROR_ABORT); NewpkiDebug(LOG_LEVEL_ERROR, _sv("NewPKI Server"), _sv("Failed to create NewPKI server's SSL certificate")); Destroy(); return false; } NewpkiDebug(LOG_LEVEL_DEBUG, _sv("NewPKI Server"), _sv("Successfully created NewPKI server's SSL certificate")); return true; } bool Entity_SERVER::Init(const EntitySignatureResp & init_datas) { NEWPKIerr(PKI_ERROR_TXT, ERROR_NOT_ALLOWED); return false; } bool Entity_SERVER::Load() { SQL sql(m_DbConn); long NumRows; long i; mString entity_name; mString str_entity_type; mString str_err; ENTITY_INFO entity_info; if(!Common_Load()) { NEWPKIerr(PKI_ERROR_TXT, ERROR_ABORT); return false; } if(!IsFullyInit()) { NEWPKIerr(PKI_ERROR_TXT, ERROR_UNKNOWN); return false; } // Getting available entities and loading each of them if(!sql.Execute(INITIAL_GET_ENTITIES) ) { NEWPKIerr(PKI_ERROR_TXT, ERROR_ABORT); return false; } if(!sql.NumRows(&NumRows)) { NEWPKIerr(PKI_ERROR_TXT, ERROR_ABORT); return false; } for(i=0; iLogMessage(LOG_STATUS_TYPE_FAILURE, LOG_MESSAGE_TYPE_ENTITY_LOAD, 0, NULL, LOG_NO_OBJECTID, entity_name.c_str(), str_err.c_str()); NewpkiDebug(LOG_LEVEL_ERROR, entity_name.c_str(), _sv("Entity failed to load: %s"), str_err.c_str()); } else { m_Logging->LogMessage(LOG_STATUS_TYPE_SUCCESS, LOG_MESSAGE_TYPE_ENTITY_LOAD, 0, NULL, LOG_NO_OBJECTID, entity_name.c_str()); NewpkiDebug(LOG_LEVEL_DEBUG, entity_name.c_str(), _sv("Entity loaded")); } //Add it to the list m_EntitiesLock.LockWrite(); m_EntitiesList[entity_name] = entity_info; m_EntitiesLock.UnlockWrite(); } if(!m_ThreadDeleteEntity.Start()) { NEWPKIerr(PKI_ERROR_TXT, ERROR_ABORT); return false; } if(!m_ThreadUnloadEntity.Start()) { NEWPKIerr(PKI_ERROR_TXT, ERROR_ABORT); return false; } return true; } Entity * Entity_SERVER::LoadEntity(const mString & Name, int Type) { Entity * entity; //We create the entity try { entity = Entity_new(Name, Type); } catch(ExceptionNewPKI e) { NEWPKIerr(PKI_ERROR_TXT, ERROR_ABORT); return NULL; } if(!entity) { NEWPKIerr(PKI_ERROR_TXT, ERROR_ABORT); return NULL; } //We upgrade it if(!entity->Upgrade(NEWPKI_VERSION)) { delete entity; NEWPKIerr(PKI_ERROR_TXT, ERROR_ABORT); NewpkiDebug(LOG_LEVEL_ERROR, _sv("NewPKI Server"), _sv("Failed to upgrade Entity %s"), Name.c_str()); return NULL; } //We load it if(!entity->Load()) { delete entity; NEWPKIerr(PKI_ERROR_TXT, ERROR_ABORT); NewpkiDebug(LOG_LEVEL_ERROR, _sv("NewPKI Server"), _sv("Failed to load Entity %s"), Name.c_str()); return NULL; } return entity; } bool Entity_SERVER::OnADMIN_REQUEST(AdminResponse & response, const char * ClientIp, const PKI_CERT & ClientCert, const AdminRequest & AdminReq) { mString EntityName; mString err; if(ParseAdminRequest(response.get_body(), ClientCert, AdminReq, EntityName)) { m_Logging->LogMessage(LOG_STATUS_TYPE_SUCCESS, LOG_MESSAGE_TYPE_ADMIN_REQUEST, 0, ClientIp, LOG_NO_OBJECTID, EntityName.c_str()); } else { ERR_to_mstring(err); m_Logging->LogMessage(LOG_STATUS_TYPE_FAILURE, LOG_MESSAGE_TYPE_ADMIN_REQUEST, 0, ClientIp, LOG_NO_OBJECTID, EntityName.c_str(), err.c_str()); } return EntitySignResponse(response); } bool Entity_SERVER::ParseAdminRequest(AdminResponseBody & response, const PKI_CERT & ClientCert, const AdminRequest & AdminReq, mString & EntityName) { Entity * entity; bool ret; ERR_clear_error(); m_EntitiesLock.LockRead(); entity = GetEntity(); if(AdminReq.get_body().get_type() == ADMIN_REQ_TYPE_LOGIN) { // User wants to login but he already did if(entity) { NEWPKIerr(PKI_ERROR_TXT, ERROR_BAD_PKI_COMMAND); m_EntitiesLock.UnlockRead(); ERR_to_ADMIN_RESPONSE(response); EntityName = entity->GetName(); return false; } //Get entity user intents to log on // we add the user to the list of known users GlobalUsersLock.EnterCS(); if(!AdminReq.get_body().get_login().get_entity().size()) { //It's for the local server entity (myself) GlobalUsers[NewpkiThread::CurrentThreadId()] = INITIAL_DB; } else { GlobalUsers[NewpkiThread::CurrentThreadId()] = AdminReq.get_body().get_login().get_entity(); } GlobalUsersLock.LeaveCS(); entity = GetEntity(); } if(!entity) { NEWPKIerr(PKI_ERROR_TXT, ERROR_UNKNOWN_ENTITY); m_EntitiesLock.UnlockRead(); ERR_to_ADMIN_RESPONSE(response); EntityName = _sv("Unknown"); return false; } EntityName = entity->GetName(); entity->ClientEnter(); m_EntitiesLock.UnlockRead(); if(!entity->IsFullyInit()) {// I don't take commands for an entity when it's not initialized entity->ClientLeave(); NEWPKIerr(PKI_ERROR_TXT, ERROR_ENTITY_NOT_READY); ERR_to_ADMIN_RESPONSE(response); return false; } else { ret = entity->ParseAdminCommand(response, ClientCert, AdminReq); } entity->ClientLeave(); return ret; } void Entity_SERVER::OnConnectionClosed() { Entity * entity; std::map::iterator user; m_EntitiesLock.LockRead(); if( (entity = GetEntity()) ) { GlobalUsersLock.EnterCS(); user = GlobalUsers.find(NewpkiThread::CurrentThreadId()); if(user != GlobalUsers.end()) { GlobalUsers.erase(user); } GlobalUsersLock.LeaveCS(); entity->ClientEnter(); entity->OnUserLogout(); entity->ClientLeave(); } m_EntitiesLock.UnlockRead(); } Entity * Entity_SERVER::GetEntity() { mString entity_name; std::map::iterator user; GlobalUsersLock.EnterCS(); //Is user known ? user = GlobalUsers.find(NewpkiThread::CurrentThreadId()); if(user == GlobalUsers.end()) { GlobalUsersLock.LeaveCS(); return NULL; } entity_name = user->second; GlobalUsersLock.LeaveCS(); //If it's me we do internal processing if(entity_name == INITIAL_DB) { return this; } else { //We get the associated entity if( m_EntitiesList.find(entity_name) == m_EntitiesList.end() ) { return NULL; } return m_EntitiesList[entity_name].entity; } } bool Entity_SERVER::CreateSSL_CERT() { mString req; char localName[500]; mString cert_pem; mString key_pem; HashTable_Dn Dn; PKI_CSR CsrK; mString emailAddress; if(gethostname(localName, sizeof(localName)) == -1) { strcpy(localName, "localhost"); } emailAddress = "localhost@"; emailAddress += localName; Dn.Add("commonName", localName); Dn.Add("organizationName", "NewPKI"); Dn.Add("organizationalUnitName", "SSL Server"); Dn.Add("emailAddress", (char*)emailAddress.c_str()); if(!CsrK.GenerateCSR(Dn, m_EntityKey)) { NEWPKIerr(PKI_ERROR_TXT, ERROR_ABORT); return false; } HashTable_String Exts; Exts.Add("basicConstraints", "CA:FALSE"); Exts.Add("nsComment", "NewPKI SSL Server Certificate"); Exts.Add("subjectKeyIdentifier", "hash"); Exts.Add("authorityKeyIdentifier", "keyid:always"); Exts.Add("keyUsage", "digitalSignature, nonRepudiation, keyEncipherment"); Exts.Add("nsCertType", "server"); Exts.Add("extendedKeyUsage", "serverAuth"); if(!m_EntityCert.CreateSelfSigned(CsrK, &Exts, 3650, 1)) { NEWPKIerr(PKI_ERROR_TXT, ERROR_ABORT); return false; } return true; } bool Entity_SERVER::ParseAdminCommand(AdminResponseBody & response, const PKI_CERT & ClientCert, const AdminRequest & AdminReq) { unsigned long user_id; UserHandle & hUser = GetUserHandle(); user_id = ( (hUser)?hUser.GetUserId():0); PARSER_COMMAND_BEGIN(Entity_SERVER, response, user_id, AdminReq, ClientCert, hUser, true, this, LogsType) PARSER_ADD_LOG_ENTRY(LOG_MESSAGE_TYPE_ENTITY_LOAD) PARSER_COMMAND_ENTRY_LOG( ADMIN_REQ_TYPE_LOGIN, Entity_SERVER::UserLogin, LOG_MESSAGE_TYPE_USER_LOGIN, (AdminReq.get_body().get_login().get_username().size()?AdminReq.get_body().get_login().get_username():(ClientCert?ClientCert.GetStringName():"")), LOG_NO_OBJECTID) PARSER_COMMAND_ENTRY_LOG( ADMIN_REQ_TYPE_CREATE_ENTITY, Entity_SERVER::CreateEntity, LOG_MESSAGE_TYPE_ENTITY_ADD, AdminReq.get_body().get_creEntity().get_name() , LOG_NO_OBJECTID) PARSER_COMMAND_ENTRY_LOG( ADMIN_REQ_TYPE_DELETE_ENTITY, Entity_SERVER::DeleteEntity, LOG_MESSAGE_TYPE_ENTITY_DEL, AdminReq.get_body().get_entityName(), LOG_NO_OBJECTID) PARSER_COMMAND_ENTRY( ADMIN_REQ_TYPE_ENUM_ENTITIES, Entity_SERVER::EnumEntities) PARSER_COMMAND_ENTRY( ADMIN_REQ_TYPE_ENUM_LOGS, Entity_SERVER::EnumLogs) PARSER_COMMAND_ENTRY( ADMIN_REQ_TYPE_GET_LOGS_COUNT, Entity_SERVER::GetLogsCount) PARSER_COMMAND_ENTRY( ADMIN_REQ_TYPE_ENUM_USERS, Entity_SERVER::EnumUsers) PARSER_COMMAND_ENTRY_LOG( ADMIN_REQ_TYPE_CREATE_USER, Entity_SERVER::CreateUser, LOG_MESSAGE_TYPE_USER_ADD, AdminReq.get_body().get_creUser().get_name(), LOG_NO_OBJECTID) PARSER_COMMAND_ENTRY_LOG( ADMIN_REQ_TYPE_UPDATE_USER, Entity_SERVER::UpdateUser, LOG_MESSAGE_TYPE_USER_MOD, "", AdminReq.get_body().get_updUser().get_userId()) PARSER_COMMAND_ENTRY_LOG( ADMIN_REQ_TYPE_CHG_USER_PASSWD, Entity_SERVER::ChangeUserPassword, LOG_MESSAGE_TYPE_PWD_MOD, "", AdminReq.get_body().get_chgUserPwd().get_userId()) PARSER_COMMAND_ENTRY_LOG( ADMIN_REQ_TYPE_CHG_PASSWD, Entity_SERVER::ChangePassword, LOG_MESSAGE_TYPE_PWD_MOD, "", hUser.GetUserId()) PARSER_COMMAND_ENTRY_LOG( ADMIN_REQ_TYPE_INIT_ENTITY, Entity_SERVER::InitEntity, LOG_MESSAGE_TYPE_ENTITY_INIT, AdminReq.get_body().get_initEntity().get_name() , LOG_NO_OBJECTID) PARSER_COMMAND_ENTRY( ADMIN_REQ_TYPE_GET_LOGS_TYPE, Entity_SERVER::GetLogsType) PARSER_COMMAND_ENTRY( ADMIN_REQ_TYPE_CHECK_LOGS, Entity_SERVER::CheckLogsIntegrity) PARSER_COMMAND_ENTRY_LOG( ADMIN_REQ_TYPE_LOAD_ENTITY, Entity_SERVER::EntityLoad, LOG_MESSAGE_TYPE_ENTITY_LOAD, AdminReq.get_body().get_entityName(), LOG_NO_OBJECTID) PARSER_COMMAND_ENTRY_LOG( ADMIN_REQ_TYPE_UNLOAD_ENTITY, Entity_SERVER::EntityUnload, LOG_MESSAGE_TYPE_ENTITY_UNLOAD, AdminReq.get_body().get_entityName(), LOG_NO_OBJECTID) PARSER_COMMAND_END(Entity_SERVER) } bool Entity_SERVER::LoginUser(UserHandle & hUser, int & UserType) { mString req; long NumRows; mString tmpdatas; PKI_PASSWD pki_password; mString username; mString password; username = hUser.GetUserName(); password = hUser.GetPassword(); if(!username.size() || !password.size()) { NEWPKIerr(PKI_ERROR_TXT, ERROR_BAD_PKI_COMMAND); return false; } SQL sql(m_DbConn); // We seek the user if(req.sprintf( SQL_SELECT_USER, username.c_str()) <= 0) { NEWPKIerr(PKI_ERROR_TXT, ERROR_ABORT); return false; } if(!sql.Execute(req)) { 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_UNKNOWN_USER); return false; } if(!sql.Value(0, "flags", tmpdatas)) { NEWPKIerr(PKI_ERROR_TXT, ERROR_ABORT); return false; } if( (tmpdatas.c_lng() & USER_FLAGS_EXTERNAL_AUTH) ) { if(!m_AuthModule || !m_AuthModule->Login((char*)username.c_str(), (char*)password.c_str())) { NEWPKIerr(PKI_ERROR_TXT, ERROR_BAD_UNKNOWN_USER); return false; } } else { if(!sql.Value(0, "password", tmpdatas)) { NEWPKIerr(PKI_ERROR_TXT, ERROR_ABORT); return false; } if(!pki_password.VerifySHA1Password((char*)password.c_str(), (char*)tmpdatas.c_str())) { NEWPKIerr(PKI_ERROR_TXT, ERROR_BAD_UNKNOWN_USER); return false; } } if(!sql.Value(0, "user_id", tmpdatas)) { NEWPKIerr(PKI_ERROR_TXT, ERROR_ABORT); return false; } hUser.SetUserId(tmpdatas.c_ulng()); if(!sql.Value(0, "activated", tmpdatas)) { NEWPKIerr(PKI_ERROR_TXT, ERROR_ABORT); return false; } // If user has been deactivated if(!tmpdatas.c_int()) { NEWPKIerr(PKI_ERROR_TXT, ERROR_BAD_UNKNOWN_USER); return false; } UserType = USER_TYPE_SERVER; return true; } void Entity_SERVER::LogoutUser(const UserHandle & hUser) { } bool Entity_SERVER::CreateEntity(COMMAND_PARAMETERS) { ENTITY_INFO entity_info; if(!hUser) { NEWPKIerr(PKI_ERROR_TXT, ERROR_NOT_ALLOWED); return false; } entity_info.Type = body.get_creEntity().get_datas().get_type(); if(!body.get_creEntity().get_name().size()) { NEWPKIerr(PKI_ERROR_TXT, ERROR_BAD_PARAM); return false; } //We create the entity entity_info.entity = Entity_new(body.get_creEntity().get_name(), entity_info.Type); if(!entity_info.entity) { NEWPKIerr(PKI_ERROR_TXT, ERROR_ABORT); return false; } if(!response.set_type(ADMIN_RESP_TYPE_CREATE_ENTITY)) { NEWPKIerr(PKI_ERROR_TXT, ERROR_ABORT); return false; } if(!entity_info.entity->Create(body.get_creEntity().get_datas(), response)) { delete entity_info.entity; NEWPKIerr(PKI_ERROR_TXT, ERROR_ABORT); return false; } if(!entity_info.entity->Load()) { entity_info.entity->Destroy(); delete entity_info.entity; NEWPKIerr(PKI_ERROR_TXT, ERROR_ABORT); return false; } //We now insert it in the database SQL sql(m_DbConn); mString req; if(req.sprintf(INITIAL_INSERT_ENTITY, body.get_creEntity().get_name().c_str(), entity_info.Type) == -1) { entity_info.entity->Destroy(); delete entity_info.entity; NEWPKIerr(PKI_ERROR_TXT, ERROR_MALLOC); return false; } if(!sql.Execute(req)) { entity_info.entity->Destroy(); delete entity_info.entity; NEWPKIerr(PKI_ERROR_TXT, ERROR_ABORT); return false; } if(entity_info.Type == ENTITY_TYPE_PUBLICATION) { ((Entity_PUBLICATION*)entity_info.entity)->SetOcspServersHandler(m_OcspServersHandler); } m_EntitiesLock.LockWrite(); m_EntitiesList[body.get_creEntity().get_name()] = entity_info; m_EntitiesLock.UnlockWrite(); return true; } bool Entity_SERVER::DeleteEntity(COMMAND_PARAMETERS) { mString req; Entity * entity; if(!hUser) { NEWPKIerr(PKI_ERROR_TXT, ERROR_NOT_ALLOWED); return false; } if(!response.set_type(ADMIN_RESP_TYPE_NONE)) { NEWPKIerr(PKI_ERROR_TXT, ERROR_ABORT); return false; } SQL sql(m_DbConn); if(!body.get_entityName().size()) { NEWPKIerr(PKI_ERROR_TXT, ERROR_BAD_PARAM); return false; } m_EntitiesLock.LockWrite(); if( m_EntitiesList.find(body.get_entityName()) == m_EntitiesList.end() ) { m_EntitiesLock.UnlockWrite(); NEWPKIerr(PKI_ERROR_TXT, ERROR_UNKNOWN_ENTITY); return false; } //We remove it from the database if(req.sprintf(INITIAL_REMOVE_ENTITY, body.get_entityName().c_str()) <= 0) { m_EntitiesLock.UnlockWrite(); NEWPKIerr(PKI_ERROR_TXT, ERROR_MALLOC); return false; } if(!sql.Execute(req)) { m_EntitiesLock.UnlockWrite(); NEWPKIerr(PKI_ERROR_TXT, ERROR_ABORT); return false; } entity = m_EntitiesList[body.get_entityName()].entity; m_EntitiesList.erase(body.get_entityName()); m_EntitiesLock.UnlockWrite(); if(entity) { m_DeleteEntitiesLock.EnterCS(); m_DeleteEntitiesList.push_back(entity); m_DeleteEntitiesLock.LeaveCS(); } return true; } bool Entity_SERVER::EnumEntities(COMMAND_PARAMETERS) { EntityEntryInfo entity; std::map::iterator i; if(!hUser) { NEWPKIerr(PKI_ERROR_TXT, ERROR_NOT_ALLOWED); return false; } if(!response.set_type(ADMIN_RESP_TYPE_ENUM_ENTITIES)) { NEWPKIerr(PKI_ERROR_TXT, ERROR_ABORT); return false; } m_EntitiesLock.LockRead(); for(i=m_EntitiesList.begin(); i != m_EntitiesList.end(); i++) { entity.set_name(i->first); entity.set_type(i->second.Type); if(i->second.entity) { i->second.entity->GetEntityCertificate(entity.get_certificate()); entity.set_loaded(1); } else { entity.get_certificate().Clear(); entity.set_loaded(0); } response.get_entities().push_back(entity); } m_EntitiesLock.UnlockRead(); return true; } bool Entity_SERVER::EnumUsers(COMMAND_PARAMETERS) { if(!hUser) { NEWPKIerr(PKI_ERROR_TXT, ERROR_NOT_ALLOWED); return false; } if(!response.set_type(ADMIN_RESP_TYPE_ENUM_USERS)) { NEWPKIerr(PKI_ERROR_TXT, ERROR_ABORT); return false; } if(!Private_EnumUsers(response, hUser)) { NEWPKIerr(PKI_ERROR_TXT, ERROR_ABORT); return false; } return true; } bool Entity_SERVER::CreateUser(COMMAND_PARAMETERS) { if(!hUser) { NEWPKIerr(PKI_ERROR_TXT, ERROR_NOT_ALLOWED); return false; } if(!response.set_type(ADMIN_RESP_TYPE_NONE)) { NEWPKIerr(PKI_ERROR_TXT, ERROR_ABORT); return false; } if(!Private_CreateUser(response, hUser, body.get_creUser().get_name(), body.get_creUser().get_flags(), body.get_creUser().get_activated())) { NEWPKIerr(PKI_ERROR_TXT, ERROR_ABORT); return false; } return true; } bool Entity_SERVER::Private_EnumUsers(AdminResponseBody & response, const UserHandle & hUser) { SQL sql(m_DbConn); long NumRows; mString tmpstr; UserEntry user; int i; if(!sql.Execute(SQL_SELECT_USERS)) { NEWPKIerr(PKI_ERROR_TXT, ERROR_ABORT); return false; } if(!sql.NumRows(&NumRows)) { NEWPKIerr(PKI_ERROR_TXT, ERROR_ABORT); return false; } for(i=0; iValidateUsername(Username.c_str())) { NEWPKIerr(PKI_ERROR_TXT, ERROR_ABORT); return false; } } password = pwd.CalcSHA1Password(Username); if(!password) { NEWPKIerr(PKI_ERROR_TXT, ERROR_UNKNOWN); return false; } if(req.sprintf(SQL_INSERT_USER, Username.c_str(), password, Activated, Flags) <= 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_SERVER::UpdateUser(COMMAND_PARAMETERS) { if(!hUser) { NEWPKIerr(PKI_ERROR_TXT, ERROR_NOT_ALLOWED); return false; } if(!response.set_type(ADMIN_RESP_TYPE_NONE)) { NEWPKIerr(PKI_ERROR_TXT, ERROR_ABORT); return false; } if(!Private_UpdateUser(response, hUser, body.get_updUser().get_userId(), body.get_updUser().get_userInfo().get_name(), body.get_updUser().get_userInfo().get_flags(), body.get_updUser().get_userInfo().get_activated())) { NEWPKIerr(PKI_ERROR_TXT, ERROR_ABORT); return false; } return true; } bool Entity_SERVER::Private_UpdateUser(AdminResponseBody & response, const UserHandle & hUser, unsigned long user_id, const mString & Username, unsigned long Flags, int Activated) { SQL sql(m_DbConn); mString req; if(!Username.size()) { NEWPKIerr(PKI_ERROR_TXT, ERROR_BAD_PARAM); return false; } //No one ca modify the default admin ! if(user_id == DEFAULT_ADMIN_ID) { NEWPKIerr(PKI_ERROR_TXT, ERROR_NOT_ALLOWED); return false; } //We verify thru the module the validity of the username if( (Flags & USER_FLAGS_EXTERNAL_AUTH) ) { if(!m_AuthModule) { NEWPKIerr(PKI_ERROR_TXT, ERROR_BAD_AUTH_LIB); return false; } if(!m_AuthModule->ValidateUsername(Username.c_str())) { NEWPKIerr(PKI_ERROR_TXT, ERROR_ABORT); return false; } } if(req.sprintf(SQL_UPDATE_USER, Username.c_str(), Activated, Flags, user_id) <= 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_SERVER::ChangeUserPassword(COMMAND_PARAMETERS) { if(!hUser) { NEWPKIerr(PKI_ERROR_TXT, ERROR_NOT_ALLOWED); return false; } if(!response.set_type(ADMIN_RESP_TYPE_NONE)) { NEWPKIerr(PKI_ERROR_TXT, ERROR_ABORT); return false; } if(!Private_ChangeUserPassword(response, hUser, body.get_chgUserPwd().get_userId(), body.get_chgUserPwd().get_password())) { NEWPKIerr(PKI_ERROR_TXT, ERROR_ABORT); return false; } return true; } bool Entity_SERVER::ChangePassword(COMMAND_PARAMETERS) { if(!hUser) { NEWPKIerr(PKI_ERROR_TXT, ERROR_NOT_ALLOWED); return false; } if(!response.set_type(ADMIN_RESP_TYPE_NONE)) { NEWPKIerr(PKI_ERROR_TXT, ERROR_ABORT); return false; } if(!Private_ChangeUserPassword(response, hUser, hUser.GetUserId(), body.get_chgPwd().get_password())) { NEWPKIerr(PKI_ERROR_TXT, ERROR_ABORT); return false; } return true; } bool Entity_SERVER::Private_ChangeUserPassword(AdminResponseBody & response, const UserHandle & hUser, unsigned long user_id, const mString & NewPassword) { SQL sql(m_DbConn); mString req; PKI_PASSWD pwd; char * password; if(!NewPassword.size()) { NEWPKIerr(PKI_ERROR_TXT, ERROR_BAD_PARAM); return false; } // Users can change their own password if(user_id != hUser.GetUserId()) { //Only default admin can change his password ! if(user_id == DEFAULT_ADMIN_ID && hUser.GetUserId() != DEFAULT_ADMIN_ID) { NEWPKIerr(PKI_ERROR_TXT, ERROR_NOT_ALLOWED); return false; } } password = pwd.CalcSHA1Password(NewPassword); if(!password) { NEWPKIerr(PKI_ERROR_TXT, ERROR_UNKNOWN); return false; } if(req.sprintf(SQL_UPDATE_USER_PWD, password, user_id) <= 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_SERVER::InitEntity(COMMAND_PARAMETERS) { if(!hUser) { NEWPKIerr(PKI_ERROR_TXT, ERROR_NOT_ALLOWED); return false; } if(!body.get_initEntity().get_name().size()) { NEWPKIerr(PKI_ERROR_TXT, ERROR_BAD_PARAM); return false; } if(!response.set_type(ADMIN_RESP_TYPE_NONE)) { NEWPKIerr(PKI_ERROR_TXT, ERROR_ABORT); return false; } m_EntitiesLock.LockWrite(); if( m_EntitiesList.find(body.get_initEntity().get_name()) == m_EntitiesList.end() ) { m_EntitiesLock.UnlockWrite(); NEWPKIerr(PKI_ERROR_TXT, ERROR_UNKNOWN_ENTITY); return false; } if(!m_EntitiesList[body.get_initEntity().get_name()].entity) { m_EntitiesLock.UnlockWrite(); NEWPKIerr(PKI_ERROR_TXT, ERROR_ENTITY_NOT_READY); return false; } if(!m_EntitiesList[body.get_initEntity().get_name()].entity->Init(body.get_initEntity().get_signResp())) { m_EntitiesLock.UnlockWrite(); NEWPKIerr(PKI_ERROR_TXT, ERROR_ABORT); return false; } if(!m_EntitiesList[body.get_initEntity().get_name()].entity->Load()) { m_EntitiesLock.UnlockWrite(); NEWPKIerr(PKI_ERROR_TXT, ERROR_ABORT); return false; } m_EntitiesLock.UnlockWrite(); return true; } bool Entity_SERVER::Upgrade(const char * Version) { return true; } bool Entity_SERVER::ParseNewConf() { return true; } bool Entity_SERVER::Responder_TreatRequest(const NewpkiRequest & Request, const mString & SenderName, NewpkiResponse & Response) { return true; } bool Entity_SERVER::Responder_ValidateRequest(const NewpkiRequest & Request, const X509_PUBKEY * Requester, mString & SenderName) { return true; } bool Entity_SERVER::Requester_OnNewResponse(const Asn1OctetString & transactionID, const X509_PUBKEY * sender, const NewpkiResponse & Response) { return true; } bool Entity_SERVER::EntitySignResponse(AdminResponse & response) { Entity * entity; bool Ret; m_EntitiesLock.LockRead(); entity = GetEntity(); if(!entity) entity = this; entity->ClientEnter(); m_EntitiesLock.UnlockRead(); // If entity is not fully initialized I sign the response if(!entity->IsFullyInit()) { Ret = SignResponse(response); } else { Ret = entity->SignResponse(response); } entity->ClientLeave(); return Ret; } bool Entity_SERVER::OnNewOCSP(const char * Ip, const OCSP_REQUEST *request, OCSP_RESPONSE **response, const mString &EntityName, bool & ShouldStopServer) { bool Ret; if(EntityName == INITIAL_DB) { ShouldStopServer = true; return false; } ShouldStopServer = false; m_EntitiesLock.LockRead(); //We get the entity if(m_EntitiesList.find(EntityName) == m_EntitiesList.end()) { m_EntitiesLock.UnlockRead(); ShouldStopServer = true; return false; } if(!m_EntitiesList[EntityName].entity) { m_EntitiesLock.UnlockRead(); return false; } m_EntitiesList[EntityName].entity->ClientEnter(); m_EntitiesLock.UnlockRead(); if(m_EntitiesList[EntityName].Type != ENTITY_TYPE_PUBLICATION) { m_EntitiesList[EntityName].entity->ClientLeave(); ShouldStopServer = true; return false; } Ret = ((Entity_PUBLICATION*)m_EntitiesList[EntityName].entity)->OnNewOCSP(Ip, request, response); m_EntitiesList[EntityName].entity->ClientLeave(); return Ret; } void Entity_SERVER::SetOcspServersHandler(OcspServers *OcspServersHandler) { std::map::iterator i; m_OcspServersHandler = OcspServersHandler; m_EntitiesLock.LockRead(); for(i=m_EntitiesList.begin(); i != m_EntitiesList.end(); i++) { if(i->second.entity) { i->second.entity->ClientEnter(); if(i->second.Type != ENTITY_TYPE_PUBLICATION) { i->second.entity->ClientLeave(); continue; } ((Entity_PUBLICATION*)i->second.entity)->SetOcspServersHandler(OcspServersHandler); i->second.entity->ClientLeave(); } } m_EntitiesLock.UnlockRead(); } void Entity_SERVER::ThreadDeleteEntity(const NewpkiThread *Thread, void *param) { Entity_SERVER * me_this = (Entity_SERVER *)param; Entity * entity; while(!Thread->ShouldStop()) { me_this->m_DeleteEntitiesLock.EnterCS(); if(me_this->m_DeleteEntitiesList.size()) { entity = me_this->m_DeleteEntitiesList[0]; me_this->m_DeleteEntitiesList.erase(me_this->m_DeleteEntitiesList.begin()); me_this->m_DeleteEntitiesLock.LeaveCS(); if(entity) { entity->Destroy(); entity->WaitForNoClients(); delete entity; } } else { me_this->m_DeleteEntitiesLock.LeaveCS(); } NewpkiThread::Sleep(500); } } void Entity_SERVER::ThreadUnloadEntity(const NewpkiThread *Thread, void *param) { Entity_SERVER * me_this = (Entity_SERVER *)param; Entity * entity; while(!Thread->ShouldStop()) { me_this->m_UnloadEntitiesLock.EnterCS(); if(me_this->m_UnloadEntitiesList.size()) { entity = me_this->m_UnloadEntitiesList[0]; me_this->m_UnloadEntitiesList.erase(me_this->m_UnloadEntitiesList.begin()); me_this->m_UnloadEntitiesLock.LeaveCS(); if(entity) { entity->WaitForNoClients(); delete entity; } } else { me_this->m_UnloadEntitiesLock.LeaveCS(); } NewpkiThread::Sleep(500); } } bool Entity_SERVER::PrepareConfToWrite() { return true; } bool Entity_SERVER::EntityLoad(COMMAND_PARAMETERS) { if(!hUser) { NEWPKIerr(PKI_ERROR_TXT, ERROR_NOT_ALLOWED); return false; } if(!response.set_type(ADMIN_RESP_TYPE_NONE)) { NEWPKIerr(PKI_ERROR_TXT, ERROR_ABORT); return false; } if(!body.get_entityName().size()) { NEWPKIerr(PKI_ERROR_TXT, ERROR_BAD_PARAM); return false; } m_EntitiesLock.LockWrite(); if( m_EntitiesList.find(body.get_entityName()) == m_EntitiesList.end() ) { m_EntitiesLock.UnlockWrite(); NEWPKIerr(PKI_ERROR_TXT, ERROR_UNKNOWN_ENTITY); return false; } if(m_EntitiesList[body.get_entityName()].entity) { m_EntitiesLock.UnlockWrite(); return true; } if(! (m_EntitiesList[body.get_entityName()].entity = LoadEntity(body.get_entityName(), m_EntitiesList[body.get_entityName()].Type)) ) { m_EntitiesLock.UnlockWrite(); NEWPKIerr(PKI_ERROR_TXT, ERROR_ABORT); return false; } m_EntitiesLock.UnlockWrite(); return true; } bool Entity_SERVER::EntityUnload(COMMAND_PARAMETERS) { if(!hUser) { NEWPKIerr(PKI_ERROR_TXT, ERROR_NOT_ALLOWED); return false; } if(!response.set_type(ADMIN_RESP_TYPE_NONE)) { NEWPKIerr(PKI_ERROR_TXT, ERROR_ABORT); return false; } if(!body.get_entityName().size()) { NEWPKIerr(PKI_ERROR_TXT, ERROR_BAD_PARAM); return false; } m_EntitiesLock.LockWrite(); if( m_EntitiesList.find(body.get_entityName()) == m_EntitiesList.end() ) { m_EntitiesLock.UnlockWrite(); NEWPKIerr(PKI_ERROR_TXT, ERROR_UNKNOWN_ENTITY); return false; } if(!m_EntitiesList[body.get_entityName()].entity) { m_EntitiesLock.UnlockWrite(); return true; } // Entity get removed from memory in another // thread, this avoids having deadlocks in a // user function m_UnloadEntitiesLock.EnterCS(); m_UnloadEntitiesList.push_back(m_EntitiesList[body.get_entityName()].entity); m_UnloadEntitiesLock.LeaveCS(); m_EntitiesList[body.get_entityName()].entity = NULL; m_EntitiesLock.UnlockWrite(); return true; }