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