mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-01 01:07:51 -04:00
common_name -> friendly_name
This commit is contained in:
parent
df998fbf48
commit
2552864754
@ -165,7 +165,7 @@ AuthDialog(const wxString &cert_filename, const wxString &cert_dir) :
|
||||
_verify_result = -1;
|
||||
|
||||
read_cert_file(cert_filename);
|
||||
get_common_name();
|
||||
get_friendly_name();
|
||||
verify_cert();
|
||||
layout();
|
||||
}
|
||||
@ -295,39 +295,52 @@ read_cert_file(const wxString &cert_filename) {
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: AuthDialog::get_common_name
|
||||
// Function: AuthDialog::get_friendly_name
|
||||
// Access: Private
|
||||
// Description: Extracts the common_name from the certificate.
|
||||
// Description: Extracts the "friendly name" from the certificate:
|
||||
// the common name or email name.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void AuthDialog::
|
||||
get_common_name() {
|
||||
get_friendly_name() {
|
||||
if (_cert == NULL) {
|
||||
_common_name.clear();
|
||||
_friendly_name.clear();
|
||||
return;
|
||||
}
|
||||
|
||||
// A complex OpenSSL interface to extract out the common name in
|
||||
// utf-8.
|
||||
X509_NAME *xname = X509_get_subject_name(_cert);
|
||||
if (xname != NULL) {
|
||||
int pos = X509_NAME_get_index_by_NID(xname, NID_commonName, -1);
|
||||
if (pos != -1) {
|
||||
// We just get the first common name. I guess it's possible to
|
||||
// have more than one; not sure what that means in this context.
|
||||
X509_NAME_ENTRY *xentry = X509_NAME_get_entry(xname, pos);
|
||||
if (xentry != NULL) {
|
||||
ASN1_STRING *data = X509_NAME_ENTRY_get_data(xentry);
|
||||
if (data != NULL) {
|
||||
// We use "print" to dump the output to a memory BIO. Is
|
||||
// there an easier way to decode the ASN1_STRING? Curse
|
||||
// these incomplete docs.
|
||||
BIO *mbio = BIO_new(BIO_s_mem());
|
||||
ASN1_STRING_print_ex(mbio, data, ASN1_STRFLGS_RFC2253 & ~ASN1_STRFLGS_ESC_MSB);
|
||||
|
||||
char *pp;
|
||||
long pp_size = BIO_get_mem_data(mbio, &pp);
|
||||
_common_name = wxString(pp, wxConvUTF8, pp_size);
|
||||
BIO_free(mbio);
|
||||
static const int nid_choices[] = {
|
||||
NID_pkcs9_emailAddress,
|
||||
NID_commonName,
|
||||
-1,
|
||||
};
|
||||
|
||||
// Choose the first NID that exists on the cert.
|
||||
for (int ni = 0; nid_choices[ni] != -1; ++ni) {
|
||||
int nid = nid_choices[ni];
|
||||
|
||||
// A complex OpenSSL interface to extract out the name in utf-8.
|
||||
X509_NAME *xname = X509_get_subject_name(_cert);
|
||||
if (xname != NULL) {
|
||||
int pos = X509_NAME_get_index_by_NID(xname, nid, -1);
|
||||
if (pos != -1) {
|
||||
// We just get the first common name. I guess it's possible to
|
||||
// have more than one; not sure what that means in this context.
|
||||
X509_NAME_ENTRY *xentry = X509_NAME_get_entry(xname, pos);
|
||||
if (xentry != NULL) {
|
||||
ASN1_STRING *data = X509_NAME_ENTRY_get_data(xentry);
|
||||
if (data != NULL) {
|
||||
// We use "print" to dump the output to a memory BIO. Is
|
||||
// there an easier way to decode the ASN1_STRING? Curse
|
||||
// these incomplete docs.
|
||||
BIO *mbio = BIO_new(BIO_s_mem());
|
||||
ASN1_STRING_print_ex(mbio, data, ASN1_STRFLGS_RFC2253 & ~ASN1_STRFLGS_ESC_MSB);
|
||||
|
||||
char *pp;
|
||||
long pp_size = BIO_get_mem_data(mbio, &pp);
|
||||
_friendly_name = wxString(pp, wxConvUTF8, pp_size);
|
||||
BIO_free(mbio);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -388,7 +401,7 @@ verify_cert() {
|
||||
|
||||
X509_STORE_free(store);
|
||||
|
||||
cerr << "Got certificate from " << _common_name
|
||||
cerr << "Got certificate from " << _friendly_name
|
||||
<< ", verify_result = " << _verify_result << "\n";
|
||||
}
|
||||
|
||||
@ -461,7 +474,7 @@ get_text(wxString &header, wxString &text) {
|
||||
break;
|
||||
|
||||
case 0:
|
||||
text.Printf(verified_cert_text, _common_name.c_str(), _common_name.c_str(), _common_name.c_str());
|
||||
text.Printf(verified_cert_text, _friendly_name.c_str(), _friendly_name.c_str(), _friendly_name.c_str());
|
||||
break;
|
||||
|
||||
case X509_V_ERR_CERT_NOT_YET_VALID:
|
||||
@ -469,12 +482,12 @@ get_text(wxString &header, wxString &text) {
|
||||
case X509_V_ERR_CRL_NOT_YET_VALID:
|
||||
case X509_V_ERR_CRL_HAS_EXPIRED:
|
||||
header = _T("Expired signature!");
|
||||
text.Printf(expired_cert_text, _common_name.c_str());
|
||||
text.Printf(expired_cert_text, _friendly_name.c_str());
|
||||
break;
|
||||
|
||||
case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY:
|
||||
header = _T("Unverified signature!");
|
||||
text.Printf(unknown_auth_cert_text, _common_name.c_str());
|
||||
text.Printf(unknown_auth_cert_text, _friendly_name.c_str());
|
||||
break;
|
||||
|
||||
case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT:
|
||||
|
@ -67,7 +67,7 @@ public:
|
||||
|
||||
private:
|
||||
void read_cert_file(const wxString &cert_filename);
|
||||
void get_common_name();
|
||||
void get_friendly_name();
|
||||
void verify_cert();
|
||||
|
||||
void layout();
|
||||
@ -84,7 +84,7 @@ private:
|
||||
X509 *_cert;
|
||||
STACK *_stack;
|
||||
|
||||
wxString _common_name;
|
||||
wxString _friendly_name;
|
||||
int _verify_result;
|
||||
};
|
||||
|
||||
|
@ -224,17 +224,19 @@ help() {
|
||||
" generate slightly smaller files, but compression takes longer. The\n"
|
||||
" default is -" << default_compression_level << ".\n\n"
|
||||
|
||||
" -S file.crt,[chain.crt],file.key[,\"password\"]\n"
|
||||
" -S file.crt[,chain.crt[,file.key[,\"password\"]]]\n"
|
||||
" Sign the multifile. The signing certificate should be in PEM form in\n"
|
||||
" file.crt, with its private key in PEM form in file.key. If the key\n"
|
||||
" is encrypted on-disk, specify the decryption password as the third\n"
|
||||
" option. If a certificate chain is required, chain.crt should also\n"
|
||||
" be specified; note that the commas should be supplied even if this\n"
|
||||
" optional filename is omitted.\n"
|
||||
" be specified; note that the separating commas should be supplied\n"
|
||||
" even if this optional filename is omitted.\n"
|
||||
" You may also provide a single composite file that contains the\n"
|
||||
" certificate, chain, and key in the same file.\n"
|
||||
" PEM form is the form accepted by the Apache web server. The\n"
|
||||
" signature is written to the multifile to prove it is unchanged; any\n"
|
||||
" subsequent change to the multifile will invalidate the signature.\n"
|
||||
" This parameter may be repeated to sign the multifile with different\n"
|
||||
" This parameter may be repeated to sign the multifile with additional\n"
|
||||
" certificates.\n\n";
|
||||
}
|
||||
|
||||
@ -391,7 +393,13 @@ add_files(const vector_string ¶ms) {
|
||||
|
||||
bool okflag = do_add_files(multifile, filenames);
|
||||
|
||||
if (multifile->needs_repack()) {
|
||||
bool needs_repack = multifile->needs_repack();
|
||||
if (append) {
|
||||
// If we specified -r mode, we always repack.
|
||||
needs_repack = true;
|
||||
}
|
||||
|
||||
if (needs_repack) {
|
||||
if (!multifile->repack()) {
|
||||
cerr << "Failed to write " << multifile_name << ".\n";
|
||||
okflag = false;
|
||||
@ -529,27 +537,27 @@ sign_multifile() {
|
||||
vector_string::iterator si;
|
||||
for (si = sign_params.begin(); si != sign_params.end(); ++si) {
|
||||
const string ¶m = (*si);
|
||||
Filename certificate, chain, pkey;
|
||||
string password;
|
||||
|
||||
size_t comma1 = param.find(',');
|
||||
if (comma1 == string::npos) {
|
||||
cerr << "Signing parameter requires two commas: " << param << "\n";
|
||||
return false;
|
||||
}
|
||||
size_t comma2 = param.find(',', comma1 + 1);
|
||||
if (comma2 == string::npos) {
|
||||
cerr << "Signing parameter requires two commas: " << param << "\n";
|
||||
return false;
|
||||
}
|
||||
size_t comma3 = param.find(',', comma2 + 1);
|
||||
|
||||
Filename certificate = Filename::from_os_specific(param.substr(0, comma1));
|
||||
Filename chain = Filename::from_os_specific(param.substr(comma1 + 1, comma2 - comma1 - 1));
|
||||
Filename pkey;
|
||||
string password;
|
||||
if (comma3 != string::npos) {
|
||||
pkey = Filename::from_os_specific(param.substr(comma2 + 1, comma3 - comma2 - 1));
|
||||
password = param.substr(comma3 + 1);
|
||||
certificate = Filename::from_os_specific(param);
|
||||
} else {
|
||||
pkey = Filename::from_os_specific(param.substr(comma2 + 1));
|
||||
certificate = Filename::from_os_specific(param.substr(0, comma1));
|
||||
size_t comma2 = param.find(',', comma1 + 1);
|
||||
if (comma2 == string::npos) {
|
||||
chain = Filename::from_os_specific(param.substr(comma1 + 1));
|
||||
} else {
|
||||
chain = Filename::from_os_specific(param.substr(comma1 + 1, comma2 - comma1 - 1));
|
||||
size_t comma3 = param.find(',', comma2 + 1);
|
||||
if (comma3 == string::npos) {
|
||||
pkey = Filename::from_os_specific(param.substr(comma2 + 1));
|
||||
} else {
|
||||
pkey = Filename::from_os_specific(param.substr(comma2 + 1, comma3 - comma2 - 1));
|
||||
password = param.substr(comma3 + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!multifile->add_signature(certificate, chain, pkey, password)) {
|
||||
@ -675,7 +683,7 @@ list_files(const vector_string ¶ms) {
|
||||
if (num_signatures != 0) {
|
||||
cout << "\n";
|
||||
for (i = 0; i < num_signatures; ++i) {
|
||||
cout << "Signed by " << multifile->get_signature_common_name(i);
|
||||
cout << "Signed by " << multifile->get_signature_friendly_name(i);
|
||||
int verify_result = multifile->validate_signature_certificate(i);
|
||||
if (verify_result == 0) {
|
||||
cout << " (certificate validated)\n";
|
||||
|
@ -568,3 +568,14 @@ INLINE Multifile::CertRecord::
|
||||
~CertRecord() {
|
||||
X509_free(_cert);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: Multifile::CertRecord::Copy Assignment
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void Multifile::CertRecord::
|
||||
operator = (const Multifile::CertRecord &other) {
|
||||
X509_free(_cert);
|
||||
_cert = X509_dup(other._cert);
|
||||
}
|
||||
|
@ -598,6 +598,13 @@ add_signature(const Filename &certificate, const Filename &chain,
|
||||
const Filename &pkey, const string &password) {
|
||||
VirtualFileSystem *vfs = VirtualFileSystem::get_global_ptr();
|
||||
|
||||
if (chain.empty() && pkey.empty()) {
|
||||
// If the second two filenames are empty, assume we're going for
|
||||
// the composite mode, where everything's stuffed into the first
|
||||
// file.
|
||||
return add_signature(certificate, password);
|
||||
}
|
||||
|
||||
CertChain cert_chain;
|
||||
|
||||
// Read the certificate file from VFS. First, read the complete
|
||||
@ -673,6 +680,98 @@ add_signature(const Filename &certificate, const Filename &chain,
|
||||
return result;
|
||||
}
|
||||
#endif // HAVE_OPENSSL
|
||||
|
||||
#ifdef HAVE_OPENSSL
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: Multifile::add_signature
|
||||
// Access: Published
|
||||
// Description: Adds a new signature to the Multifile. This
|
||||
// signature associates the indicated certificate with
|
||||
// the current contents of the Multifile. When the
|
||||
// Multifile is read later, the signature will still be
|
||||
// present only if the Multifile is unchanged; any
|
||||
// subsequent changes to the Multifile will
|
||||
// automatically invalidate and remove the signature.
|
||||
//
|
||||
// This flavor of add_signature() reads the certificate,
|
||||
// private key, and certificate chain from the same
|
||||
// PEM-formatted file. It takes the first private key
|
||||
// found as the intended key, and then uses the first
|
||||
// certificate found that matches that key as the
|
||||
// signing certificate. Any other certificates in the
|
||||
// file are taken to be part of the chain.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool Multifile::
|
||||
add_signature(const Filename &composite, const string &password) {
|
||||
VirtualFileSystem *vfs = VirtualFileSystem::get_global_ptr();
|
||||
|
||||
// First, read the complete file into memory.
|
||||
string composite_data;
|
||||
if (!vfs->read_file(composite, composite_data, true)) {
|
||||
express_cat.info()
|
||||
<< "Could not read " << composite << ".\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
// Get the private key.
|
||||
BIO *pkey_mbio = BIO_new_mem_buf((void *)composite_data.data(), composite_data.size());
|
||||
EVP_PKEY *evp_pkey = PEM_read_bio_PrivateKey(pkey_mbio, NULL, NULL,
|
||||
(void *)password.c_str());
|
||||
BIO_free(pkey_mbio);
|
||||
if (evp_pkey == NULL) {
|
||||
express_cat.info()
|
||||
<< "Could not read private key in " << composite << ".\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
// Now read all of the certificates.
|
||||
CertChain cert_chain;
|
||||
|
||||
BIO *chain_mbio = BIO_new_mem_buf((void *)composite_data.data(), composite_data.size());
|
||||
X509 *c = PEM_read_bio_X509(chain_mbio, NULL, NULL, (void *)"");
|
||||
while (c != NULL) {
|
||||
cert_chain.push_back(c);
|
||||
c = PEM_read_bio_X509(chain_mbio, NULL, NULL, (void *)"");
|
||||
}
|
||||
BIO_free(chain_mbio);
|
||||
|
||||
if (cert_chain.empty()) {
|
||||
express_cat.info()
|
||||
<< "Could not read certificates in " << composite << ".\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
// Now find the certificate that matches the signature, and move it
|
||||
// to the front of the chain.
|
||||
size_t i;
|
||||
bool found_match = false;
|
||||
for (i = 0; i < cert_chain.size(); ++i) {
|
||||
X509 *c = cert_chain[i]._cert;
|
||||
if (X509_check_private_key(c, evp_pkey)) {
|
||||
found_match = true;
|
||||
if (i != 0) {
|
||||
// Move this entry to the beginning.
|
||||
cert_chain.insert(cert_chain.begin(), cert_chain[i]);
|
||||
cert_chain.erase(cert_chain.begin() + i + 1);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found_match) {
|
||||
express_cat.info()
|
||||
<< "No certificates in " << composite << " match key.\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
bool result = add_signature(cert_chain, evp_pkey);
|
||||
|
||||
EVP_PKEY_free(evp_pkey);
|
||||
|
||||
return result;
|
||||
}
|
||||
#endif // HAVE_OPENSSL
|
||||
|
||||
#ifdef HAVE_OPENSSL
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: Multifile::add_signature
|
||||
@ -756,6 +855,24 @@ add_signature(const Multifile::CertChain &cert_chain, EVP_PKEY *pkey) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (cert_chain.empty()) {
|
||||
express_cat.info()
|
||||
<< "No certificate given.\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (pkey == NULL) {
|
||||
express_cat.info()
|
||||
<< "No private key given.\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!X509_check_private_key(cert_chain[0]._cert, pkey)) {
|
||||
express_cat.info()
|
||||
<< "Private key does not match certificate.\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
// Now encode that list of certs to a stream in DER form.
|
||||
stringstream der_stream;
|
||||
@ -871,42 +988,54 @@ get_signature_subject_name(int n) const {
|
||||
|
||||
#ifdef HAVE_OPENSSL
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: Multifile::get_signature_common_name
|
||||
// Function: Multifile::get_signature_friendly_name
|
||||
// Access: Published
|
||||
// Description: Returns the "common name" for the nth signature found
|
||||
// on the Multifile, encoded in utf-8. This is a subset
|
||||
// of the subject_name, but it is probably a friendlier
|
||||
// string to present to a user. See the comments in
|
||||
// get_num_signatures().
|
||||
// Description: Returns a "friendly name" for the nth signature found
|
||||
// on the Multifile. This attempts to extract out the
|
||||
// most meaningful part of the subject name. It returns
|
||||
// the emailAddress, if it is defined; otherwise, it
|
||||
// returns the commonName.
|
||||
|
||||
// See the comments in get_num_signatures().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
string Multifile::
|
||||
get_signature_common_name(int n) const {
|
||||
get_signature_friendly_name(int n) const {
|
||||
const CertChain &cert_chain = get_signature(n);
|
||||
nassertr(!cert_chain.empty(), string());
|
||||
|
||||
// A complex OpenSSL interface to extract out the common name in
|
||||
// utf-8.
|
||||
X509_NAME *xname = X509_get_subject_name(cert_chain[0]._cert);
|
||||
if (xname != NULL) {
|
||||
int pos = X509_NAME_get_index_by_NID(xname, NID_commonName, -1);
|
||||
if (pos != -1) {
|
||||
// We just get the first common name. I guess it's possible to
|
||||
// have more than one; not sure what that means in this context.
|
||||
X509_NAME_ENTRY *xentry = X509_NAME_get_entry(xname, pos);
|
||||
if (xentry != NULL) {
|
||||
ASN1_STRING *data = X509_NAME_ENTRY_get_data(xentry);
|
||||
if (data != NULL) {
|
||||
// We use "print" to dump the output to a memory BIO. Is
|
||||
// there an easier way to decode the ASN1_STRING? Curse
|
||||
// these incomplete docs.
|
||||
BIO *mbio = BIO_new(BIO_s_mem());
|
||||
ASN1_STRING_print_ex(mbio, data, ASN1_STRFLGS_RFC2253 & ~ASN1_STRFLGS_ESC_MSB);
|
||||
static const int nid_choices[] = {
|
||||
NID_pkcs9_emailAddress,
|
||||
NID_commonName,
|
||||
-1,
|
||||
};
|
||||
|
||||
char *pp;
|
||||
long pp_size = BIO_get_mem_data(mbio, &pp);
|
||||
string name(pp, pp_size);
|
||||
BIO_free(mbio);
|
||||
return name;
|
||||
// Choose the first NID that exists on the cert.
|
||||
for (int ni = 0; nid_choices[ni] != -1; ++ni) {
|
||||
int nid = nid_choices[ni];
|
||||
|
||||
// A complex OpenSSL interface to extract out the name in utf-8.
|
||||
X509_NAME *xname = X509_get_subject_name(cert_chain[0]._cert);
|
||||
if (xname != NULL) {
|
||||
int pos = X509_NAME_get_index_by_NID(xname, nid, -1);
|
||||
if (pos != -1) {
|
||||
// We just get the first common name. I guess it's possible to
|
||||
// have more than one; not sure what that means in this context.
|
||||
X509_NAME_ENTRY *xentry = X509_NAME_get_entry(xname, pos);
|
||||
if (xentry != NULL) {
|
||||
ASN1_STRING *data = X509_NAME_ENTRY_get_data(xentry);
|
||||
if (data != NULL) {
|
||||
// We use "print" to dump the output to a memory BIO. Is
|
||||
// there an easier way to decode the ASN1_STRING? Curse
|
||||
// these incomplete docs.
|
||||
BIO *mbio = BIO_new(BIO_s_mem());
|
||||
ASN1_STRING_print_ex(mbio, data, ASN1_STRFLGS_RFC2253 & ~ASN1_STRFLGS_ESC_MSB);
|
||||
|
||||
char *pp;
|
||||
long pp_size = BIO_get_mem_data(mbio, &pp);
|
||||
string name(pp, pp_size);
|
||||
BIO_free(mbio);
|
||||
return name;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2081,6 +2210,8 @@ clear_subfiles() {
|
||||
delete subfile;
|
||||
}
|
||||
_cert_special.clear();
|
||||
|
||||
_signatures.clear();
|
||||
#endif // HAVE_OPENSSL
|
||||
|
||||
Subfiles::iterator fi;
|
||||
|
@ -89,6 +89,7 @@ PUBLISHED:
|
||||
INLINE CertRecord(X509 *cert);
|
||||
INLINE CertRecord(const CertRecord ©);
|
||||
INLINE ~CertRecord();
|
||||
INLINE void operator = (const CertRecord &other);
|
||||
X509 *_cert;
|
||||
};
|
||||
typedef pvector<CertRecord> CertChain;
|
||||
@ -97,13 +98,15 @@ PUBLISHED:
|
||||
const Filename &chain,
|
||||
const Filename &pkey,
|
||||
const string &password = "");
|
||||
bool add_signature(const Filename &composite,
|
||||
const string &password = "");
|
||||
bool add_signature(X509 *certificate, STACK *chain, EVP_PKEY *pkey);
|
||||
bool add_signature(const CertChain &chain, EVP_PKEY *pkey);
|
||||
|
||||
int get_num_signatures() const;
|
||||
const CertChain &get_signature(int n) const;
|
||||
string get_signature_subject_name(int n) const;
|
||||
string get_signature_common_name(int n) const;
|
||||
string get_signature_friendly_name(int n) const;
|
||||
string get_signature_public_key(int n) const;
|
||||
void write_signature_certificate(int n, ostream &out) const;
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user