[Box Backup-commit] COMMIT r2787 - in box/invisnet/vs2010/0.11: bin/bbackupd bin/bbackupd/win32 lib/backupclient lib/server

subversion at boxbackup.org subversion at boxbackup.org
Sun Oct 10 00:36:01 BST 2010


Author: invisnet
Date: 2010-10-10 00:36:00 +0100 (Sun, 10 Oct 2010)
New Revision: 2787

Modified:
   box/invisnet/vs2010/0.11/bin/bbackupd/BackupDaemon.cpp
   box/invisnet/vs2010/0.11/bin/bbackupd/win32/bbackupd.conf
   box/invisnet/vs2010/0.11/lib/backupclient/BackupDaemonConfigVerify.cpp
   box/invisnet/vs2010/0.11/lib/server/TLSContext.cpp
   box/invisnet/vs2010/0.11/lib/server/TLSContext.h
Log:
Non-working commit.
Some things have standard places under Windows:
Keys belong in a named container,
Certs belong in a cert store,
Application data belongs in the appdata shell folder

Modified: box/invisnet/vs2010/0.11/bin/bbackupd/BackupDaemon.cpp
===================================================================
--- box/invisnet/vs2010/0.11/bin/bbackupd/BackupDaemon.cpp	2010-10-09 04:17:16 UTC (rev 2786)
+++ box/invisnet/vs2010/0.11/bin/bbackupd/BackupDaemon.cpp	2010-10-09 23:36:00 UTC (rev 2787)
@@ -80,6 +80,8 @@
 #ifdef WIN32
 	#include "Win32ServiceFunctions.h"
 	#include "Win32BackupService.h"
+	#include "Shlobj.h"
+	#include "Shlwapi.h"
 
 	extern Win32BackupService* gpDaemonService;
 #endif
@@ -1904,9 +1906,31 @@
 // --------------------------------------------------------------------------
 void BackupDaemon::MakeMapBaseName(unsigned int MountNumber, std::string &rNameOut) const
 {
+	std::string dir;
+
 	// Get the directory for the maps
+#ifdef WIN32
+	// we just ask the system where to put the files...
+	char path[MAX_PATH];
+
+	if (SUCCEEDED(SHGetFolderPath(NULL,CSIDL_LOCAL_APPDATA,NULL,0,path)))
+	{
+		PathAppend(path,"Box Backup");
+		if(FALSE == CreateDirectory(path, NULL)
+			&& ERROR_ALREADY_EXISTS != GetLastError())
+		{
+			THROW_EXCEPTION(CommonException, OSFileError);
+		}
+		dir.assign(path);
+	}
+	else
+	{
+		THROW_EXCEPTION(CommonException, Internal);
+	}
+#else
 	const Configuration &config(GetConfiguration());
-	std::string dir(config.GetKeyValue("DataDirectory"));
+	dir.assign(config.GetKeyValue("DataDirectory"));
+#endif
 
 	// Make a leafname
 	std::string leaf(mIDMapMounts[MountNumber]);

Modified: box/invisnet/vs2010/0.11/bin/bbackupd/win32/bbackupd.conf
===================================================================
--- box/invisnet/vs2010/0.11/bin/bbackupd/win32/bbackupd.conf	2010-10-09 04:17:16 UTC (rev 2786)
+++ box/invisnet/vs2010/0.11/bin/bbackupd/win32/bbackupd.conf	2010-10-09 23:36:00 UTC (rev 2787)
@@ -1,14 +1,7 @@
-
+[BoxBackup]
 StoreHostname = yourhost
 AccountNumber = 0x1
-KeysFile = C:\Program Files\Box Backup\1-FileEncKeys.raw
 
-CertificateFile = C:\Program Files\Box Backup\1-cert.pem
-PrivateKeyFile = C:\Program Files\Box Backup\1-key.pem
-TrustedCAsFile = C:\Program Files\Box Backup\serverCA.pem
-
-DataDirectory = C:\Program Files\Box Backup\bbackupd
-
 # If you do not install it in the default location - also do not forget to 
 # change the pid file location (below)
 

Modified: box/invisnet/vs2010/0.11/lib/backupclient/BackupDaemonConfigVerify.cpp
===================================================================
--- box/invisnet/vs2010/0.11/lib/backupclient/BackupDaemonConfigVerify.cpp	2010-10-09 04:17:16 UTC (rev 2786)
+++ box/invisnet/vs2010/0.11/lib/backupclient/BackupDaemonConfigVerify.cpp	2010-10-09 23:36:00 UTC (rev 2787)
@@ -107,19 +107,20 @@
 	ConfigurationVerifyKey("KeepAliveTime", ConfigTest_IsInt),
  	ConfigurationVerifyKey("StoreObjectInfoFile", 0),
 	// optional
-
-	ConfigurationVerifyKey("NotifyScript", 0),
-	// optional script to run when backup needs attention, eg store full
 	
 	ConfigurationVerifyKey("NotifyAlways", ConfigTest_IsBool, false),
 	// option to disable the suppression of duplicate notifications
 
+#ifndef WIN32
 	ConfigurationVerifyKey("CertificateFile", ConfigTest_Exists),
 	ConfigurationVerifyKey("PrivateKeyFile", ConfigTest_Exists),
 	ConfigurationVerifyKey("TrustedCAsFile", ConfigTest_Exists),
 	ConfigurationVerifyKey("KeysFile", ConfigTest_Exists),
-	ConfigurationVerifyKey("DataDirectory", 
-		ConfigTest_Exists | ConfigTest_LastEntry),
+	ConfigurationVerifyKey("DataDirectory", ConfigTest_Exists),
+#endif
+
+	ConfigurationVerifyKey("NotifyScript", ConfigTest_LastEntry),
+	// optional script to run when backup needs attention, eg store full
 };
 
 const ConfigurationVerify BackupDaemonConfigVerify =

