00001
00002
00003 const char *XrdCryptosslAuxCVSID = "$Id: XrdCryptosslAux.cc 35287 2010-09-14 21:19:35Z ganis $";
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #include <time.h>
00018 #include <errno.h>
00019 #include <stdlib.h>
00020 #include <sys/types.h>
00021 #include <sys/stat.h>
00022
00023 #include <XrdCrypto/XrdCryptoX509Chain.hh>
00024 #include <XrdCrypto/XrdCryptosslAux.hh>
00025 #include <XrdCrypto/XrdCryptosslRSA.hh>
00026 #include <XrdCrypto/XrdCryptosslX509.hh>
00027 #include <XrdCrypto/XrdCryptosslTrace.hh>
00028 #include <openssl/pem.h>
00029
00030
00031 static int gErrVerifyChain = 0;
00032
00033 int XrdCryptosslX509VerifyCB(int ok, X509_STORE_CTX *ctx)
00034 {
00035
00036
00037
00038 gErrVerifyChain = 0;
00039
00040 if (ok != 0) {
00041
00042
00043 gErrVerifyChain = 1;
00044 }
00045
00046
00047 return ok;
00048 }
00049
00050
00051 int XrdCryptosslKDFunLen()
00052 {
00053
00054 return kSslKDFunDefLen;
00055 }
00056
00057
00058 int XrdCryptosslKDFun(const char *pass, int plen, const char *salt, int slen,
00059 char *key, int klen)
00060 {
00061
00062
00063
00064
00065
00066
00067 klen = (klen <= 0) ? 24 : klen;
00068
00069
00070 char *realsalt = (char *)salt;
00071 int realslen = slen;
00072 int it = 10000;
00073
00074
00075 char *ibeg = (char *)memchr(salt+1,'$',slen-1);
00076 if (ibeg) {
00077 char *del = 0;
00078 int newit = strtol(ibeg+1, &del, 10);
00079 if (newit > 0 && del[0] == '$' && errno != ERANGE) {
00080
00081 it = newit;
00082 realsalt = del+1;
00083 realslen = slen - (int)(realsalt-salt);
00084 }
00085 }
00086
00087 PKCS5_PBKDF2_HMAC_SHA1(pass, plen,
00088 (unsigned char *)realsalt, realslen, it,
00089 klen, (unsigned char *)key);
00090 return klen;
00091 }
00092
00093
00094 bool XrdCryptosslX509VerifyCert(XrdCryptoX509 *cert, XrdCryptoX509 *ref)
00095 {
00096
00097
00098
00099 X509 *c = cert ? (X509 *)(cert->Opaque()) : 0;
00100 X509 *r = ref ? (X509 *)(ref->Opaque()) : 0;
00101 EVP_PKEY *rk = r ? X509_get_pubkey(r) : 0;
00102 if (!c || !rk) return 0;
00103
00104
00105 return (X509_verify(c, rk) > 0);
00106 }
00107
00108
00109 bool XrdCryptosslX509VerifyChain(XrdCryptoX509Chain *chain, int &errcode)
00110 {
00111
00112
00113
00114
00115 if (!chain || chain->Size() <= 1)
00116 return 0;
00117
00118
00119 X509_STORE *store = X509_STORE_new();
00120 if (!store)
00121 return 0;
00122
00123
00124 X509_STORE_set_verify_cb_func(store,0);
00125
00126
00127 XrdCryptoX509 *cert = chain->Begin();
00128 if (cert->type != XrdCryptoX509::kCA && cert->Opaque())
00129 return 0;
00130 X509_STORE_add_cert(store, (X509 *)(cert->Opaque()));
00131
00132
00133 STACK_OF(X509) *stk = sk_X509_new_null();
00134 if (!stk)
00135 return 0;
00136
00137
00138 X509 *cref = 0;
00139 while ((cert = chain->Next()) && cert->Opaque()) {
00140 if (!cref)
00141 cref = (X509 *)(cert->Opaque());
00142 sk_X509_push(stk, (X509 *)(cert->Opaque()));
00143 }
00144
00145
00146 #if OPENSSL_VERSION_NUMBER >= 0x10000000L
00147 if (sk_X509_num(stk) != chain->Size() - 1)
00148 #else
00149 if (sk_num(stk) != chain->Size() - 1)
00150 #endif
00151 return 0;
00152
00153
00154 X509_STORE_CTX *ctx = X509_STORE_CTX_new();
00155 if (!ctx)
00156 return 0;
00157
00158
00159 X509_STORE_CTX_init(ctx, store, cref, stk);
00160
00161
00162 bool verify_ok = (X509_verify_cert(ctx) == 1);
00163
00164
00165 errcode = 0;
00166 if (!verify_ok)
00167 errcode = gErrVerifyChain;
00168
00169 return verify_ok;
00170 }
00171
00172
00173 XrdSutBucket *XrdCryptosslX509ExportChain(XrdCryptoX509Chain *chain,
00174 bool withprivatekey)
00175 {
00176
00177 EPNAME("X509ExportChain");
00178 XrdSutBucket *bck = 0;
00179
00180
00181 if (!chain || chain->Size() <= 0) {
00182 DEBUG("chain undefined or empty: nothing to export");
00183 return bck;
00184 }
00185
00186
00187 if (chain->Size() == 1 && chain->Begin()->type == XrdCryptoX509::kCA &&
00188 !strcmp(chain->Begin()->IssuerHash(),chain->Begin()->SubjectHash())) {
00189 DEBUG("chain contains only a CA certificate: nothing to export");
00190 return bck;
00191 }
00192
00193
00194 BIO *bmem = BIO_new(BIO_s_mem());
00195 if (!bmem) {
00196 DEBUG("unable to create BIO for memory operations");
00197 return bck;
00198 }
00199
00200
00201 chain->Reorder();
00202
00203
00204 XrdCryptoX509 *c = chain->End();
00205 if (!PEM_write_bio_X509(bmem, (X509 *)c->Opaque())) {
00206 DEBUG("error while writing proxy certificate");
00207 BIO_free(bmem);
00208 return bck;
00209 }
00210
00211 if (withprivatekey) {
00212 XrdCryptoRSA *k = c->PKI();
00213 if (k->status == XrdCryptoRSA::kComplete) {
00214 if (!PEM_write_bio_PrivateKey(bmem, (EVP_PKEY *)(k->Opaque()),
00215 0, 0, 0, 0, 0)) {
00216 DEBUG("error while writing proxy private key");
00217 BIO_free(bmem);
00218 return bck;
00219 }
00220 }
00221 }
00222
00223 while ((c = chain->SearchBySubject(c->Issuer()))) {
00224 if (c->type == XrdCryptoX509::kCA) {
00225 DEBUG("Encountered CA in chain; breaking. Subject: " << c->Subject());
00226 break;
00227 }
00228 if (strcmp(c->IssuerHash(), c->SubjectHash())) {
00229
00230 if (!PEM_write_bio_X509(bmem, (X509 *)c->Opaque())) {
00231 DEBUG("error while writing proxy certificate");
00232 BIO_free(bmem);
00233 return bck;
00234 }
00235 } else {
00236 DEBUG("Encountered self-signed CA in chain; breaking. Subject: " << c->Subject());
00237 break;
00238 }
00239 }
00240
00241
00242 char *bdata = 0;
00243 int blen = BIO_get_mem_data(bmem, &bdata);
00244 DEBUG("BIO data: "<<blen<<" bytes at 0x"<<(int *)bdata);
00245
00246
00247 bck = new XrdSutBucket(0, 0, kXRS_x509);
00248 if (bck) {
00249
00250 bck->SetBuf(bdata, blen);
00251 DEBUG("result of serialization: "<<bck->size<<" bytes");
00252 } else {
00253 DEBUG("unable to create bucket for serialized format");
00254 BIO_free(bmem);
00255 return bck;
00256 }
00257
00258
00259 BIO_free(bmem);
00260
00261
00262 return bck;
00263 }
00264
00265
00266 int XrdCryptosslX509ChainToFile(XrdCryptoX509Chain *ch, const char *fn)
00267 {
00268
00269 EPNAME("X509ChainToFile");
00270
00271
00272 if (!ch || !fn) {
00273 DEBUG("Invalid inputs");
00274 return -1;
00275 }
00276
00277
00278 FILE *fp = fopen(fn,"w");
00279 if (!fp) {
00280 DEBUG("cannot open file to save chain (file: "<<fn<<")");
00281 return -1;
00282 }
00283 int ifp = fileno(fp);
00284 if (ifp == -1) {
00285 DEBUG("got invalid file descriptor (file: "<<fn<<")");
00286 fclose(fp);
00287 return -1;
00288 }
00289
00290
00291 { XrdSutFileLocker fl(ifp,XrdSutFileLocker::kExcl);
00292
00293
00294 if (!fl.IsValid()) {
00295 DEBUG("could not lock file: "<<fn<<")");
00296 fclose(fp);
00297 return -1;
00298 }
00299
00300
00301 if (fchmod(ifp, 0600) == -1) {
00302 DEBUG("cannot set permissions on file: "<<fn<<" (errno: "<<errno<<")");
00303 fclose(fp);
00304 return -1;
00305 }
00306
00307
00308 ch->Reorder();
00309
00310
00311 XrdCryptoX509 *c = ch->End();
00312 if (PEM_write_X509(fp, (X509 *)c->Opaque()) != 1) {
00313 DEBUG("error while writing proxy certificate");
00314 fclose(fp);
00315 return -1;
00316 }
00317
00318 XrdCryptoRSA *k = c->PKI();
00319 if (k->status == XrdCryptoRSA::kComplete) {
00320 if (PEM_write_PrivateKey(fp, (EVP_PKEY *)(k->Opaque()),
00321 0, 0, 0, 0, 0) != 1) {
00322 DEBUG("error while writing proxy private key");
00323 fclose(fp);
00324 return -1;
00325 }
00326 }
00327
00328 while ((c = ch->SearchBySubject(c->Issuer())) && c->type != XrdCryptoX509::kCA) {
00329
00330 if (PEM_write_X509(fp, (X509 *)c->Opaque()) != 1) {
00331 DEBUG("error while writing proxy certificate");
00332 fclose(fp);
00333 return -1;
00334 }
00335 }
00336 }
00337
00338
00339 fclose(fp);
00340
00341
00342 return 0;
00343 }
00344
00345
00346 int XrdCryptosslX509ParseFile(const char *fname,
00347 XrdCryptoX509Chain *chain)
00348 {
00349
00350
00351
00352
00353 EPNAME("X509ParseFile");
00354 int nci = 0;
00355
00356
00357 if (!fname) {
00358 DEBUG("file name undefined: can do nothing");
00359 return nci;
00360 }
00361
00362
00363 if (!chain) {
00364 DEBUG("chain undefined: can do nothing");
00365 return nci;
00366 }
00367
00368
00369
00370
00371 FILE *fcer = fopen(fname, "r");
00372 if (!fcer) {
00373 DEBUG("unable to open file (errno: "<<errno<<")");
00374 return nci;
00375 }
00376
00377
00378 X509 *xcer = 0;
00379 while (PEM_read_X509(fcer, &xcer, 0, 0)) {
00380
00381 XrdCryptoX509 *c = new XrdCryptosslX509(xcer);
00382 if (c) {
00383 chain->PushBack(c);
00384 nci++;
00385 DEBUG("certificate added to the chain - ord: "<<chain->Size());
00386 } else {
00387 DEBUG("could not create certificate: memory exhausted?");
00388 fclose(fcer);
00389 return nci;
00390 }
00391 xcer = 0;
00392 }
00393
00394
00395
00396 if (nci) {
00397 rewind(fcer);
00398 RSA *rsap = 0;
00399 if (!PEM_read_RSAPrivateKey(fcer, &rsap, 0, 0)) {
00400 DEBUG("no RSA private key found in file "<<fname);
00401 } else {
00402 DEBUG("found a RSA private key in file "<<fname);
00403
00404
00405
00406 bool ok = 1;
00407 BIO *bkey = BIO_new(BIO_s_mem());
00408 if (!bkey) {
00409 DEBUG("unable to create BIO for key completion");
00410 ok = 0;
00411 }
00412 if (ok) {
00413
00414 if (!PEM_write_bio_RSAPrivateKey(bkey,rsap,0,0,0,0,0)) {
00415 DEBUG("unable to write RSA private key to bio");
00416 ok = 0;
00417 }
00418 }
00419 RSA_free(rsap);
00420 if (ok) {
00421
00422 XrdCryptoX509 *cert = chain->Begin();
00423 while (cert->Opaque()) {
00424 if (cert->type != XrdCryptoX509::kCA) {
00425
00426 EVP_PKEY *evpp = X509_get_pubkey((X509 *)(cert->Opaque()));
00427 if (evpp) {
00428 #if OPENSSL_VERSION_NUMBER >= 0x10000000L
00429
00430 if (PEM_read_bio_RSAPrivateKey(bkey,&(evpp->pkey.rsa),0,0)) {
00431 #else
00432 if (PEM_read_bio_PrivateKey(bkey,&evpp,0,0)) {
00433 #endif
00434 DEBUG("RSA key completed ");
00435
00436 int rc = RSA_check_key(evpp->pkey.rsa);
00437 if (rc != 0) {
00438
00439 cert->SetPKI((XrdCryptoX509data)evpp);
00440
00441 cert->PKI()->status = XrdCryptoRSA::kComplete;
00442 break;
00443 }
00444 }
00445 }
00446 }
00447
00448 cert = chain->Next();
00449 }
00450 }
00451
00452 BIO_free(bkey);
00453 }
00454 }
00455
00456
00457 fclose(fcer);
00458
00459
00460 return nci;
00461 }
00462
00463
00464 int XrdCryptosslX509ParseBucket(XrdSutBucket *b, XrdCryptoX509Chain *chain)
00465 {
00466
00467
00468 EPNAME("X509ParseBucket");
00469 int nci = 0;
00470
00471
00472 if (!b || b->size <= 0) {
00473 DEBUG("bucket undefined or empty: can do nothing");
00474 return nci;
00475 }
00476
00477
00478 if (!chain) {
00479 DEBUG("chain undefined: can do nothing");
00480 return nci;
00481 }
00482
00483
00484 BIO *bmem = BIO_new(BIO_s_mem());
00485 if (!bmem) {
00486 DEBUG("unable to create BIO to import certificates");
00487 return nci;
00488 }
00489
00490
00491 if (BIO_write(bmem,(const void *)(b->buffer),b->size) != b->size) {
00492 DEBUG("problems writing data to BIO");
00493 BIO_free(bmem);
00494 return nci;
00495 }
00496
00497
00498 X509 *xcer = 0;
00499 while (PEM_read_bio_X509(bmem,&xcer,0,0)) {
00500
00501
00502 XrdCryptoX509 *c = new XrdCryptosslX509(xcer);
00503 if (c) {
00504 chain->PushBack(c);
00505 nci++;
00506 DEBUG("certificate added to the chain - ord: "<<chain->Size());
00507 } else {
00508 DEBUG("could not create certificate: memory exhausted?");
00509 BIO_free(bmem);
00510 return nci;
00511 }
00512
00513 xcer = 0;
00514 }
00515
00516
00517
00518
00519
00520 if (nci && BIO_write(bmem,(const void *)(b->buffer),b->size) == b->size) {
00521 RSA *rsap = 0;
00522 if (!PEM_read_bio_RSAPrivateKey(bmem, &rsap, 0, 0)) {
00523 DEBUG("no RSA private key found in bucket ");
00524 } else {
00525 DEBUG("found a RSA private key in bucket ");
00526
00527
00528
00529 bool ok = 1;
00530 BIO *bkey = BIO_new(BIO_s_mem());
00531 if (!bkey) {
00532 DEBUG("unable to create BIO for key completion");
00533 ok = 0;
00534 }
00535 if (ok) {
00536
00537 if (!PEM_write_bio_RSAPrivateKey(bkey,rsap,0,0,0,0,0)) {
00538 DEBUG("unable to write RSA private key to bio");
00539 ok = 0;
00540 }
00541 }
00542 RSA_free(rsap);
00543 if (ok) {
00544
00545 XrdCryptoX509 *cert = chain->Begin();
00546 while (cert->Opaque()) {
00547 if (cert->type != XrdCryptoX509::kCA) {
00548
00549 EVP_PKEY *evpp = X509_get_pubkey((X509 *)(cert->Opaque()));
00550 if (evpp) {
00551 if (PEM_read_bio_PrivateKey(bkey,&evpp,0,0)) {
00552 DEBUG("RSA key completed ");
00553
00554 int rc = RSA_check_key(evpp->pkey.rsa);
00555 if (rc != 0) {
00556
00557 cert->SetPKI((XrdCryptoX509data)evpp);
00558
00559 cert->PKI()->status = XrdCryptoRSA::kComplete;
00560 break;
00561 }
00562 }
00563 }
00564 }
00565
00566 cert = chain->Next();
00567 }
00568 }
00569
00570 BIO_free(bkey);
00571 }
00572 }
00573
00574
00575 BIO_free(bmem);
00576
00577
00578 return nci;
00579 }
00580
00581
00582 int XrdCryptosslASN1toUTC(ASN1_TIME *tsn1)
00583 {
00584
00585
00586
00587 int etime = -1;
00588
00589
00590
00591 if (!tsn1) return etime;
00592
00593
00594
00595
00596
00597
00598 struct tm ltm;
00599 char zz;
00600 if ((sscanf((const char *)(tsn1->data),
00601 "%02d%02d%02d%02d%02d%02d%c",
00602 &(ltm.tm_year), &(ltm.tm_mon), &(ltm.tm_mday),
00603 &(ltm.tm_hour), &(ltm.tm_min), &(ltm.tm_sec),
00604 &zz) != 7) || (zz != 'Z')) {
00605 return -1;
00606 }
00607
00608 ltm.tm_wday = 0;
00609 ltm.tm_yday = 0;
00610 ltm.tm_isdst = -1;
00611
00612
00613 if (ltm.tm_year < 90)
00614 ltm.tm_year += 100;
00615
00616
00617 (ltm.tm_mon)--;
00618
00619
00620 etime = mktime(<m);
00621
00622
00623 time_t now = time(0);
00624 struct tm ltn, gtn;
00625 if (!localtime_r(&now, <n)) return etime;
00626 if (!gmtime_r(&now, >n)) return etime;
00627
00628
00629 int tzcor = (int) difftime(mktime(<n), mktime(>n));
00630
00631
00632 etime += tzcor;
00633
00634
00635 return etime;
00636 }