39#include <openssl/pem.h>
49#define BIO_PRINT(b,c) \
51 BIO_get_mem_ptr(b, &bptr); \
53 char *s = new char[bptr->length+1]; \
54 memcpy(s, bptr->data, bptr->length); \
55 s[bptr->length] = '\0'; \
59 PRINT("ERROR: "<<c<<" BIO internal buffer undefined!"); \
63const char *XrdCryptosslX509::cpxytype[5] = {
"",
"unknown",
"RFC",
"GSI3",
"legacy" };
71 EPNAME(
"X509::XrdCryptosslX509_file");
90 DEBUG(
"file name undefined");
95 int fd =
open(cf, O_RDONLY);
98 if (errno == ENOENT) {
99 DEBUG(
"file "<<cf<<
" does not exist - do nothing");
101 DEBUG(
"cannot open file "<<cf<<
" (errno: "<<errno<<
")");
106 if (
fstat(fd, &st) != 0) {
107 DEBUG(
"cannot stat file "<<cf<<
" (errno: "<<errno<<
")");
113 FILE *fc = fdopen(fd,
"r");
115 DEBUG(
"cannot fdopen file "<<cf<<
" (errno: "<<errno<<
")");
121 if (!PEM_read_X509(fc, &cert, 0, 0)) {
122 DEBUG(
"Unable to load certificate from file");
126 DEBUG(
"certificate successfully loaded");
144 int fd =
open(kf, O_RDONLY);
146 DEBUG(
"cannot open file "<<kf<<
" (errno: "<<errno<<
")");
149 if (
fstat(fd, &st) == -1) {
150 DEBUG(
"cannot stat private key file "<<kf<<
" (errno:"<<errno<<
")");
154 if (!S_ISREG(st.st_mode) || S_ISDIR(st.st_mode) ||
155 (st.st_mode & (S_IROTH | S_IWOTH)) != 0 ||
156 (st.st_mode & (S_IWGRP)) != 0) {
157 DEBUG(
"private key file "<<kf<<
" has wrong permissions "<<
158 (st.st_mode & 0777) <<
" (should be at most 0640)");
163 FILE *fk = fdopen(fd,
"r");
165 DEBUG(
"cannot open file "<<kf<<
" (errno: "<<errno<<
")");
170 if ((evpp = PEM_read_PrivateKey(fk,0,0,0))) {
171 DEBUG(
"RSA key completed ");
173 auto tmprsa = std::make_unique<XrdCryptosslRSA>(evpp, 1);
176 pki = tmprsa.release();
179 DEBUG(
"cannot read the key from file");
194 EPNAME(
"X509::XrdCryptosslX509_bio");
213 DEBUG(
"got undefined opaque buffer");
219 BIO *bmem = BIO_new(BIO_s_mem());
221 DEBUG(
"unable to create BIO for memory operations");
226 int nw = BIO_write(bmem,(
const void *)(buck->
buffer),buck->
size);
227 if (nw != buck->
size) {
228 DEBUG(
"problems writing data to memory BIO (nw: "<<nw<<
")");
233 if (!(cert = PEM_read_bio_X509(bmem,0,0,0))) {
234 DEBUG(
"unable to read certificate to memory BIO");
248 EVP_PKEY *evpp = X509_get_pubkey(cert);
255 DEBUG(
"could not access the public key");
263 EPNAME(
"X509::XrdCryptosslX509_x509");
282 DEBUG(
"got undefined X509 object");
296 EVP_PKEY *evpp = X509_get_pubkey(cert);
303 DEBUG(
"could not access the public key");
313 if (cert) X509_free(cert);
319void XrdCryptosslX509::CertType()
327 PRINT(
"ERROR: certificate is not initialized");
335 int numext = X509_get_ext_count(cert);
337 DEBUG(
"certificate has got no extensions");
340 TRACE(ALL,
"certificate has "<<numext<<
" extensions");
344#if OPENSSL_VERSION_NUMBER < 0x40000000L
345 X509_EXTENSION *ext = 0;
347 const X509_EXTENSION *ext = 0;
353 BASIC_CONSTRAINTS *bc = 0;
354 if ((bc = (BASIC_CONSTRAINTS *)X509_get_ext_d2i(cert, NID_basic_constraints, &crit, &idx)) &&
357 DEBUG(
"CA certificate");
360 if (bc) BASIC_CONSTRAINTS_free(bc);
366 XrdOucString common(subject, 0, subject.rfind(
"/CN=") - 1);
368 if (issuer == common) {
375 if ((idx = X509_get_ext_by_NID(cert, NID_proxyCertInfo,-1)) == -1) {
381 DEBUG(
"Found GSI 3 proxyCertInfo extension");
382 }
else if (xcp == -1) {
386 if ((ext = X509_get_ext(cert,idx)) == 0) {
387 PRINT(
"ERROR: could not get proxyCertInfo extension");
393 if (X509_EXTENSION_get_critical(ext)) {
394 PROXY_CERT_INFO_EXTENSION *pci = (PROXY_CERT_INFO_EXTENSION *)X509V3_EXT_d2i(ext);
396 if ((pci->proxyPolicy) != 0) {
397 if ((pci->proxyPolicy->policyLanguage) != 0) {
401 DEBUG(
"Found RFC 382{0,1}compliant proxyCertInfo extension");
402 if (X509_get_ext_by_NID(cert, NID_proxyCertInfo, idx) != -1) {
403 PRINT(
"WARNING: multiple proxyCertInfo extensions found: taking the first");
406 PRINT(
"ERROR: accessing policy language from proxyCertInfo extension");
409 PRINT(
"ERROR: accessing policy from proxyCertInfo extension");
411 PROXY_CERT_INFO_EXTENSION_free(pci);
413 PRINT(
"ERROR: proxyCertInfo conversion error");
416 PRINT(
"ERROR: proxyCertInfo not flagged as critical");
419 if (!pxyname || done)
return;
422 XrdOucString lastcn(subject, subject.rfind(
"/CN=") + 4, -1);
423 if (lastcn ==
"proxy" || lastcn ==
"limited proxy") {
445 auto tmprsa = std::make_unique<XrdCryptosslRSA>((EVP_PKEY*)newpki, 1);
453 pki = tmprsa.release();
496 if (subject.length() <= 0) {
500 DEBUG(
"WARNING: no certificate available - cannot extract subject name");
501 return (
const char *)0;
509 return (subject.length() > 0) ? subject.c_str() : (
const char *)0;
519 if (issuer.length() <= 0) {
523 DEBUG(
"WARNING: no certificate available - cannot extract issuer name");
524 return (
const char *)0;
532 return (issuer.length() > 0) ? issuer.c_str() : (
const char *)0;
541 EPNAME(
"X509::IssuerHash");
545 if (issueroldhash.length() <= 0) {
548 char chash[30] = {0};
549 snprintf(chash,
sizeof(chash),
550 "%08lx.0",X509_NAME_hash_old(X509_get_issuer_name(cert)));
551 issueroldhash = chash;
553 DEBUG(
"WARNING: no certificate available - cannot extract issuer hash (md5)");
557 return (issueroldhash.length() > 0) ? issueroldhash.c_str() : (
const char *)0;
561 if (issuerhash.length() <= 0) {
565 char chash[30] = {0};
566 snprintf(chash,
sizeof(chash),
567 "%08lx.0",X509_NAME_hash(X509_get_issuer_name(cert)));
570 DEBUG(
"WARNING: no certificate available - cannot extract issuer hash (default)");
575 return (issuerhash.length() > 0) ? issuerhash.c_str() : (
const char *)0;
584 EPNAME(
"X509::SubjectHash");
588 if (subjectoldhash.length() <= 0) {
591 char chash[30] = {0};
592 snprintf(chash,
sizeof(chash),
593 "%08lx.0",X509_NAME_hash_old(X509_get_subject_name(cert)));
594 subjectoldhash = chash;
596 DEBUG(
"WARNING: no certificate available - cannot extract subject hash (md5)");
600 return (subjectoldhash.length() > 0) ? subjectoldhash.c_str() : (
const char *)0;
604 if (subjecthash.length() <= 0) {
608 char chash[30] = {0};
609 snprintf(chash,
sizeof(chash),
610 "%08lx.0",X509_NAME_hash(X509_get_subject_name(cert)));
613 DEBUG(
"WARNING: no certificate available - cannot extract subject hash (default)");
618 return (subjecthash.length() > 0) ? subjecthash.c_str() : (
const char *)0;
627 if (cert && X509_get_serialNumber(cert)) {
628 BIGNUM *bn = BN_new();
629 ASN1_INTEGER_to_BN(X509_get_serialNumber(cert), bn);
630 char *sn = BN_bn2dec(bn);
631 sernum = strtoll(sn, 0, 10);
645 if (cert && X509_get_serialNumber(cert)) {
646 BIGNUM *bn = BN_new();
647 ASN1_INTEGER_to_BN(X509_get_serialNumber(cert), bn);
648 char *sn = BN_bn2hex(bn);
662 EPNAME(
"X509::GetExtension");
667 DEBUG(
"OID string not defined");
673 DEBUG(
"certificate is not initialized");
678 int numext = X509_get_ext_count(cert);
680 DEBUG(
"certificate has got no extensions");
683 DEBUG(
"certificate has "<<numext<<
" extensions");
687 int nid = OBJ_sn2nid(oid);
688 bool usenid = (nid > 0);
692#if OPENSSL_VERSION_NUMBER < 0x40000000L
693 X509_EXTENSION *wext = 0;
695 const X509_EXTENSION *wext = 0;
697 for (i = 0; i< numext; i++) {
698 wext = X509_get_ext(cert, i);
700 int enid = OBJ_obj2nid(X509_EXTENSION_get_object(wext));
706 OBJ_obj2txt(s,
sizeof(s), X509_EXTENSION_get_object(wext), 1);
716 DEBUG(
"Extension "<<oid<<
" not found");
732 DEBUG(
"serialization already performed:"
733 " return previous result ("<<bucket->size<<
" bytes)");
739 DEBUG(
"certificate is not initialized");
745 BIO *bmem = BIO_new(BIO_s_mem());
747 DEBUG(
"unable to create BIO for memory operations");
752 if (!PEM_write_bio_X509(bmem, cert)) {
753 DEBUG(
"unable to write certificate to memory BIO");
759 int blen = BIO_get_mem_data(bmem, &bdata);
760 DEBUG(
"BIO data: "<<blen<<
" bytes at 0x"<<(
int *)bdata);
766 bucket->SetBuf(bdata, blen);
767 DEBUG(
"result of serialization: "<<bucket->size<<
" bytes");
769 DEBUG(
"unable to create bucket for serialized format");
792 X509 *r = ref ? (X509 *)(ref->
Opaque()) : 0;
793 EVP_PKEY *rk = r ? X509_get_pubkey(r) : 0;
798 int rc = X509_verify(cert, rk);
803 DEBUG(
"signature not OK");
806 DEBUG(
"could not verify signature");
823 X509 *xpi = (X509 *)
Opaque();
827 PRINT(
"we are empty! Do nothing");
833#if OPENSSL_VERSION_NUMBER < 0x40000000L
834 X509_EXTENSION *xpiext = 0;
836 const X509_EXTENSION *xpiext = 0;
838 int npiext = X509_get_ext_count(xpi);
839 PRINT(
"found "<<npiext<<
" extensions ");
841 for (i = 0; i< npiext; i++) {
842 xpiext = X509_get_ext(xpi, i);
844 OBJ_obj2txt(s,
sizeof(s), X509_EXTENSION_get_object(xpiext), 1);
845 int crit = X509_EXTENSION_get_critical(xpiext);
847 PRINT(i <<
": found extension '"<<s<<
"', critical: " << crit);
850 const unsigned char *pp = ASN1_STRING_get0_data(X509_EXTENSION_get_data(xpiext));
851 long length = ASN1_STRING_length(X509_EXTENSION_get_data(xpiext));
852 int ret = FillUnknownExt(&pp, length, dumpunknown);
853 PRINT(
"ret: " << ret);
861int XrdCryptosslX509::FillUnknownExt(
const unsigned char **pp,
long length,
bool dump)
866 const unsigned char *p,*ep,*tot,*op,*opp;
868 int tag, xclass, ret = 0;
871 ASN1_OCTET_STRING *os = 0;
880 while ((p < tot) && (op < p)) {
882 j = ASN1_get_object(&p, &len, &tag, &xclass, length);
887 if (dump)
PRINT(
"ERROR: error in encoding");
895 if (j != (V_ASN1_CONSTRUCTED | 1)) {
896 if (dump)
PRINT(
"PRIM: d="<<depth<<
" hl="<<hl<<
" l="<<len);
898 if (dump)
PRINT(
"CONST: d="<<depth<<
" hl="<<hl<<
" l=inf ");
900 if (!Asn1PrintInfo(tag, xclass, j, (indent) ? depth : 0))
902 if (j & V_ASN1_CONSTRUCTED) {
904 if (dump)
PRINT(
" ");
906 if (dump)
PRINT(
"ERROR:CONST: length is greater than " <<length);
910 if ((j == 0x21) && (len == 0)) {
912 r = FillUnknownExt(&p, (
long)(tot-p), dump);
917 if ((r == 2) || (p >= tot))
922 r = FillUnknownExt(&p, (
long)len, dump);
929 }
else if (xclass != 0) {
931 if (dump)
PRINT(
" ");
934 if ((tag == V_ASN1_PRINTABLESTRING) ||
935 (tag == V_ASN1_T61STRING) ||
936 (tag == V_ASN1_IA5STRING) ||
937 (tag == V_ASN1_VISIBLESTRING) ||
938 (tag == V_ASN1_NUMERICSTRING) ||
939 (tag == V_ASN1_UTF8STRING) ||
940 (tag == V_ASN1_UTCTIME) ||
941 (tag == V_ASN1_GENERALIZEDTIME)) {
943 char *s =
new char[len + 1];
946 if (dump)
PRINT(
"GENERIC:" << s <<
" (len: "<<(
int)len<<
")");
949 if (dump)
PRINT(
"GENERIC: (len: "<<(
int)len<<
")");
951 }
else if (tag == V_ASN1_OBJECT) {
953 if (d2i_ASN1_OBJECT(&o, &opp, len+hl)) {
954 BIO *mem = BIO_new(BIO_s_mem());
955 i2a_ASN1_OBJECT(mem, o);
959 if (dump)
PRINT(
"ERROR:AOBJ: BAD OBJECT");
961 }
else if (tag == V_ASN1_BOOLEAN) {
963 if (dump)
PRINT(
"ERROR:BOOL: Bad boolean");
966 if (dump)
PRINT(
"BOOL:"<< p[0]);
967 }
else if (tag == V_ASN1_BMPSTRING) {
969 }
else if (tag == V_ASN1_OCTET_STRING) {
970 int i, printable = 1;
972 os = d2i_ASN1_OCTET_STRING(0, &opp, len + hl);
973 if (os && ASN1_STRING_length(os) > 0) {
974 opp = ASN1_STRING_get0_data(os);
976 for (i=0; i < ASN1_STRING_length(os); i++) {
977 if (( (opp[i] <
' ') && (opp[i] !=
'\n') &&
978 (opp[i] !=
'\r') && (opp[i] !=
'\t')) || (opp[i] >
'~')) {
985 char *s =
new char[ASN1_STRING_length(os) + 1];
986 memcpy(s, opp, ASN1_STRING_length(os));
987 s[ASN1_STRING_length(os)] = 0;
988 if (dump)
PRINT(
"OBJS:" << s <<
" (len: " << ASN1_STRING_length(os) <<
")");
992 if (!nl)
PRINT(
"OBJS:");
993 BIO *mem = BIO_new(BIO_s_mem());
994 if (BIO_dump_indent(mem, (
const char *)opp, ASN1_STRING_length(os), dump_indent) <= 0) {
995 if (dump)
PRINT(
"ERROR:OBJS: problems dumping to BIO");
1004 ASN1_OCTET_STRING_free(os);
1007 }
else if (tag == V_ASN1_INTEGER) {
1012 bs = d2i_ASN1_INTEGER(0, &opp, len+hl);
1014 if (dump)
PRINT(
"AINT:");
1015 if (ASN1_STRING_type(bs) == V_ASN1_NEG_INTEGER)
1016 if (dump)
PRINT(
"-");
1017 BIO *mem = BIO_new(BIO_s_mem());
1018 for (i = 0; i < ASN1_STRING_length(bs); i++) {
1019 if (BIO_printf(mem,
"%02X", ASN1_STRING_get0_data(bs)[i]) <= 0) {
1020 if (dump)
PRINT(
"ERROR:AINT: problems printf-ing to BIO");
1026 if (ASN1_STRING_length(bs) == 0)
PRINT(
"00");
1028 if (dump)
PRINT(
"ERROR:AINT: BAD INTEGER");
1030 ASN1_INTEGER_free(bs);
1031 }
else if (tag == V_ASN1_ENUMERATED) {
1032 ASN1_ENUMERATED *bs;
1036 bs = d2i_ASN1_ENUMERATED(0, &opp, len+hl);
1038 if (dump)
PRINT(
"AENU:");
1039 if (ASN1_STRING_type(bs) == V_ASN1_NEG_ENUMERATED)
1040 if (dump)
PRINT(
"-");
1041 BIO *mem = BIO_new(BIO_s_mem());
1042 for (i = 0; i < ASN1_STRING_length(bs); i++) {
1043 if (BIO_printf(mem,
"%02X", ASN1_STRING_get0_data(bs)[i]) <= 0) {
1044 if (dump)
PRINT(
"ERROR:AENU: problems printf-ing to BIO");
1050 if (ASN1_STRING_length(bs) == 0)
PRINT(
"00");
1052 if (dump)
PRINT(
"ERROR:AENU: BAD ENUMERATED");
1054 ASN1_ENUMERATED_free(bs);
1057 if (!nl && dump)
PRINT(
" ");
1060 if ((tag == V_ASN1_EOC) && (xclass == 0)) {
1069 if (o) ASN1_OBJECT_free(o);
1070 if (os) ASN1_OCTET_STRING_free(os);
1072 if (dump)
PRINT(
"ret: "<<ret);
1078int XrdCryptosslX509::Asn1PrintInfo(
int tag,
int xclass,
int constructed,
int indent)
1083 static const char fmt[]=
"%-18s";
1084 static const char fmt2[]=
"%2d %-15s";
1086 const char *p, *p2 = 0;
1088 BIO *bp = BIO_new(BIO_s_mem());
1089 if (constructed & V_ASN1_CONSTRUCTED)
1093 if (BIO_write(bp, p, 6) < 6)
1095 BIO_indent(bp, indent, 128);
1098 if ((xclass & V_ASN1_PRIVATE) == V_ASN1_PRIVATE)
1099 BIO_snprintf(str,
sizeof str,
"priv [ %d ] ",tag);
1100 else if ((xclass & V_ASN1_CONTEXT_SPECIFIC) == V_ASN1_CONTEXT_SPECIFIC)
1101 BIO_snprintf(str,
sizeof str,
"cont [ %d ]",tag);
1102 else if ((xclass & V_ASN1_APPLICATION) == V_ASN1_APPLICATION)
1103 BIO_snprintf(str,
sizeof str,
"appl [ %d ]",tag);
1105 BIO_snprintf(str,
sizeof str,
"<ASN1 %d>",tag);
1107 p = ASN1_tag2str(tag);
1110 if (BIO_printf(bp,fmt2,tag,p2) <= 0)
1113 if (BIO_printf(bp, fmt, p) <= 0)
1136 GENERAL_NAMES *gens =
static_cast<GENERAL_NAMES *
>(X509_get_ext_d2i(cert,
1137 NID_subject_alt_name, NULL, NULL));
1151 bool success =
false;
1152 for (
int idx = 0; idx < sk_GENERAL_NAME_num(gens); idx++) {
1155 gen = sk_GENERAL_NAME_value(gens, idx);
1156 if (gen->type != GEN_DNS)
1158 cstr = gen->d.dNSName;
1159 if (ASN1_STRING_type(cstr) != V_ASN1_IA5STRING)
1161 int san_fqdn_len = ASN1_STRING_length(cstr);
1162 if (san_fqdn_len > 255)
1164 memcpy(san_fqdn, ASN1_STRING_get0_data(cstr), san_fqdn_len);
1165 san_fqdn[san_fqdn_len] =
'\0';
1166 if (strlen(san_fqdn) !=
static_cast<size_t>(san_fqdn_len))
1168 DEBUG(
"Comparing SAN " << san_fqdn <<
" with " << fqdn);
1170 DEBUG(
"SAN " << san_fqdn <<
" matches with " << fqdn);
1175 sk_GENERAL_NAME_pop_free(gens, GENERAL_NAME_free);
time_t XrdCryptosslASN1toUTC(const ASN1_TIME *tsn1)
void XrdCryptosslNameOneLine(const X509_NAME *nm, XrdOucString &s)
int XrdCryptosslX509CheckProxy3(XrdCryptoX509 *, XrdOucString &)
int emsg(int rc, char *msg)
const char * SubjectHash()
virtual XrdCryptoX509data Opaque()
const char * IssuerHash()
static bool MatchHostnames(const char *match_pattern, const char *fqdn)
XrdCryptoX509data GetExtension(const char *oid)
int DumpExtensions(bool dumpunknown=0)
virtual ~XrdCryptosslX509()
XrdOucString SerialNumberString()
XrdCryptoX509data Opaque()
bool Verify(XrdCryptoX509 *ref)
virtual bool MatchesSAN(const char *, bool &)
XrdCryptosslX509(const char *cf, const char *kf=0)
void SetPKI(XrdCryptoX509data pki)