r3362 - in trunk/libmcrypto: include/libmcrypto include/libmcrypto/gnutls include/libmcrypto/openssl source
mikaelsv at minisip.org
mikaelsv at minisip.org
Mon Aug 13 10:11:04 CEST 2007
Author: mikaelsv
Date: 2007-08-13 10:11:03 +0200 (Mon, 13 Aug 2007)
New Revision: 3362
Modified:
trunk/libmcrypto/include/libmcrypto/CacheManager.h
trunk/libmcrypto/include/libmcrypto/CertificateFinder.h
trunk/libmcrypto/include/libmcrypto/cert.h
trunk/libmcrypto/include/libmcrypto/gnutls/cert.h
trunk/libmcrypto/include/libmcrypto/openssl/cert.h
trunk/libmcrypto/source/CacheManager.cxx
trunk/libmcrypto/source/CertificateFinder.cxx
trunk/libmcrypto/source/CertificatePathFinderUcd.cxx
trunk/libmcrypto/source/cert.cxx
Log:
* Added support for certificate cache and "failed preivous certificate look-up cache".
Both these features are enabled at compile time using two different constants.
(This revision contains a lot of debug output, but it will eventually be removed)
Modified: trunk/libmcrypto/include/libmcrypto/CacheManager.h
===================================================================
--- trunk/libmcrypto/include/libmcrypto/CacheManager.h 2007-08-13 08:05:50 UTC (rev 3361)
+++ trunk/libmcrypto/include/libmcrypto/CacheManager.h 2007-08-13 08:11:03 UTC (rev 3362)
@@ -25,19 +25,30 @@
#define _CACHEMANAGER_H_
#include <libmcrypto/config.h>
+#include <libmutil/MemObject.h>
#include <libmcrypto/cert.h>
-#include <libmutil/MemObject.h>
#include <libmutil/CacheItem.h>
#include <libmnetutil/DirectorySet.h>
#include <libmnetutil/DirectorySetItem.h>
#include <string>
#include <map>
+#include <list>
+#include <vector>
+#define CACHEMANAGER_CERTSET_DOWNLOADED "downloadedcerts"
#define CACHEMANAGER_CERTSET_ROOTCAS "rootcas"
#define CACHEMANAGER_DIRSET_MAIN "main"
+class LIBMCRYPTO_API CertFindSettings : public MObject {
+ public:
+ CertFindSettings(const std::string s, const std::string i) : searchText(s), issuer(i) {}
+ //CertFindSettings();
+ std::string searchText;
+ std::string issuer;
+};
+
class LIBMCRYPTO_API CacheManager : public MObject {
public:
CacheManager();
@@ -92,13 +103,43 @@
* the function will match the URI against the certificate's subjectAltNames.
* Otherwise (if the parameter is not a SIP URI) the subject field is matched.
*/
- std::vector<MRef<Certificate*> > findCertificate(const std::string searchText, const std::string issuer);
+ std::vector<MRef<Certificate*> > findCertificates(const std::string searchText, const std::string issuer, const std::string defaultSet = "");
+
+ void addCertificateSet(const MRef<CertificateSet*> certSet, const std::string setKey);
+ std::string addCertificate(const MRef<Certificate*> certItem, std::string setKey);
+
+ bool findCertsFailedBefore(const std::string searchText, const std::string issuer);
+ void addFindCertsFailed(const std::string searchText, const std::string issuer);
+
private:
- std::string getNewDirectoryKey() const;
+ std::string getNewDirectorySetKey() const;
+ std::string getNewCertificateSetKey() const;
+ //std::string test;
+
std::map<std::string, MRef<DirectorySet*> > directorySets;
+ std::map<std::string, MRef<CertificateSet*> > certificateSets;
+ //std::map<std::string, MRef<CertificateSet*> > certificateSets2;
+ std::list<MRef<CertFindSettings*> > failedCertSearches;
- std::vector<MRef<Certificate*> > fakeCache;
+ //std::vector<MRef<Certificate*> > fakeCache;
+ //std::string test;
+ //int test;
+ /*
+ int a;
+ int b;
+ int c;
+ int d;
+ int e;
+ int f;
+ int g;
+ int h;
+ int i;
+ int j;
+ int k;
+ int l;
+ int m;
+ */
};
#endif
Modified: trunk/libmcrypto/include/libmcrypto/CertificateFinder.h
===================================================================
--- trunk/libmcrypto/include/libmcrypto/CertificateFinder.h 2007-08-13 08:05:50 UTC (rev 3361)
+++ trunk/libmcrypto/include/libmcrypto/CertificateFinder.h 2007-08-13 08:11:03 UTC (rev 3362)
@@ -40,6 +40,17 @@
#define MAX_EFFORT -1
#endif
+/* Don't cache any certificates, don't even try to use the cache */
+#define CERTCACHEUSE_NONE 0
+/* Cache only certificates in the path, no irrelevant certificates */
+#define CERTCACHEUSE_LOW 1
+/* Cache all downloaded certificates */
+#define CERTCACHEUSE_NORMAL 2
+/* The constant used to determine the cache level */
+#define USE_CERTIFICATE_CACHE CERTCACHEUSE_NORMAL
+
+#define USE_FINDCERTSFAILED_CACHE 0
+
class LIBMCRYPTO_API CertificateFinderStats : public MObject {
public:
Modified: trunk/libmcrypto/include/libmcrypto/cert.h
===================================================================
--- trunk/libmcrypto/include/libmcrypto/cert.h 2007-08-13 08:05:50 UTC (rev 3361)
+++ trunk/libmcrypto/include/libmcrypto/cert.h 2007-08-13 08:11:03 UTC (rev 3362)
@@ -191,9 +191,19 @@
static CertificateSet *create();
virtual CertificateSet* clone();
+
void addDirectory( std::string dir );
MRef<CertificateSetItem*> addFile( std::string file );
virtual MRef<CertificateSetItem*> addCertificate( MRef<Certificate *> cert );
+
+ /**
+ * Returns the certificates within the set "matching the parameter \p searchFor".
+ *
+ * A certificate is considered to match the query if the subject or any of the
+ * subject alternative names contain the text \p searchFor.
+ */
+ std::vector<MRef<CertificateSetItem*> > findItems(const std::string searchFor, const std::string issuer = "");
+
virtual std::list<MRef<CertificateSetItem*> > &getItems();
virtual MRef<CertificateSetItem*> getNext();
virtual void initIndex();
Modified: trunk/libmcrypto/include/libmcrypto/gnutls/cert.h
===================================================================
--- trunk/libmcrypto/include/libmcrypto/gnutls/cert.h 2007-08-13 08:05:50 UTC (rev 3361)
+++ trunk/libmcrypto/include/libmcrypto/gnutls/cert.h 2007-08-13 08:11:03 UTC (rev 3362)
@@ -159,6 +159,8 @@
std::string getIssuer();
std::string getIssuerCn();
+ bool verifySignedBy(MRef<Certificate*> cert);
+
gnutls_x509_crt_t getCertificate(){return cert;};
protected:
Modified: trunk/libmcrypto/include/libmcrypto/openssl/cert.h
===================================================================
--- trunk/libmcrypto/include/libmcrypto/openssl/cert.h 2007-08-13 08:05:50 UTC (rev 3361)
+++ trunk/libmcrypto/include/libmcrypto/openssl/cert.h 2007-08-13 08:11:03 UTC (rev 3362)
@@ -135,6 +135,8 @@
std::string getIssuer();
std::string getIssuerCn();
+ bool verifySignedBy(MRef<Certificate*> cert);
+
X509 * getOpensslCertificate(){return cert;};
private:
X509 * cert;
Modified: trunk/libmcrypto/source/CacheManager.cxx
===================================================================
--- trunk/libmcrypto/source/CacheManager.cxx 2007-08-13 08:05:50 UTC (rev 3361)
+++ trunk/libmcrypto/source/CacheManager.cxx 2007-08-13 08:11:03 UTC (rev 3362)
@@ -35,6 +35,7 @@
CacheManager::CacheManager() {
std::cerr << "^^^ Start of " << __FUNCTION__ << std::endl;
+ /*
Certificate* cert;
std::stack<std::string> certFiles;
@@ -51,14 +52,13 @@
certFiles.pop();
}
+ */
}
MRef<DirectorySetItem*> CacheManager::findDirectory(const std::string domain, const std::string defaultSet) {
std::cerr << "^^^ Start of " << __FUNCTION__ << std::endl;
std::vector<MRef<DirectorySetItem*> > res;
if (defaultSet.length() == 0) {
// Scan all directory sets
- //std::map<const std::string, MRef<DirectorySet*> >::iterator i = directorySets.begin();
- //while (i != directorySets.end()) {
for (std::map<const std::string, MRef<DirectorySet*> >::iterator i = directorySets.begin(); i != directorySets.end(); i++) {
res = i->second->findItemsPrioritized(domain);
if (!res.empty())
@@ -87,7 +87,7 @@
std::string CacheManager::addDirectory(const MRef<DirectorySetItem*> dirItem, std::string setKey) {
std::cerr << "^^^ Start of " << __FUNCTION__ << std::endl;
if (0 == setKey.length()) {
- setKey = getNewDirectoryKey();
+ setKey = getNewDirectorySetKey();
}
if (directorySets.find(setKey) == directorySets.end()) {
directorySets[setKey] = MRef<DirectorySet*>(new DirectorySet());
@@ -98,13 +98,13 @@
std::string CacheManager::addDirectoryLdap(std::string url, std::string subTree, const std::string setKey) {
std::cerr << "^^^ Start of " << __FUNCTION__ << std::endl;
- return addDirectory(MRef<DirectorySetItem*>(new DirectorySetItem(url, subTree)), setKey != "" ? setKey : getNewDirectoryKey());
+ return addDirectory(MRef<DirectorySetItem*>(new DirectorySetItem(url, subTree)), setKey != "" ? setKey : getNewDirectorySetKey());
}
//void CacheManager::purgeCache();
//void CacheManager::removeFromCache(MRef<CacheItem*> item);
-std::string CacheManager::getNewDirectoryKey() const {
+std::string CacheManager::getNewDirectorySetKey() const {
std::cerr << "^^^ Start of " << __FUNCTION__ << std::endl;
std::string newName = "dirset";
int num = 1;
@@ -112,14 +112,55 @@
num++;
return newName;
}
+std::string CacheManager::getNewCertificateSetKey() const {
+ std::cerr << "^^^ Start of " << __FUNCTION__ << std::endl;
+ std::string newName = "certset";
+ int num = 1;
+ while (certificateSets.find(newName + itoa(num)) != certificateSets.end())
+ num++;
+ return newName;
+}
/**
+ * @note If a certificate has been index and unloaded from memory, this function will indirectly
+ * (through its use of CertificateSetItem.getCertificate()) try to load the certifcate
+ * once more. This may entain downloading the certificate from a remote host.
* @todo Subject and Issuer should NOT be used to identify certificates. Use *KeyIdentifier (?) and ??? instead.
*/
-std::vector<MRef<Certificate*> > CacheManager::findCertificate(const std::string searchText, const std::string issuer) {
+std::vector<MRef<Certificate*> > CacheManager::findCertificates(const std::string searchText, const std::string issuer, const std::string defaultSet) {
std::cerr << "^^^ Start of " << __FUNCTION__ << std::endl;
+ std::vector<MRef<CertificateSetItem*> > tempRes;
std::vector<MRef<Certificate*> > res;
+ std::vector<MRef<CertificateSetItem*> >::iterator iRes;
+
+ if (defaultSet.length() == 0) {
+ // Scan all directory sets
+ for (std::map<const std::string, MRef<CertificateSet*> >::iterator i = certificateSets.begin(); i != certificateSets.end(); i++) {
+ tempRes = i->second->findItems(searchText, issuer);
+ if (!tempRes.empty()) {
+ for (iRes = tempRes.begin(); iRes != tempRes.end(); iRes++) {
+ res.push_back((*iRes)->getCertificate());
+ }
+ }
+ }
+
+ } else {
+ // Scan only one directory set, the one mentioned in the function parameters.
+ if (certificateSets.find(defaultSet) != certificateSets.end()) {
+ tempRes = certificateSets[defaultSet]->findItems(searchText, issuer);
+ if (!tempRes.empty()) {
+ for (iRes = tempRes.begin(); iRes != tempRes.end(); iRes++) {
+ res.push_back((*iRes)->getCertificate());
+ }
+ }
+ }
+ }
+ // Return empty item if no result found
+ return res;
+
+ /*
+ std::vector<MRef<Certificate*> > res;
SipUri uri(searchText);
for (std::vector<MRef<Certificate*> >::iterator i = fakeCache.begin(); i != fakeCache.end(); i++) {
if (uri.isValid()) {
@@ -133,4 +174,37 @@
}
}
return res;
+ */
}
+
+void CacheManager::addCertificateSet(const MRef<CertificateSet*> certSet, const std::string setKey) {
+ if (certificateSets.find(setKey) == certificateSets.end()) {
+ certificateSets[setKey] = CertificateSet::create();
+ }
+ certificateSets[setKey] = certSet;
+}
+
+std::string CacheManager::addCertificate(const MRef<Certificate*> cert, std::string setKey) {
+ std::cerr << "^^^ Start of " << __FUNCTION__ << std::endl;
+ if (0 == setKey.length()) {
+ setKey = getNewCertificateSetKey();
+ }
+ if (certificateSets.find(setKey) == certificateSets.end()) {
+ certificateSets[setKey] = CertificateSet::create();
+ }
+ certificateSets[setKey]->addCertificate(cert);
+ return setKey;
+}
+
+
+bool CacheManager::findCertsFailedBefore(const std::string searchText, const std::string issuer) {
+ for (std::list<MRef<CertFindSettings*> >::iterator i = failedCertSearches.begin(); i != failedCertSearches.end(); i++) {
+ if ((*i)->searchText == searchText && (*i)->issuer == issuer)
+ return true;
+ }
+ return false;
+}
+void CacheManager::addFindCertsFailed(const std::string searchText, const std::string issuer) {
+ failedCertSearches.push_back(MRef<CertFindSettings*>(new CertFindSettings(searchText, issuer)));
+ std::cerr << "Look-up failure using (" << searchText <<", "<<issuer << std::endl;
+}
Modified: trunk/libmcrypto/source/CertificateFinder.cxx
===================================================================
--- trunk/libmcrypto/source/CertificateFinder.cxx 2007-08-13 08:05:50 UTC (rev 3361)
+++ trunk/libmcrypto/source/CertificateFinder.cxx 2007-08-13 08:11:03 UTC (rev 3362)
@@ -68,16 +68,29 @@
std::string issuer = curCert->getName();
/*
+ Test to see if this query has failed before. If so, abort immediately.
+ */
+ if (USE_FINDCERTSFAILED_CACHE) {
+ if (cacheManager->findCertsFailedBefore(subjectUri, issuer)) {
+ effort=MAX_EFFORT;
+ return std::vector<MRef<Certificate*> >();
+ }
+ }
+ /*
Scan the local certificate cache
*/
if (effort == 0){
- stats->cacheQueries++;
- ret = cacheManager->findCertificate(subjectUri, issuer);
- std::cerr << " Found certificates in local cache: " << ret.size() << std::endl;
- if (!ret.empty()){
- return ret;
+ if (USE_CERTIFICATE_CACHE != CERTCACHEUSE_NONE) {
+ stats->cacheQueries++;
+ ret = cacheManager->findCertificates(subjectUri, issuer);
+ std::cerr << " Found certificates in local cache: " << ret.size() << std::endl;
+ if (!ret.empty()){
+ return ret;
+ } else {
+ stats->cacheQueriesNoResult++;
+ effort = 1;
+ }
} else {
- stats->cacheQueriesNoResult++;
effort = 1;
}
}
@@ -146,6 +159,9 @@
return ret;
}
}
+ if (USE_FINDCERTSFAILED_CACHE) {
+ cacheManager->addFindCertsFailed(subjectUri, issuer);
+ }
effort=MAX_EFFORT;
return std::vector<MRef<Certificate*> >();
@@ -282,7 +298,7 @@
certs = (*iter)->getAttrValuesBinary("userCertificate;binary");
}
- Certificate* cert;
+ MRef<Certificate*> cert;
/*
Load/parse each retrieved certificate and test if they match the conditions.
@@ -294,7 +310,7 @@
if (stats != NULL) stats->certsProcessed++;
std::cerr << " Found binary attribute in LDAP database" << std::endl;
- if (NULL != cert) {
+ if (!cert.isNull()) {
if (stats != NULL) stats->ldapCertsDownloaded++;
std::cerr << " Found certificate in LDAP database" << std::endl;
@@ -313,8 +329,21 @@
*/
if (stats != NULL) stats->certsUseful++;
std::cerr << " Found MATCHING certificate in LDAP database" << std::endl;
- res.push_back(MRef<Certificate*>(cert));
+ if (USE_CERTIFICATE_CACHE == CERTCACHEUSE_LOW) {
+ std::vector<MRef<Certificate*> > temp = cacheManager->findCertificates(cert->getName(), cert->getIssuer(), CACHEMANAGER_CERTSET_DOWNLOADED);
+ if (temp.size() == 0) {
+ cacheManager->addCertificate(cert, CACHEMANAGER_CERTSET_DOWNLOADED);
+ }
+ }
+ res.push_back(cert);
}
+
+ if (USE_CERTIFICATE_CACHE == CERTCACHEUSE_NORMAL) {
+ std::vector<MRef<Certificate*> > temp = cacheManager->findCertificates(cert->getName(), cert->getIssuer(), CACHEMANAGER_CERTSET_DOWNLOADED);
+ if (temp.size() == 0) {
+ cacheManager->addCertificate(cert, CACHEMANAGER_CERTSET_DOWNLOADED);
+ }
+ }
}
}
}
Modified: trunk/libmcrypto/source/CertificatePathFinderUcd.cxx
===================================================================
--- trunk/libmcrypto/source/CertificatePathFinderUcd.cxx 2007-08-13 08:05:50 UTC (rev 3361)
+++ trunk/libmcrypto/source/CertificatePathFinderUcd.cxx 2007-08-13 08:11:03 UTC (rev 3362)
@@ -463,8 +463,15 @@
*/
bool CertificatePathFinderUcd::verifyLastPair(std::vector<MRef<Certificate*> > & certList) {
std::cerr << "^^^ Start of " << __FUNCTION__ << std::endl;
+ bool res = true;
+ if (certList.size() > 1) {
+ MRef<Certificate*> last = certList[certList.size()-1];
+ MRef<Certificate*> secondToLast = certList[certList.size()-2];
+ std::cerr << " Verifying if " << last->getName() << " was signed by " << secondToLast->getName() << std::endl;
+ res = last->verifySignedBy(secondToLast);
+ }
std::cerr << "$$$ End of " << __FUNCTION__ << std::endl;
- return true;
+ return res;
}
void CertificatePathFinderUcd::printStats(std::string prefix, std::string timeStampFile) {
Modified: trunk/libmcrypto/source/cert.cxx
===================================================================
--- trunk/libmcrypto/source/cert.cxx 2007-08-13 08:05:50 UTC (rev 3361)
+++ trunk/libmcrypto/source/cert.cxx 2007-08-13 08:11:03 UTC (rev 3362)
@@ -123,7 +123,6 @@
return m_pk->privateDecrypt( data, size, retdata, retsize );
}
-
bool Certificate::verifySignedBy( MRef<Certificate*> cert ){
massert(cert);
MRef<CertificateSet*> set = CertificateSet::create();;
@@ -131,7 +130,6 @@
return control(*set);
}
-
bool Certificate::hasPk(){
return !m_pk.isNull();
}
@@ -242,15 +240,14 @@
void CertificateSetItem::reindexCert() {
if (!certificate.isNull()) {
- std::cerr << "REINDEX CERTIFICATE" << std::endl;
+ //std::cerr << "REINDEX CERTIFICATE" << std::endl;
subject = certificate->getName();
- std::cerr << " " << subject << std::endl;
+ //std::cerr << " " << subject << std::endl;
- std::vector<std::string> subjectAltNames;
-
Certificate::SubjectAltName altTypes[] = {Certificate::SAN_DNSNAME, Certificate::SAN_RFC822NAME, Certificate::SAN_URI, Certificate::SAN_IPADDRESS};
for (int i=0; i < 4; i++) {
std::vector<std::string> tempNames = certificate->getAltName(altTypes[i]);
+ //std::cerr << "Found " << tempNames.size() << " alternative names in certificate." << std::endl;
subjectAltNames.insert(subjectAltNames.end(), tempNames.begin(), tempNames.end());
}
@@ -298,13 +295,51 @@
mLock.unlock();
}
+std::vector<MRef<CertificateSetItem*> > CertificateSet::findItems(const std::string searchFor, const std::string issuer) {
+ initIndex();
+
+ std::vector<MRef<CertificateSetItem*> > res;
+ MRef<CertificateSetItem*> item;
+ while( items_index != items.end() ){
+ item = (*items_index);
+ //std::cerr << "findItems: testing " << item->getSubject() << std::endl;
+ // If an issuer has been specified and this certificate has another issuer then the certificate is not a match.
+ if (issuer == "" || item->getIssuer() == issuer) {
+ if (searchFor != "") {
+ if (item->getSubject() == searchFor) {
+ // Certificate subject matches "search condition"
+ res.push_back(item);
+ } else {
+ std::vector<std::string> altNames = item->getSubjectAltNames();
+ //std::cerr << "findItems: number of subjectAltNames is " << altNames.size() << std::endl;
+ for (std::vector<std::string>::iterator i = altNames.begin(); i != altNames.end(); i++) {
+ if ((*i) == searchFor) {
+ std::cerr << "findItems: found matching subjectAltName " << (*i) << " in certificates issued to " << item->getSubject() << std::endl;
+ // Certificate subject alternative name matches "search condition"
+ res.push_back(item);
+ break;
+ }
+ }
+ }
+ } else {
+ res.push_back(item);
+ }
+ }
+ items_index++;
+ }
+ initIndex();
+ return res;
+}
+
void CertificateSet::addDirectory(std::string dir) {
std::list<std::string> certs = FileSystemUtils::directoryContents(dir, false);
for (std::list<std::string>::iterator i = certs.begin(); i != certs.end(); i++) {
- std::cerr << "File: " << *i << std::endl;
+ //std::cerr << "File: " << *i << std::endl;
MRef<CertificateSetItem*> item = addFile(*i);
- item->setImportMethod(CertificateSetItem::IMPORTMETHOD_DIRECTORY);
- item->setImportParameter(dir);
+ if (!item.isNull()) {
+ item->setImportMethod(CertificateSetItem::IMPORTMETHOD_DIRECTORY);
+ item->setImportParameter(dir);
+ }
}
}
MRef<CertificateSetItem*> CertificateSet::addFile(std::string file) {
@@ -316,8 +351,10 @@
item->setCertificateUri(uri.getString());
item->setImportMethod(CertificateSetItem::IMPORTMETHOD_FILE);
item->setImportParameter(uri.getString());
+ return item;
} catch (CertificateException & ex) {
}
+ return MRef<CertificateSetItem*>();
}
void CertificateSet::addItem( MRef<CertificateSetItem*> item ){
@@ -348,8 +385,8 @@
//item->item = "";
//item->type = CERT_DB_ITEM_TYPE_OTHER;
- item->setCertificate(cert);
- item->reindexCert();
+ //item->setCertificate(cert);
+ //item->reindexCert();
return item;
}
/*
More information about the Minisip-devel
mailing list