IBR-DTNSuite  0.8
daemon/src/security/SecurityManager.cpp
Go to the documentation of this file.
00001 #include "security/SecurityManager.h"
00002 #include "security/SecurityKeyManager.h"
00003 #include "core/BundleCore.h"
00004 #include "routing/QueueBundleEvent.h"
00005 #include <ibrcommon/Logger.h>
00006 
00007 #include <openssl/rsa.h>
00008 #include <openssl/pem.h>
00009 #include <openssl/err.h>
00010 
00011 #ifdef __DEVELOPMENT_ASSERTIONS__
00012 #include <cassert>
00013 #endif
00014 
00015 namespace dtn
00016 {
00017         namespace security
00018         {
00019                 SecurityManager& SecurityManager::getInstance()
00020                 {
00021                         static SecurityManager sec_man;
00022                         return sec_man;
00023                 }
00024 
00025                 SecurityManager::SecurityManager()
00026                 : _accept_only_bab(false), _accept_only_pib(false)
00027                 {
00028                 }
00029 
00030                 SecurityManager::~SecurityManager()
00031                 {
00032                 }
00033 
00034                 void SecurityManager::auth(dtn::data::Bundle &bundle) const throw (KeyMissingException)
00035                 {
00036                         IBRCOMMON_LOGGER_DEBUG(10) << "auth bundle: " << bundle.toString() << IBRCOMMON_LOGGER_ENDL;
00037 
00038                         try {
00039                                 // try to load the local key
00040                                 const SecurityKey key = SecurityKeyManager::getInstance().get(dtn::core::BundleCore::local, SecurityKey::KEY_SHARED);
00041 
00042                                 // sign the bundle with BABs
00043                                 dtn::security::BundleAuthenticationBlock::auth(bundle, key);
00044                         } catch (const SecurityKeyManager::KeyNotFoundException &ex) {
00045                                 throw KeyMissingException(ex.what());
00046                         }
00047                 }
00048 
00049                 void SecurityManager::sign(dtn::data::Bundle &bundle) const throw (KeyMissingException)
00050                 {
00051                         IBRCOMMON_LOGGER_DEBUG(10) << "sign bundle: " << bundle.toString() << IBRCOMMON_LOGGER_ENDL;
00052 
00053                         try {
00054                                 // try to load the local key
00055                                 const SecurityKey key = SecurityKeyManager::getInstance().get(dtn::core::BundleCore::local, SecurityKey::KEY_PRIVATE);
00056 
00057                                 // sign the bundle with PIB
00058                                 dtn::security::PayloadIntegrityBlock::sign(bundle, key, bundle._destination.getNode());
00059                         } catch (const SecurityKeyManager::KeyNotFoundException &ex) {
00060                                 throw KeyMissingException(ex.what());
00061                         }
00062                 }
00063 
00064                 void SecurityManager::prefetchKey(const dtn::data::EID &eid)
00065                 {
00066                         IBRCOMMON_LOGGER_DEBUG(10) << "prefetch key for: " << eid.getString() << IBRCOMMON_LOGGER_ENDL;
00067 
00068                         // prefetch the key for this EID
00069                         SecurityKeyManager::getInstance().prefetchKey(eid, SecurityKey::KEY_PUBLIC);
00070                 }
00071 
00072                 void SecurityManager::verify(dtn::data::Bundle &bundle) const throw (VerificationFailedException)
00073                 {
00074                         verifyBAB(bundle);
00075                         verifyPIB(bundle);
00076                 }
00077 
00078                 void SecurityManager::verifyPIB(dtn::data::Bundle &bundle) const throw (VerificationFailedException)
00079                 {
00080                         IBRCOMMON_LOGGER_DEBUG(10) << "verify signed bundle: " << bundle.toString() << IBRCOMMON_LOGGER_ENDL;
00081 
00082                         // get all PIBs of this bundle
00083                         std::list<const dtn::security::PayloadIntegrityBlock*> pibs = bundle.getBlocks<dtn::security::PayloadIntegrityBlock>();
00084 
00085                         for (std::list<const dtn::security::PayloadIntegrityBlock*>::iterator it = pibs.begin(); it != pibs.end(); it++)
00086                         {
00087                                 const dtn::security::PayloadIntegrityBlock& pib = (**it);
00088 
00089                                 try {
00090                                         const SecurityKey key = SecurityKeyManager::getInstance().get(pib.getSecuritySource(bundle), SecurityKey::KEY_PUBLIC);
00091 
00092                                         if (pib.isSecurityDestination(bundle, dtn::core::BundleCore::local))
00093                                         {
00094                                                 try {
00095                                                         dtn::security::PayloadIntegrityBlock::strip(bundle, key);
00096 
00097                                                         // set the verify bit, after verification
00098                                                         bundle.set(dtn::data::Bundle::DTNSEC_STATUS_VERIFIED, true);
00099 
00100                                                         IBRCOMMON_LOGGER_DEBUG(5) << "Bundle from " << bundle._source.getString() << " successfully verified using PayloadIntegrityBlock" << IBRCOMMON_LOGGER_ENDL;
00101                                                         return;
00102                                                 } catch (const ibrcommon::Exception&) {
00103                                                         throw VerificationFailedException();
00104                                                 }
00105                                         }
00106                                         else
00107                                         {
00108                                                 try {
00109                                                         dtn::security::PayloadIntegrityBlock::verify(bundle, key);
00110 
00111                                                         // set the verify bit, after verification
00112                                                         bundle.set(dtn::data::Bundle::DTNSEC_STATUS_VERIFIED, true);
00113 
00114                                                         IBRCOMMON_LOGGER_DEBUG(5) << "Bundle from " << bundle._source.getString() << " successfully verified using PayloadIntegrityBlock" << IBRCOMMON_LOGGER_ENDL;
00115                                                 } catch (const ibrcommon::Exception&) {
00116                                                         throw VerificationFailedException();
00117                                                 }
00118                                         }
00119                                 } catch (const ibrcommon::Exception&) {
00120                                         // key not found?
00121                                 }
00122                         }
00123                 }
00124 
00125                 void SecurityManager::verifyBAB(dtn::data::Bundle &bundle) const throw (VerificationFailedException)
00126                 {
00127                         IBRCOMMON_LOGGER_DEBUG(10) << "verify authenticated bundle: " << bundle.toString() << IBRCOMMON_LOGGER_ENDL;
00128 
00129                         // get all BABs of this bundle
00130                         std::list <const dtn::security::BundleAuthenticationBlock* > babs = bundle.getBlocks<dtn::security::BundleAuthenticationBlock>();
00131 
00132                         for (std::list <const dtn::security::BundleAuthenticationBlock* >::iterator it = babs.begin(); it != babs.end(); it++)
00133                         {
00134                                 const dtn::security::BundleAuthenticationBlock& bab = (**it);
00135 
00136                                 // look for the right BAB-factory
00137                                 const dtn::data::EID node = bab.getSecuritySource(bundle);
00138 
00139                                 try {
00140                                         // try to load the key of the BAB
00141                                         const SecurityKey key = SecurityKeyManager::getInstance().get(node, SecurityKey::KEY_SHARED);
00142 
00143                                         // verify the bundle
00144                                         dtn::security::BundleAuthenticationBlock::verify(bundle, key);
00145 
00146                                         // strip all BAB of this bundle
00147                                         dtn::security::BundleAuthenticationBlock::strip(bundle);
00148 
00149                                         // set the verify bit, after verification
00150                                         bundle.set(dtn::data::Bundle::DTNSEC_STATUS_AUTHENTICATED, true);
00151 
00152                                         // at least one BAB has been authenticated, we're done!
00153                                         break;
00154                                 } catch (const SecurityKeyManager::KeyNotFoundException&) {
00155                                         // no key for this node found
00156                                 } catch (const ibrcommon::Exception &ex) {
00157                                         // verification failed
00158                                         throw SecurityManager::VerificationFailedException(ex.what());
00159                                 }
00160                         }
00161                 }
00162 
00163                 void SecurityManager::fastverify(const dtn::data::Bundle &bundle) const throw (VerificationFailedException)
00164                 {
00165                         // do a fast verify without manipulating the bundle
00166                         const dtn::daemon::Configuration::Security &secconf = dtn::daemon::Configuration::getInstance().getSecurity();
00167 
00168                         if (secconf.getLevel() & dtn::daemon::Configuration::Security::SECURITY_LEVEL_ENCRYPTED)
00169                         {
00170                                 // check if the bundle is encrypted and throw an exception if not
00171                                 //throw VerificationFailedException("Bundle is not encrypted");
00172                                 IBRCOMMON_LOGGER_DEBUG(10) << "encryption required, verify bundle: " << bundle.toString() << IBRCOMMON_LOGGER_ENDL;
00173 
00174                                 const std::list<const dtn::security::PayloadConfidentialBlock* > pcbs = bundle.getBlocks<dtn::security::PayloadConfidentialBlock>();
00175                                 if (pcbs.size() == 0) throw VerificationFailedException("No PCB available!");
00176                         }
00177 
00178                         if (secconf.getLevel() & dtn::daemon::Configuration::Security::SECURITY_LEVEL_AUTHENTICATED)
00179                         {
00180                                 // check if the bundle is signed and throw an exception if not
00181                                 //throw VerificationFailedException("Bundle is not signed");
00182                                 IBRCOMMON_LOGGER_DEBUG(10) << "authentication required, verify bundle: " << bundle.toString() << IBRCOMMON_LOGGER_ENDL;
00183 
00184                                 const std::list<const dtn::security::BundleAuthenticationBlock* > babs = bundle.getBlocks<dtn::security::BundleAuthenticationBlock>();
00185                                 if (babs.size() == 0) throw VerificationFailedException("No BAB available!");
00186                         }
00187                 }
00188 
00189                 void SecurityManager::decrypt(dtn::data::Bundle &bundle) const throw (DecryptException, KeyMissingException)
00190                 {
00191                         // check if the bundle has to be decrypted, return when not
00192                         if (bundle.getBlocks<dtn::security::PayloadConfidentialBlock>().size() <= 0) return;
00193 
00194                         // decrypt
00195                         try {
00196                                 IBRCOMMON_LOGGER_DEBUG(10) << "decrypt bundle: " << bundle.toString() << IBRCOMMON_LOGGER_ENDL;
00197 
00198                                 // get the encryption key
00199                                 dtn::security::SecurityKey key = SecurityKeyManager::getInstance().get(dtn::core::BundleCore::local, dtn::security::SecurityKey::KEY_PRIVATE);
00200 
00201                                 // encrypt the payload of the bundle
00202                                 dtn::security::PayloadConfidentialBlock::decrypt(bundle, key);
00203 
00204                                 bundle.set(dtn::data::Bundle::DTNSEC_STATUS_CONFIDENTIAL, true);
00205                         } catch (const ibrcommon::Exception &ex) {
00206                                 throw DecryptException(ex.what());
00207                         }
00208                 }
00209 
00210                 void SecurityManager::encrypt(dtn::data::Bundle &bundle) const throw (EncryptException, KeyMissingException)
00211                 {
00212                         try {
00213                                 IBRCOMMON_LOGGER_DEBUG(10) << "encrypt bundle: " << bundle.toString() << IBRCOMMON_LOGGER_ENDL;
00214 
00215                                 // get the encryption key
00216                                 dtn::security::SecurityKey key = SecurityKeyManager::getInstance().get(bundle._destination, dtn::security::SecurityKey::KEY_PUBLIC);
00217 
00218                                 // encrypt the payload of the bundle
00219                                 dtn::security::PayloadConfidentialBlock::encrypt(bundle, key, dtn::core::BundleCore::local);
00220                         } catch (const ibrcommon::Exception &ex) {
00221                                 throw EncryptException(ex.what());
00222                         }
00223                 }
00224         }
00225 }