This commit is contained in:
Thomas Olsen 2017-12-06 15:53:25 -08:00
Родитель 821d5ff985
Коммит 242bb03993
1 изменённых файлов: 72 добавлений и 47 удалений

Просмотреть файл

@ -239,6 +239,74 @@ namespace xPlat
return ok;
}
bool GetPublisherName(/*in*/ unique_PKCS7& p7, /*inout*/ std::string& publisher)
{
X509* cert = nullptr;
STACK_OF(X509) *untrustedCerts = p7.get()->d.sign->cert;
// If there's only one cert, it's a self-signed package; just return its subject
if (sk_X509_num(untrustedCerts) == 1)
{
cert = sk_X509_value(untrustedCerts, 0);
}
else
{
std::map<std::string/*issuer*/, int/*refcount*/> issuers;
for (int i = 0; i < sk_X509_num(untrustedCerts); i++)
{
X509* certT = sk_X509_value(untrustedCerts, i);
unique_OPENSSL_string issuer(X509_NAME_oneline(X509_get_issuer_name(certT), NULL, 0));
try
{
// This will throw if the issuer isn't in the map
int count = issuers.at(issuer.get());
// This issuer is already in the map, increment its refcount
issuers[issuer.get()] = count + 1;
}
catch(std::out_of_range& e)
{
// The issuer is not in the map; add it and set refcount to 1
issuers[issuer.get()] = 1;
}
}
// Now, loop through the certs and find out which one isn't an issuer
for (int i = 0; i < sk_X509_num(untrustedCerts); i++)
{
X509* certT = sk_X509_value(untrustedCerts, i);
unique_OPENSSL_string subject(X509_NAME_oneline(X509_get_subject_name(certT), NULL, 0));
try
{
// This will throw if the subject isn't in the map
issuers.at(subject.get());
}
catch(std::out_of_range& e)
{
// The subject is not in the map -- so it's the last cert in the untrusted chain
cert = certT;
break;
}
}
}
// We should have found a certificate
if (cert)
{
// Create a BIO memory buffer, and print the subject name to it.
unique_BIO bio(BIO_new(BIO_s_mem()));
X509_NAME_print_ex(bio.get(),
X509_get_subject_name(cert),
0,
XN_FLAG_SEP_CPLUS_SPC | XN_FLAG_DN_REV);
// Now extract the publisher from the BIO print buffer
char *memBuffer = nullptr;
BIO_get_mem_data(bio.get(), &memBuffer);
publisher = std::string(memBuffer);
return true;
}
return false;
}
bool SignatureValidator::Validate(
/*in*/ APPX_VALIDATION_OPTION option,
/*in*/ IStream *stream,
@ -339,53 +407,10 @@ namespace xPlat
(option & APPX_VALIDATION_OPTION::APPX_VALIDATION_OPTION_ALLOWSIGNATUREORIGINUNKNOWN)
), "Signature origin check failed");
STACK_OF(X509) *untrustedCerts = p7.get()->d.sign->cert;
// If there's only one cert, it's a self-signed package; just return its subject
if (sk_X509_num(untrustedCerts) == 1)
{
X509* cert = sk_X509_value(untrustedCerts, 0);
unique_OPENSSL_string subject(X509_NAME_oneline(X509_get_subject_name(cert), NULL, 0));
publisher = subject.get();
}
else
{
std::map<std::string/*issuer*/, int/*refcount*/> issuers;
for (int i = 0; i < sk_X509_num(untrustedCerts); i++)
{
X509* cert = sk_X509_value(untrustedCerts, i);
unique_OPENSSL_string issuer(X509_NAME_oneline(X509_get_issuer_name(cert), NULL, 0));
try
{
// This will throw if the issuer isn't in the map
int count = issuers.at(issuer.get());
// This issuer is already in the map, increment its refcount
issuers[issuer.get()] = count + 1;
}
catch(std::out_of_range& e)
{
// The issuer is not in the map; add it and set refcount to 1
issuers[issuer.get()] = 1;
}
}
// Now, loop through the certs and find out which one isn't an issuer
for (int i = 0; i < sk_X509_num(untrustedCerts); i++)
{
X509* cert = sk_X509_value(untrustedCerts, i);
unique_OPENSSL_string subject(X509_NAME_oneline(X509_get_subject_name(cert), NULL, 0));
try
{
// This will throw if the subject isn't in the map
issuers.at(subject.get());
}
catch(std::out_of_range& e)
{
// The subject is not in the map -- so it's the last cert in the untrusted chain
publisher = subject.get();
break;
}
}
}
ThrowErrorIfNot(Error::AppxSignatureInvalid, (
GetPublisherName(p7, publisher) == true
), "Signature origin check failed");
return true;
}
} // namespace xPlat