Example #1
0
std::shared_ptr<const X509_Certificate>
Certificate_Store_MacOS::find_cert_by_pubkey_sha1(const std::vector<uint8_t>& key_hash) const
   {
   if(key_hash.size() != 20)
      {
      throw Invalid_Argument("Certificate_Store_MacOS::find_cert_by_pubkey_sha1 invalid hash");
      }

   scoped_CFType<CFDataRef> key_hash_cfdata(createCFDataView(key_hash));
   check_notnull(key_hash_cfdata, "create key hash search object");

   scoped_CFType<CFArrayRef> result(m_impl->search(
      {
         {kSecAttrPublicKeyHash, key_hash_cfdata.get()},
      }));

   if(!result)
      {
      return nullptr;  // no certificate found
      }

   const auto count = CFArrayGetCount(result.get());
   BOTAN_ASSERT(count > 0, "certificate result list contains an object");

   // `count` might be greater than 1, but we'll just select the first match
   auto cfCert = to_SecCertificateRef(CFArrayGetValueAtIndex(result.get(), 0));
   return readCertificate(cfCert);
   }
Example #2
0
std::vector<X509_DN> Certificate_Store_MacOS::all_subjects() const
   {
   scoped_CFType<CFArrayRef> result(m_impl->search());

   if(!result)
      {
      return {};  // not a single certificate found in the keychain
      }

   const auto count = CFArrayGetCount(result.get());
   BOTAN_ASSERT(count > 0, "subject result list contains data");

   std::vector<X509_DN> output;
   output.reserve(count);
   for(unsigned int i = 0; i < count; ++i)
      {
      // Note: Apple's API provides SecCertificateCopyNormalizedSubjectSequence
      //       which would have saved us from reading a Botan::X509_Certificate,
      //       however, this function applies the same DN "normalization" as
      //       stated above.
      auto cfCert = to_SecCertificateRef(CFArrayGetValueAtIndex(result.get(), i));
      auto cert = readCertificate(cfCert);
      output.emplace_back(cert->subject_dn());
      }

   return output;
   }
Example #3
0
std::vector<std::shared_ptr<const X509_Certificate>> Certificate_Store_MacOS::find_all_certs(
         const X509_DN& subject_dn,
         const std::vector<uint8_t>& key_id) const
   {
   std::vector<uint8_t> dn_data;
   DER_Encoder encoder(dn_data);
   normalize(subject_dn).encode_into(encoder);

   scoped_CFType<CFDataRef> dn_cfdata(createCFDataView(dn_data));
   check_notnull(dn_cfdata, "create DN search object");

   Certificate_Store_MacOS_Impl::Query query_params(
      {
         {kSecAttrSubject, dn_cfdata.get()}
      });

   scoped_CFType<CFDataRef> keyid_cfdata(createCFDataView(key_id));
   check_notnull(keyid_cfdata, "create key ID search object");
   if(!key_id.empty())
      {
      query_params.push_back({kSecAttrSubjectKeyID, keyid_cfdata.get()});
      }

   scoped_CFType<CFArrayRef> result(m_impl->search(std::move(query_params)));

   if(!result)
      {
      return {};  // no certificates found
      }

   const auto count = CFArrayGetCount(result.get());
   BOTAN_ASSERT(count > 0, "certificate result list contains data");

   std::vector<std::shared_ptr<const X509_Certificate>> output;
   output.reserve(count);
   for(unsigned int i = 0; i < count; ++i)
      {
      auto cfCert = to_SecCertificateRef(CFArrayGetValueAtIndex(result.get(), i));
      output.emplace_back(readCertificate(cfCert));
      }

   return output;
   }