Modified: box/invisnet/vs2010/0.11/lib/server/TLSContext.cpp
===================================================================
--- box/invisnet/vs2010/0.11/lib/server/TLSContext.cpp	2010-10-09 04:17:16 UTC (rev 2786)
+++ box/invisnet/vs2010/0.11/lib/server/TLSContext.cpp	2010-10-09 23:36:00 UTC (rev 2787)
@@ -11,6 +11,9 @@
 
 #define TLS_CLASS_IMPLEMENTATION_CPP
 #include <openssl/ssl.h>
+#ifdef WIN32
+#include <openssl/evp.h>
+#endif
 
 #include "TLSContext.h"
 #include "ServerException.h"
@@ -19,6 +22,10 @@
 
 #include "MemLeakFindOn.h"
 
+#ifdef WIN32
+#include <WinCrypt.h>
+#endif
+
 #define MAX_VERIFICATION_DEPTH		2
 #define CIPHER_LIST					"ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH"
 
@@ -73,6 +80,38 @@
 	}
 	
 	// Setup our identity
+#ifdef WIN32
+	X509 *x509 = GetCertificate();
+	if(::SSL_CTX_use_certificate(mpContext, x509) != 1)
+	{
+		SSLLib::LogError("SSL_CTX_use_certificate");
+		THROW_EXCEPTION(ServerException, TLSLoadCertificatesFailed)
+	}
+	X509_free(x509);
+
+	EVP_PKEY *evpPK = GetPrivateKey();
+	if(::SSL_CTX_use_PrivateKey(mpContext, evpPK) != 1)
+	{
+		SSLLib::LogError("SSL_CTX_use_PrivateKey");
+		THROW_EXCEPTION(ServerException, TLSLoadPrivateKeyFailed)
+	}
+	EVP_PKEY_free(evpPK);
+
+	x509 = GetTrustedCertificate();
+	X509_LOOKUP *lookup = ::X509_STORE_add_lookup(mpContext->cert_store, X509_LOOKUP_file());
+	if(lookup == NULL)
+	{
+		SSLLib::LogError("X509_STORE_add_lookup");
+		THROW_EXCEPTION(ServerException, TLSLoadTrustedCAsFailed)
+	}
+	if(::X509_STORE_add_cert(lookup->store_ctx, x509) != 1)
+	{
+		SSLLib::LogError("X509_STORE_add_cert");
+		THROW_EXCEPTION(ServerException, TLSLoadTrustedCAsFailed)
+	}
+	// don't free lookup
+	X509_free(x509);
+#else
 	if(::SSL_CTX_use_certificate_chain_file(mpContext, CertificatesFile) != 1)
 	{
 		std::string msg = "loading certificates from ";
@@ -87,7 +126,7 @@
 		SSLLib::LogError(msg);
 		THROW_EXCEPTION(ServerException, TLSLoadPrivateKeyFailed)
 	}
