00001
00002
00003 const char *XrdCryptosslX509CVSID = "$Id: XrdCryptosslX509.cc 31508 2009-12-02 19:11:01Z brun $";
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include <sys/types.h>
00019 #include <sys/stat.h>
00020 #include <unistd.h>
00021 #include <errno.h>
00022
00023 #include <XrdCrypto/XrdCryptosslRSA.hh>
00024 #include <XrdCrypto/XrdCryptosslX509.hh>
00025 #include <XrdCrypto/XrdCryptosslAux.hh>
00026 #include <XrdCrypto/XrdCryptosslTrace.hh>
00027
00028 #include <openssl/pem.h>
00029
00030
00031 XrdCryptosslX509::XrdCryptosslX509(const char *cf, const char *kf)
00032 : XrdCryptoX509()
00033 {
00034
00035
00036 EPNAME("X509::XrdCryptosslX509_file");
00037
00038
00039 cert = 0;
00040 notbefore = -1;
00041 notafter = -1;
00042 subject = "";
00043 issuer = "";
00044 subjecthash = "";
00045 issuerhash = "";
00046 srcfile = "";
00047 bucket = 0;
00048 pki = 0;
00049
00050
00051 if (!cf) {
00052 DEBUG("file name undefined");
00053 return;
00054 }
00055
00056 struct stat st;
00057 if (stat(cf, &st) != 0) {
00058 if (errno == ENOENT) {
00059 DEBUG("file "<<cf<<" does not exist - do nothing");
00060 } else {
00061 DEBUG("cannot stat file "<<cf<<" (errno: "<<errno<<")");
00062 }
00063 return;
00064 }
00065
00066
00067 FILE *fc = fopen(cf, "r");
00068 if (!fc) {
00069 DEBUG("cannot open file "<<cf<<" (errno: "<<errno<<")");
00070 return;
00071 }
00072
00073
00074 if (!PEM_read_X509(fc, &cert, 0, 0)) {
00075 DEBUG("Unable to load certificate from file");
00076 return;
00077 } else {
00078 DEBUG("certificate successfully loaded");
00079 }
00080
00081
00082 fclose(fc);
00083
00084
00085 srcfile = cf;
00086
00087 Subject();
00088 Issuer();
00089
00090
00091 if (IsCA()) {
00092 type = kCA;
00093 } else {
00094 XrdOucString common(issuer,0,issuer.find('/',issuer.find("/CN=")+1));
00095 if (subject.beginswith(common))
00096 type = kProxy;
00097 else
00098 type = kEEC;
00099 }
00100
00101 EVP_PKEY *evpp = X509_get_pubkey(cert);
00102
00103 if (evpp) {
00104
00105 if (kf) {
00106 if (stat(kf, &st) == -1) {
00107 DEBUG("cannot stat private key file "<<kf<<" (errno:"<<errno<<")");
00108 return;
00109 }
00110 if (!S_ISREG(st.st_mode) || S_ISDIR(st.st_mode) ||
00111 (st.st_mode & (S_IWGRP | S_IWOTH)) != 0 ||
00112 (st.st_mode & (S_IRGRP | S_IROTH)) != 0 ||
00113 (st.st_mode & (S_IWUSR)) != 0) {
00114 DEBUG("private key file "<<kf<<" has wrong permissions "<<
00115 (st.st_mode & 0777) << " (should be 0400)");
00116 return;
00117 }
00118
00119 FILE *fk = fopen(kf, "r");
00120 if (!fk) {
00121 DEBUG("cannot open file "<<kf<<" (errno: "<<errno<<")");
00122 return;
00123 }
00124 if (PEM_read_PrivateKey(fk,&evpp,0,0)) {
00125 DEBUG("RSA key completed ");
00126
00127 if (RSA_check_key(evpp->pkey.rsa) != 0) {
00128
00129 pki = new XrdCryptosslRSA(evpp);
00130 }
00131 } else {
00132 DEBUG("cannot read the key from file");
00133 }
00134
00135 fclose(fk);
00136 }
00137
00138
00139 if (!pki)
00140 pki = new XrdCryptosslRSA(evpp, 0);
00141 } else {
00142 DEBUG("could not access the public key");
00143 }
00144 }
00145
00146
00147 XrdCryptosslX509::XrdCryptosslX509(XrdSutBucket *buck) : XrdCryptoX509()
00148 {
00149
00150 EPNAME("X509::XrdCryptosslX509_bio");
00151
00152
00153 cert = 0;
00154 notbefore = -1;
00155 notafter = -1;
00156 subject = "";
00157 issuer = "";
00158 subjecthash = "";
00159 issuerhash = "";
00160 srcfile = "";
00161 bucket = 0;
00162 pki = 0;
00163
00164
00165 if (!buck) {
00166 DEBUG("got undefined opaque buffer");
00167 return;
00168 }
00169
00170
00171
00172 BIO *bmem = BIO_new(BIO_s_mem());
00173 if (!bmem) {
00174 DEBUG("unable to create BIO for memory operations");
00175 return;
00176 }
00177
00178
00179 int nw = BIO_write(bmem,(const void *)(buck->buffer),buck->size);
00180 if (nw != buck->size) {
00181 DEBUG("problems writing data to memory BIO (nw: "<<nw<<")");
00182 return;
00183 }
00184
00185
00186 if (!PEM_read_bio_X509(bmem,&cert,0,0)) {
00187 DEBUG("unable to read certificate to memory BIO");
00188 return;
00189 }
00190
00191
00192 BIO_free(bmem);
00193
00194
00195 Subject();
00196 Issuer();
00197
00198
00199 if (IsCA()) {
00200 type = kCA;
00201 } else {
00202 XrdOucString common(issuer,0,issuer.find('/',issuer.find("/CN=")+1));
00203 if (subject.beginswith(common))
00204 type = kProxy;
00205 else
00206 type = kEEC;
00207 }
00208
00209 EVP_PKEY *evpp = X509_get_pubkey(cert);
00210
00211 if (evpp) {
00212
00213 if (!pki)
00214 pki = new XrdCryptosslRSA(evpp, 0);
00215 } else {
00216 DEBUG("could not access the public key");
00217 }
00218 }
00219
00220
00221 XrdCryptosslX509::XrdCryptosslX509(X509 *xc) : XrdCryptoX509()
00222 {
00223
00224 EPNAME("X509::XrdCryptosslX509_x509");
00225
00226
00227 cert = 0;
00228 notbefore = -1;
00229 notafter = -1;
00230 subject = "";
00231 issuer = "";
00232 subjecthash = "";
00233 issuerhash = "";
00234 srcfile = "";
00235 bucket = 0;
00236 pki = 0;
00237
00238
00239 if (!xc) {
00240 DEBUG("got undefined X509 object");
00241 return;
00242 }
00243
00244
00245 cert = xc;
00246
00247
00248 Subject();
00249 Issuer();
00250
00251
00252 if (IsCA()) {
00253 type = kCA;
00254 } else {
00255 XrdOucString common(issuer,0,issuer.find('/',issuer.find("/CN=")+1));
00256 if (subject.beginswith(common))
00257 type = kProxy;
00258 else
00259 type = kEEC;
00260 }
00261
00262 EVP_PKEY *evpp = X509_get_pubkey(cert);
00263
00264 if (evpp) {
00265
00266 if (!pki)
00267 pki = new XrdCryptosslRSA(evpp, 0);
00268 } else {
00269 DEBUG("could not access the public key");
00270 }
00271 }
00272
00273
00274 XrdCryptosslX509::~XrdCryptosslX509()
00275 {
00276
00277
00278
00279 if (cert) X509_free(cert);
00280
00281 if (pki) delete pki;
00282 }
00283
00284
00285 void XrdCryptosslX509::SetPKI(XrdCryptoX509data newpki)
00286 {
00287
00288
00289
00290 if (pki)
00291 delete pki;
00292 if (newpki)
00293 pki = new XrdCryptosslRSA((EVP_PKEY *)newpki, 1);
00294
00295 }
00296
00297
00298 int XrdCryptosslX509::NotBefore()
00299 {
00300
00301
00302
00303 if (notbefore < 0) {
00304
00305 if (cert)
00306
00307 notbefore = XrdCryptosslASN1toUTC(X509_get_notBefore(cert));
00308 }
00309
00310 return notbefore;
00311 }
00312
00313
00314 int XrdCryptosslX509::NotAfter()
00315 {
00316
00317
00318
00319 if (notafter < 0) {
00320
00321 if (cert)
00322
00323 notafter = XrdCryptosslASN1toUTC(X509_get_notAfter(cert));
00324 }
00325
00326 return notafter;
00327 }
00328
00329
00330 const char *XrdCryptosslX509::Subject()
00331 {
00332
00333 EPNAME("X509::Subject");
00334
00335
00336 if (subject.length() <= 0) {
00337
00338
00339 if (!cert) {
00340 DEBUG("WARNING: no certificate available - cannot extract subject name");
00341 return (const char *)0;
00342 }
00343
00344
00345 subject = X509_NAME_oneline(X509_get_subject_name(cert), 0, 0);
00346 }
00347
00348
00349 return (subject.length() > 0) ? subject.c_str() : (const char *)0;
00350 }
00351
00352
00353 const char *XrdCryptosslX509::Issuer()
00354 {
00355
00356 EPNAME("X509::Issuer");
00357
00358
00359 if (issuer.length() <= 0) {
00360
00361
00362 if (!cert) {
00363 DEBUG("WARNING: no certificate available - cannot extract issuer name");
00364 return (const char *)0;
00365 }
00366
00367
00368 issuer = X509_NAME_oneline(X509_get_issuer_name(cert), 0, 0);
00369 }
00370
00371
00372 return (issuer.length() > 0) ? issuer.c_str() : (const char *)0;
00373 }
00374
00375
00376 const char *XrdCryptosslX509::IssuerHash()
00377 {
00378
00379 EPNAME("X509::IssuerHash");
00380
00381
00382 if (issuerhash.length() <= 0) {
00383
00384
00385 if (cert) {
00386 char chash[15];
00387 #if OPENSSL_VERSION_NUMBER >= 0x10000000L
00388 sprintf(chash,"%08lx.0",X509_NAME_hash_old(cert->cert_info->issuer));
00389 #else
00390 sprintf(chash,"%08lx.0",X509_NAME_hash(cert->cert_info->issuer));
00391 #endif
00392 issuerhash = chash;
00393 } else {
00394 DEBUG("WARNING: no certificate available - cannot extract issuer hash");
00395 }
00396 }
00397
00398
00399 return (issuerhash.length() > 0) ? issuerhash.c_str() : (const char *)0;
00400 }
00401
00402
00403 const char *XrdCryptosslX509::SubjectHash()
00404 {
00405
00406 EPNAME("X509::SubjectHash");
00407
00408
00409 if (subjecthash.length() <= 0) {
00410
00411
00412 if (cert) {
00413 char chash[15];
00414 #if OPENSSL_VERSION_NUMBER >= 0x10000000L
00415 sprintf(chash,"%08lx.0",X509_NAME_hash_old(cert->cert_info->subject));
00416 #else
00417 sprintf(chash,"%08lx.0",X509_NAME_hash(cert->cert_info->subject));
00418 #endif
00419 subjecthash = chash;
00420 } else {
00421 DEBUG("WARNING: no certificate available - cannot extract subject hash");
00422 }
00423 }
00424
00425
00426 return (subjecthash.length() > 0) ? subjecthash.c_str() : (const char *)0;
00427 }
00428
00429
00430 kXR_int64 XrdCryptosslX509::SerialNumber()
00431 {
00432
00433
00434 kXR_int64 sernum = -1;
00435 if (cert && X509_get_serialNumber(cert)) {
00436 BIGNUM *bn = BN_new();
00437 ASN1_INTEGER_to_BN(X509_get_serialNumber(cert), bn);
00438 char *sn = BN_bn2dec(bn);
00439 sernum = strtoll(sn, 0, 10);
00440 BN_free(bn);
00441 OPENSSL_free(sn);
00442 }
00443
00444 return sernum;
00445 }
00446
00447
00448 XrdOucString XrdCryptosslX509::SerialNumberString()
00449 {
00450
00451
00452 XrdOucString sernum;
00453 if (cert && X509_get_serialNumber(cert)) {
00454 BIGNUM *bn = BN_new();
00455 ASN1_INTEGER_to_BN(X509_get_serialNumber(cert), bn);
00456 char *sn = BN_bn2hex(bn);
00457 sernum = sn;
00458 BN_free(bn);
00459 OPENSSL_free(sn);
00460 }
00461
00462 return sernum;
00463 }
00464
00465
00466 XrdCryptoX509data XrdCryptosslX509::GetExtension(const char *oid)
00467 {
00468
00469
00470 EPNAME("X509::GetExtension");
00471 XrdCryptoX509data ext = 0;
00472
00473
00474 if (!oid) {
00475 DEBUG("OID string not defined");
00476 return ext;
00477 }
00478
00479
00480 if (!cert) {
00481 DEBUG("certificate is not initialized");
00482 return ext;
00483 }
00484
00485
00486 int numext = X509_get_ext_count(cert);
00487 if (numext <= 0) {
00488 DEBUG("certificate has got no extensions");
00489 return ext;
00490 }
00491 DEBUG("certificate has "<<numext<<" extensions");
00492
00493
00494
00495 int nid = OBJ_sn2nid(oid);
00496 bool usenid = (nid > 0);
00497
00498
00499 int i = 0;
00500 X509_EXTENSION *wext = 0;
00501 for (i = 0; i< numext; i++) {
00502 wext = X509_get_ext(cert, i);
00503 if (usenid) {
00504 int enid = OBJ_obj2nid(X509_EXTENSION_get_object(wext));
00505 if (enid == nid)
00506 break;
00507 } else {
00508
00509 char s[256];
00510 OBJ_obj2txt(s, sizeof(s), X509_EXTENSION_get_object(wext), 1);
00511 if (!strcmp(s, oid))
00512 break;
00513 }
00514
00515 wext = 0;
00516 }
00517
00518
00519 if (!wext) {
00520 DEBUG("Extension "<<oid<<" not found");
00521 return ext;
00522 }
00523
00524
00525 return (XrdCryptoX509data)wext;
00526 }
00527
00528
00529 bool XrdCryptosslX509::IsCA()
00530 {
00531
00532 EPNAME("X509::IsCA");
00533
00534
00535 if (!cert) {
00536 DEBUG("certificate is not initialized");
00537 return 0;
00538 }
00539
00540
00541 int numext = X509_get_ext_count(cert);
00542 if (numext <= 0) {
00543 DEBUG("certificate has got no extensions");
00544 return 0;
00545 }
00546 TRACE(ALL,"certificate has "<<numext<<" extensions");
00547
00548 X509_EXTENSION *ext = 0;
00549 int i = 0;
00550 for (; i < numext; i++) {
00551
00552 ext = X509_get_ext(cert,i);
00553
00554 if (OBJ_obj2nid(X509_EXTENSION_get_object(ext)) ==
00555 OBJ_sn2nid("basicConstraints")) {
00556 break;
00557 }
00558
00559 ext = 0;
00560 }
00561
00562
00563 if (!ext)
00564 return 0;
00565
00566
00567 unsigned char *p = ext->value->data;
00568 #ifdef R__SSL_GE_098
00569 BASIC_CONSTRAINTS *bc =
00570 d2i_BASIC_CONSTRAINTS(0, const_cast<const unsigned char**>(&p), ext->value->length);
00571 #else
00572 BASIC_CONSTRAINTS *bc = d2i_BASIC_CONSTRAINTS(0, &p, ext->value->length);
00573 #endif
00574
00575
00576 bool isca = (bc->ca != 0);
00577 if (isca) {
00578 DEBUG("CA certificate");
00579 }
00580
00581
00582 return isca;
00583 }
00584
00585
00586 XrdSutBucket *XrdCryptosslX509::Export()
00587 {
00588
00589 EPNAME("X509::Export");
00590
00591
00592 if (bucket) {
00593 DEBUG("serialization already performed:"
00594 " return previous result ("<<bucket->size<<" bytes)");
00595 return bucket;
00596 }
00597
00598
00599 if (!cert) {
00600 DEBUG("certificate is not initialized");
00601 return 0;
00602 }
00603
00604
00605
00606 BIO *bmem = BIO_new(BIO_s_mem());
00607 if (!bmem) {
00608 DEBUG("unable to create BIO for memory operations");
00609 return 0;
00610 }
00611
00612
00613 if (!PEM_write_bio_X509(bmem, cert)) {
00614 DEBUG("unable to write certificate to memory BIO");
00615 return 0;
00616 }
00617
00618
00619 char *bdata = 0;
00620 int blen = BIO_get_mem_data(bmem, &bdata);
00621 DEBUG("BIO data: "<<blen<<" bytes at 0x"<<(int *)bdata);
00622
00623
00624 bucket = new XrdSutBucket(0,0,kXRS_x509);
00625 if (bucket) {
00626
00627 bucket->SetBuf(bdata, blen);
00628 DEBUG("result of serialization: "<<bucket->size<<" bytes");
00629 } else {
00630 DEBUG("unable to create bucket for serialized format");
00631 BIO_free(bmem);
00632 return 0;
00633 }
00634
00635
00636 BIO_free(bmem);
00637
00638
00639 return bucket;
00640 }
00641
00642
00643 bool XrdCryptosslX509::Verify(XrdCryptoX509 *ref)
00644 {
00645
00646 EPNAME("X509::Verify");
00647
00648
00649 if (!cert)
00650 return 0;
00651
00652
00653 X509 *r = ref ? (X509 *)(ref->Opaque()) : 0;
00654 EVP_PKEY *rk = r ? X509_get_pubkey(r) : 0;
00655 if (!rk)
00656 return 0;
00657
00658
00659 int rc = X509_verify(cert, rk);
00660 if (rc <= 0) {
00661 if (rc == 0) {
00662
00663 DEBUG("signature not OK");
00664 } else {
00665
00666 DEBUG("could not verify signature");
00667 }
00668 return 0;
00669 }
00670
00671 return 1;
00672 }