Example #4
0
bool isValid() {
	static bool hasValidated = false;
	static bool validates = false;

	if ( hasValidated ) return validates;

	Environment *env = Environment::Instance();
	if ( env == NULL ) {
		cerr << "FATAL ERROR: No environment available" << endl;
		return false;
	}

	hasValidated = true;

	string licenseDir = env->configDir() + "/key";
	string licenseFile = licenseDir + "/License";
	string licenseKeyfile = licenseDir + "/License.key";
	string licenseSignature = licenseDir + "/License.signed";

	boost::filesystem::path path = SC_FS_PATH(env->shareDir())
	    / SC_FS_PATH("licenses") / SC_FS_PATH("seiscomp3.crt");

	if ( !Seiscomp::Util::fileExists(path.string().c_str()) ) {
		path = SC_FS_PATH(env->configDir())
		    / SC_FS_PATH("licenses") / SC_FS_PATH("seiscomp3.crt");
		if ( !Seiscomp::Util::fileExists(path.string()) ) {
			path = SC_FS_PATH(env->configDir())
			    / SC_FS_PATH("key") / SC_FS_PATH("License.crt");
		}
	}

	X509 *x509 = readCertificate(path.string());
	if ( x509 ) {
		ASN1_TIME* notAfter = X509_get_notAfter(x509),
		         * notBefore = X509_get_notBefore(x509);
		time_t ptime = time(NULL);

		int res = X509_cmp_time(notBefore, &ptime);
		if ( res == 0 || res > 0 ) {
			X509_free(x509);
			cerr << "FATAL ERROR: License has expired: " << path.string() << endl;
			return false;
		}

		res = X509_cmp_time(notAfter, &ptime);
		if ( res == 0 || res < 0 ) {
			X509_free(x509);
			cerr << "FATAL ERROR: License has expired: " << path.string() << endl;
			return false;
		}

		OpenSSL_add_all_algorithms();
		OpenSSL_add_all_ciphers();
		OpenSSL_add_all_digests();

		EVP_PKEY* pkey=X509_get_pubkey(x509);
		if ( !pkey ) {
			X509_free(x509);
			EVP_cleanup();
			cerr << "FATAL ERROR: License verification has failed: " << path.string() << endl;
			return false;
		}

		res = X509_verify(x509, pkey);
		if ( res != 1 ) {
			X509_free(x509);
			EVP_PKEY_free(pkey);
			EVP_cleanup();
			cerr << "FATAL ERROR: License verification has failed: " << path.string() << endl;
			return false;
		}

		char *buf;
		if ( readNID(&buf, x509, NID_netscape_comment) ) {
			licenseText = buf;
			delete buf;
		}

		EVP_PKEY_free(pkey);
		X509_free(x509);

		EVP_cleanup();

		return true;
	}

	// Read license file
	MD5_CTX ctx;
	MD5_Init(&ctx);

	unsigned char digest[MD5_DIGEST_LENGTH];
	char data[64];
	size_t len;

	ifstream f;

	try {
		f.open(licenseFile.c_str(), ios_base::in);
	}
	catch ( std::exception &e ) {
		cerr << "FATAL ERROR: Failed to open license file: " << licenseFile << endl;
		validates = false;
		return false;
	}

	if ( !f.good() ) {
		cerr << "FATAL ERROR: Failed to open license file: " << licenseFile << endl;
		validates = false;
		return false;
	}

	licenseText.clear();

	try {
		while ( (len = f.rdbuf()->sgetn(data, sizeof(data))) > 0 ) {
			licenseText.append(data, len);
			MD5_Update(&ctx, data, len);
		}
	}
	catch ( ... ) {
		cerr << "FATAL ERROR: Invalid license file: " << licenseFile << endl;
		f.close();
		validates = false;
		return false;
	}

	f.close();

	MD5_Final(digest, &ctx);

	int strength = 0;
	RSA *publicKey = readKey(licenseKeyfile.c_str(), PUBLIC, 1024, 8192, strength);
	if ( publicKey == NULL ) {
		cerr << "FATAL ERROR: Invalid key file: " << licenseKeyfile << endl;
		validates = false;
		return false;
	}

	BIO *bio_file = NULL, *b64_file;
	b64_file = BIO_new(BIO_f_base64());
	bio_file = BIO_new_file(licenseSignature.c_str(), "r");
	bio_file = BIO_push(b64_file, bio_file);

	int sigLength = strength / 8;
	unsigned char *signature = new unsigned char[sigLength];

	sigLength = BIO_read(bio_file, signature, sigLength);

	BIO_free_all(bio_file);

	if ( sigLength <= 0 ) {
		delete [] signature;
		cerr << "FATAL ERROR: Empty signature" << endl;
		validates = false;
		return false;
	}

	validates = RSA_verify(NID_md5, digest, MD5_DIGEST_LENGTH, signature, sigLength, publicKey);

	delete [] signature;

	/*
	if ( validates ) {
		cerr << "-----BEGIN LICENSE-----" << endl;
		cerr << licenseText << endl;
		cerr << "-----END LICENSE-----" << endl << endl;
	}
	*/

	return validates;
}