-	
+
 	// Setup the identify of CAs we trust
 	if(::SSL_CTX_load_verify_locations(mpContext, TrustedCAsFile, NULL) != 1)
 	{
@@ -96,7 +135,8 @@
 		SSLLib::LogError(msg);
 		THROW_EXCEPTION(ServerException, TLSLoadTrustedCAsFailed)
 	}
-	
+#endif
+
 	// Setup options to require these certificates
 	::SSL_CTX_set_verify(mpContext, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, NULL);
 	// and a sensible maximum depth
@@ -128,4 +168,208 @@
 }
 
 
+#ifdef WIN32
+// --------------------------------------------------------------------------
+//
+// Function
+//		Name:    TLSContext::GetCertificate()
+//		Purpose: Get the certificate from the store
+//		Created: 2010/09/03
+//
+// --------------------------------------------------------------------------
+X509* TLSContext::GetCertificate()
+{
+	HCRYPTPROV	hCryptProv	= NULL;
+	X509			*x509			= NULL;
 
+	if (FALSE == CryptAcquireContext(&hCryptProv,"BoxBackup",NULL,PROV_RSA_FULL,CRYPT_MACHINE_KEYSET))
+	{
+		BOX_ERROR("CryptAcquireContext failed");
+	}
+	else
+	{
+		DWORD cbPublicKeyInfo = 0;
+
+		if(FALSE == CryptExportPublicKeyInfo(hCryptProv, AT_SIGNATURE, X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, NULL, &cbPublicKeyInfo))
+		{
+			BOX_ERROR("Failed to get buffer length for public key");
+		}
+		else
+		{
+			char	*PublicKeyBuffer	= new char[cbPublicKeyInfo];
+			CERT_PUBLIC_KEY_INFO*	pbPublicKeyInfo	= (CERT_PUBLIC_KEY_INFO*) PublicKeyBuffer;
+
+			if(FALSE == CryptExportPublicKeyInfo(hCryptProv, AT_SIGNATURE, X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, pbPublicKeyInfo, &cbPublicKeyInfo))
+			{
+				BOX_ERROR("Failed to export public key");
+			}
+			else
+			{
+				HCERTSTORE  hSystemStore;
+
+				if (NULL == (hSystemStore = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, NULL, CERT_SYSTEM_STORE_LOCAL_MACHINE | CERT_STORE_READONLY_FLAG, L"MY")))
+				{
+					BOX_ERROR("Failed to open store");
+				}
+				else
+				{
+					PCCERT_CONTEXT  pDesiredCert = NULL;
+
+					if(NULL == (pDesiredCert = CertFindCertificateInStore(hSystemStore, PKCS_7_ASN_ENCODING | X509_ASN_ENCODING, 0, CERT_FIND_PUBLIC_KEY, pbPublicKeyInfo, NULL)))
+					{
+						BOX_ERROR("No matching certificate");
+					}
+					else
+					{
+						const unsigned char *pbCertEncoded = pDesiredCert->pbCertEncoded;
+
+						x509 = d2i_X509(NULL, &pbCertEncoded, pDesiredCert->cbCertEncoded);
+
+						CertFreeCertificateContext(pDesiredCert);
+					}
+
+					CertCloseStore(hSystemStore,CERT_CLOSE_STORE_CHECK_FLAG); // TODO: check this
+				}
+			}
+
+			delete[] PublicKeyBuffer;
+		}
+
+		CryptReleaseContext(hCryptProv,0);
+	}
+
+	if(NULL == x509)
+	{
+		THROW_EXCEPTION(ServerException, TLSLoadCertificatesFailed)
+	}
+
+	return x509;
+}
+
+
+// --------------------------------------------------------------------------
+//
+// Function
+//		Name:    TLSContext::GetTrustedCertificate()
+//		Purpose: Get the certificate from the store
+//		Created: 2010/10/09
+//
+// --------------------------------------------------------------------------
+X509* TLSContext::GetTrustedCertificate()
+{
+	X509			*x509			= NULL;
+	HCERTSTORE  hSystemStore;
+
+	if (NULL == (hSystemStore = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, NULL, CERT_SYSTEM_STORE_LOCAL_MACHINE | CERT_STORE_READONLY_FLAG, L"MY")))
+	{
+		BOX_ERROR("Failed to open store");
+	}
+	else
+	{
+		PCCERT_CONTEXT  pDesiredCert = NULL;
+
+		if(NULL == (pDesiredCert = CertFindCertificateInStore(hSystemStore, PKCS_7_ASN_ENCODING | X509_ASN_ENCODING, 0, CERT_FIND_SUBJECT_STR, L"Backup system server root", NULL)))
+		{
+			BOX_ERROR("No matching root certificate");
+		}
+		else
+		{
+			const unsigned char *pbCertEncoded = pDesiredCert->pbCertEncoded;
+
+			x509 = d2i_X509(NULL, &pbCertEncoded, pDesiredCert->cbCertEncoded);
+
+			CertFreeCertificateContext(pDesiredCert);
+		}
+
+		CertCloseStore(hSystemStore,CERT_CLOSE_STORE_CHECK_FLAG); // TODO: check this
+	}
+
+	if(NULL == x509)
+	{
+		THROW_EXCEPTION(ServerException, TLSLoadTrustedCAsFailed)
+	}
+
+	return x509;
+}
+
+
+// --------------------------------------------------------------------------
+//
+// Function
+//		Name:    TLSContext::GetPrivateKey()
+//		Purpose: Get the private key from the container
+//		Created: 2010/09/03
+//
+// --------------------------------------------------------------------------
+EVP_PKEY* TLSContext::GetPrivateKey()
+{
+	HCRYPTPROV		hCryptProv		= NULL;
+	EVP_PKEY			*evpPK			= NULL;
+
+	if (FALSE == CryptAcquireContext(&hCryptProv,"BoxBackup",NULL,PROV_RSA_FULL,CRYPT_MACHINE_KEYSET))
+	{
+		BOX_ERROR("CryptAcquireContext failed");
+	}
+	else
+	{
+		HCRYPTKEY	hKey	= NULL;
+
+		if (FALSE == CryptGetUserKey(hCryptProv,AT_SIGNATURE,&hKey))
+		{
+			BOX_ERROR("CryptGetUserKey failed");
+		}
+		else
+		{
+			DWORD len = 0;
+
+			if(FALSE == CryptExportKey(hKey,NULL,PRIVATEKEYBLOB,0,NULL,&len))
+			{
+				BOX_ERROR("CryptExportKey failed (first pass)");
+			}
+			else
+			{
+				BYTE *key = new BYTE[len];
+
+				if(FALSE == CryptExportKey(hKey,NULL,PRIVATEKEYBLOB,0,key,&len))
+				{
+					BOX_ERROR("CryptExportKey failed (second pass)");
+				}
+				else if(FALSE == CryptEncodeObject(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, PKCS_RSA_PRIVATE_KEY, key, NULL, &len))
+				{
+					BOX_ERROR("CryptEncodeObject failed (first pass)");
+				}
+				else
+				{
+					BYTE *encodedKey = new BYTE[len];
+
+					if(FALSE == CryptEncodeObject(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, PKCS_RSA_PRIVATE_KEY, key, encodedKey, &len))
+					{
+						BOX_ERROR("CryptEncodeObject failed (second pass)");
+					}
+					else
+					{
+						const unsigned char *pEncodedKey = encodedKey;
+
+						d2i_PrivateKey(EVP_PKEY_RSA, &evpPK, &pEncodedKey, len);
+					}
+
+					delete[] encodedKey;
+				}
+
+				delete[] key;
+			}
+
+			CryptDestroyKey(hKey);
+		}
+		CryptReleaseContext(hCryptProv,0);
+	}
+
+	if(NULL == evpPK)
+	{
+		THROW_EXCEPTION(ServerException, TLSLoadPrivateKeyFailed)
+	}
+
+	return evpPK;
+}
+
+#endif
\ No newline at end of file

Modified: box/invisnet/vs2010/0.11/lib/server/TLSContext.h
===================================================================
--- box/invisnet/vs2010/0.11/lib/server/TLSContext.h	2010-10-09 04:17:16 UTC (rev 2786)
+++ box/invisnet/vs2010/0.11/lib/server/TLSContext.h	2010-10-09 23:36:00 UTC (rev 2787)
@@ -12,6 +12,8 @@
 
 #ifndef TLS_CLASS_IMPLEMENTATION_CPP
 	class SSL_CTX;
+	class EVP_PKEY;
+	class X509;
 #endif
 
 // --------------------------------------------------------------------------
@@ -35,6 +37,13 @@
 
 private:
 	SSL_CTX *mpContext;
+
+#ifdef WIN32
+private:
+	EVP_PKEY *GetPrivateKey();
+	X509 *GetCertificate();
+	X509 *GetTrustedCertificate();
+#endif
 };
 
 #endif // TLSCONTEXT__H




More information about the Boxbackup-commit mailing list