00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053 #include "grst_verifycallback.h"
00054 #include "gridsite.h"
00055 #include <openssl/x509v3.h>
00056 #include <string.h>
00057
00058 X509_STORE* grst_store=NULL;
00059 int grst_verify=0;
00060 int grst_depth=0;
00061 char* grst_cadir = "/etc/grid-certificates/certificates";
00062 char* grst_vomsdir = "/etc/grid-certificates/vomsdir";
00063
00064
00065 int ssl_callback_SSLVerify(int ok, X509_STORE_CTX *ctx);
00066 int ssl_callback_SSLVerify_CRL(int ok, X509_STORE_CTX *ctx);
00067
00068
00069 int GRST_X509_check_issued_wrapper(X509_STORE_CTX *ctx, X509 *x, X509 *issuer)
00070
00071
00072 {
00073 int ret;
00074 ret = X509_check_issued(issuer, x);
00075 if (ret == X509_V_OK)
00076 return 1;
00077
00078
00079
00080 if ((ret == X509_V_ERR_KEYUSAGE_NO_CERTSIGN) &&
00081 (X509_NAME_cmp(X509_get_subject_name(issuer),
00082 X509_get_subject_name(x)) != 0)) return 1;
00083
00084
00085 #if OPENSSL_VERSION_NUMBER < 0x00908000
00086 if (!(ctx->flags & X509_V_FLAG_CB_ISSUER_CHECK)) return 0;
00087 #else
00088 if (!(ctx->param->flags & X509_V_FLAG_CB_ISSUER_CHECK)) return 0;
00089 #endif
00090
00091 ctx->error = ret;
00092 ctx->current_cert = x;
00093 ctx->current_issuer = issuer;
00094 return ctx->verify_cb(0, ctx);
00095 }
00096
00097
00098 int GRST_verify_cert_wrapper(X509_STORE_CTX *ctx, void *p)
00099
00100
00101
00102
00103
00104
00105
00106 {
00107 ctx->check_issued = GRST_X509_check_issued_wrapper;
00108 #ifdef R__SSL_GE_098
00109 X509_STORE_CTX_set_flags(ctx, X509_V_FLAG_ALLOW_PROXY_CERTS);
00110 #endif
00111 return X509_verify_cert(ctx);
00112 }
00113
00114 int GRST_callback_SSLVerify_wrapper(int ok, X509_STORE_CTX *ctx)
00115 {
00116 SSL *ssl = (SSL *) X509_STORE_CTX_get_app_data(ctx);
00117 int errnum = X509_STORE_CTX_get_error(ctx);
00118 int errdepth = X509_STORE_CTX_get_error_depth(ctx);
00119 int returned_ok;
00120 STACK_OF(X509) *certstack;
00121 GRSTx509Chain *grst_chain;
00122 GRSTx509Chain *grst_old_chain;
00123
00124
00125
00126
00127
00128
00129 if (errnum == X509_V_ERR_INVALID_CA)
00130 {
00131 GRSTerrorLog(GRST_LOG_DEBUG,"Skip invalid CA error, since we will check again at errdepth=0");
00132 ok = TRUE;
00133 errnum = X509_V_OK;
00134 X509_STORE_CTX_set_error(ctx, errnum);
00135 }
00136
00137
00138
00139
00140
00141 #ifndef X509_V_ERR_UNHANDLED_CRITICAL_EXTENSION
00142 #define X509_V_ERR_UNHANDLED_CRITICAL_EXTENSION 34
00143 #endif
00144 if (errnum == X509_V_ERR_UNHANDLED_CRITICAL_EXTENSION)
00145 {
00146 if (GRSTx509KnownCriticalExts(X509_STORE_CTX_get_current_cert(ctx))
00147 == GRST_RET_OK)
00148 {
00149 GRSTerrorLog(GRST_LOG_DEBUG,"GRSTx509KnownCriticalExts() accepts previously unhandled Critical Extension(GSI Proxy?)");
00150 ok = TRUE;
00151 errnum = X509_V_OK;
00152 X509_STORE_CTX_set_error(ctx, errnum);
00153 }
00154 }
00155
00156 if (errnum == X509_V_ERR_INVALID_PURPOSE ) {
00157 GRSTerrorLog(GRST_LOG_DEBUG,"GRSTx509 invalid purpose error ignored ");
00158 ok = TRUE;
00159 errnum = X509_V_OK;
00160 X509_STORE_CTX_set_error(ctx, errnum);
00161 }
00162
00163 returned_ok = ssl_callback_SSLVerify(ok, ctx);
00164
00165
00166 errnum = X509_STORE_CTX_get_error(ctx);
00167
00168 if ((errdepth == 0) && (errnum == X509_V_OK))
00169
00170
00171
00172
00173
00174 {
00175 certstack = (STACK_OF(X509) *) X509_STORE_CTX_get_chain(ctx);
00176
00177 errnum = GRSTx509ChainLoadCheck(&grst_chain, certstack, NULL,
00178 grst_cadir,
00179 grst_vomsdir);
00180
00181 if (errnum != X509_V_OK)
00182 {
00183 GRSTerrorLog(GRST_LOG_ERR,"Invalid certificate chain reported by GRSTx509CheckChain() %s\n", X509_verify_cert_error_string(errnum));
00184 ok = FALSE;
00185 }
00186 else
00187 {
00188 GRSTerrorLog(GRST_LOG_DEBUG,"Valid certificate chain reported by GRSTx509ChainLoadCheck()\n");
00189 }
00190
00191
00192 if ((grst_old_chain = SSL_get_app_data(ssl))) {
00193 SSL_set_app_data(ssl,grst_chain);
00194 GRSTerrorLog(GRST_LOG_INFO,"Free Chain %llx", grst_old_chain);
00195 GRSTx509ChainFree(grst_old_chain);
00196 } else {
00197 SSL_set_app_data(ssl,grst_chain);
00198 }
00199 }
00200
00201 return returned_ok;
00202 }
00203
00204
00205
00206
00207
00208
00209 void GRST_print_ssl_creds(void *in_chain)
00210 {
00211 int i= 0;
00212 int lowest_voms_delegation = 65535;
00213 GRSTx509Chain *grst_chain = (GRSTx509Chain*) in_chain;
00214 GRSTx509Cert *grst_cert = NULL;
00215
00216
00217
00218 for (grst_cert = grst_chain->firstcert;
00219 grst_cert != NULL; grst_cert = grst_cert->next)
00220 {
00221 if (grst_cert->type == GRST_CERT_TYPE_VOMS)
00222 {
00223
00224
00225 GRSTerrorLog(GRST_LOG_DEBUG,"Recording VOMS delegation %d\n",grst_cert->delegation);
00226 lowest_voms_delegation = grst_cert->delegation;
00227 }
00228 else if ((grst_cert->type == GRST_CERT_TYPE_EEC) ||
00229 (grst_cert->type == GRST_CERT_TYPE_PROXY))
00230 {
00231 GRSTerrorLog(GRST_LOG_INFO,"(%d) dn: %s\n",i,grst_cert->dn);
00232 GRSTerrorLog(GRST_LOG_INFO,"notbefore=%ld notafter=%ld delegation=%d nist-loa=%d\n",grst_cert->notbefore,grst_cert->notafter,grst_cert->delegation);
00233 ++i;
00234 }
00235 }
00236
00237 for (grst_cert = grst_chain->firstcert;
00238 grst_cert != NULL; grst_cert = grst_cert->next)
00239 {
00240 if ((grst_cert->type == GRST_CERT_TYPE_VOMS) &&
00241 (grst_cert->delegation == lowest_voms_delegation))
00242 {
00243
00244 GRSTerrorLog(GRST_LOG_INFO,"fqan:%s\n",grst_cert->value);
00245 GRSTerrorLog(GRST_LOG_INFO,"notbefore=%ld notafter=%ld delegation=%d nist-loa=%d\n",grst_cert->notbefore,grst_cert->notafter,grst_cert->delegation);
00246 ++i;
00247 }
00248 }
00249 }
00250
00251
00252 char* GRST_get_voms_roles_and_free(void* in_chain)
00253 {
00254 int i, lowest_voms_delegation = 65535;
00255 GRSTx509Chain *grst_chain = (GRSTx509Chain*) in_chain;
00256 GRSTx509Cert *grst_cert = NULL;
00257
00258 char* voms_roles = (char*) malloc(16384);
00259 voms_roles[0] =0;
00260
00261 if (!voms_roles) {
00262 return NULL;
00263 }
00264
00265
00266
00267 for (grst_cert = grst_chain->firstcert;
00268 grst_cert != NULL; grst_cert = grst_cert->next)
00269 {
00270 if (grst_cert->type == GRST_CERT_TYPE_VOMS)
00271 {
00272
00273
00274 lowest_voms_delegation = grst_cert->delegation;
00275 }
00276 else if ((grst_cert->type == GRST_CERT_TYPE_EEC) ||
00277 (grst_cert->type == GRST_CERT_TYPE_PROXY))
00278 {
00279 ++i;
00280 }
00281 }
00282
00283 for (grst_cert = grst_chain->firstcert;
00284 grst_cert != NULL; grst_cert = grst_cert->next)
00285 {
00286 if ((grst_cert->type == GRST_CERT_TYPE_VOMS) &&
00287 (grst_cert->delegation == lowest_voms_delegation))
00288 {
00289
00290 GRSTerrorLog(GRST_LOG_DEBUG,"fqan:%s\n",grst_cert->value);
00291
00292
00293
00294
00295
00296
00297
00298
00299 strcat(voms_roles,grst_cert->value);
00300 strcat(voms_roles,":");
00301
00302 GRSTerrorLog(GRST_LOG_DEBUG,"notbefore=%ld notafter=%ld delegation=%d nist-loa=%d\n",grst_cert->notbefore,grst_cert->notafter,grst_cert->delegation);
00303 ++i;
00304 }
00305 }
00306
00307 if (strlen(voms_roles)) {
00308
00309 voms_roles[strlen(voms_roles)-1] = 0;
00310 }
00311
00312
00313 if (grst_chain) {
00314 GRSTerrorLog(GRST_LOG_INFO,"Free Chain %llx", grst_chain);
00315 GRSTx509ChainFree(grst_chain);
00316 }
00317 return voms_roles;
00318 }
00319
00320 void GRST_free_chain(void* in_chain) {
00321 GRSTx509Chain *grst_chain = (GRSTx509Chain*) in_chain;
00322 if (grst_chain)
00323 GRSTx509ChainFree(grst_chain);
00324 }
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337
00338
00339
00340
00341 int ssl_callback_SSLVerify(int ok, X509_STORE_CTX *ctx)
00342 {
00343 X509 *xs;
00344 int errnum;
00345 int errdepth;
00346 char *cp;
00347 char *cp2;
00348 int depth;
00349
00350
00351
00352
00353 SSL *ssl = (SSL *) X509_STORE_CTX_get_app_data(ctx);
00354
00355
00356
00357
00358 xs = X509_STORE_CTX_get_current_cert(ctx);
00359 errnum = X509_STORE_CTX_get_error(ctx);
00360 errdepth = X509_STORE_CTX_get_error_depth(ctx);
00361
00362
00363
00364
00365 cp = X509_NAME_oneline(X509_get_subject_name(xs), NULL, 0);
00366 cp2 = X509_NAME_oneline(X509_get_issuer_name(xs), NULL, 0);
00367
00368 GRSTerrorLog(GRST_LOG_DEBUG,
00369 "Certificate Verification: depth: %d, subject: %s, issuer: %s\n",
00370 errdepth, cp != NULL ? cp : "-unknown-",
00371 cp2 != NULL ? cp2 : "-unknown");
00372
00373
00374 if (cp)
00375 OPENSSL_free(cp);
00376 if (cp2)
00377 OPENSSL_free(cp2);
00378
00379
00380
00381
00382
00383 if ( ( errnum == X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT
00384 || errnum == X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN
00385 || errnum == X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY
00386 #if SSL_LIBRARY_VERSION >= 0x00905000
00387 || errnum == X509_V_ERR_CERT_UNTRUSTED
00388 #endif
00389 || errnum == X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE )
00390 && grst_verify == GRST_VERIFY_OPTIONAL_NO_CA ) {
00391 GRSTerrorLog(GRST_LOG_ERR,
00392 "Certificate Verification: Verifiable Issuer is configured as "
00393 "optional, therefore we're accepting the certificate\n");
00394 SSL_set_verify_result(ssl, X509_V_OK);
00395 ok = TRUE;
00396 }
00397
00398
00399
00400
00401
00402 if (ok) {
00403 ok = ssl_callback_SSLVerify_CRL(ok, ctx);
00404 if (!ok)
00405 errnum = X509_STORE_CTX_get_error(ctx);
00406 }
00407
00408
00409
00410
00411 if (!ok) {
00412 GRSTerrorLog(GRST_LOG_ERR,"Certificate Verification: Error (%d): %s\n",
00413 errnum, X509_verify_cert_error_string(errnum));
00414 }
00415
00416
00417
00418
00419
00420 depth = grst_depth;
00421
00422 if (errdepth > depth) {
00423 GRSTerrorLog(GRST_LOG_ERR,
00424 "Certificate Verification: Certificate Chain too long "
00425 "(chain has %d certificates, but maximum allowed are only %d)\n",
00426 errdepth, depth);
00427 ok = FALSE;
00428 }
00429
00430
00431
00432
00433 return (ok);
00434 }
00435
00436 int ssl_callback_SSLVerify_CRL(
00437 int ok, X509_STORE_CTX *ctx)
00438 {
00439 X509_OBJECT obj;
00440 X509_NAME *subject;
00441 X509_NAME *issuer;
00442 X509 *xs;
00443 X509_CRL *crl;
00444 X509_REVOKED *revoked;
00445 EVP_PKEY *pubkey;
00446 long serial;
00447 int i, n, rc;
00448 char *cp;
00449 ASN1_TIME *t;
00450
00451
00452
00453
00454
00455 GRSTerrorLog(GRST_LOG_DEBUG,"Checking certificate revocation lists\n");
00456
00457
00458 xs = X509_STORE_CTX_get_current_cert(ctx);
00459 subject = X509_get_subject_name(xs);
00460 issuer = X509_get_issuer_name(xs);
00461
00462
00463
00464
00465
00466
00467
00468
00469
00470
00471
00472
00473
00474
00475
00476
00477
00478
00479
00480
00481
00482
00483
00484
00485
00486
00487
00488
00489
00490
00491
00492
00493
00494
00495
00496
00497
00498
00499
00500
00501
00502
00503
00504
00505 if (!grst_store) {
00506 return 1;
00507 }
00508
00509
00510
00511
00512
00513
00514 memset((char *)&obj, 0, sizeof(obj));
00515
00516 rc = SSL_X509_STORE_lookup(grst_store,X509_LU_CRL, subject, &obj);
00517
00518 crl = obj.data.crl;
00519 if (rc > 0 && crl != NULL) {
00520 GRSTerrorLog(GRST_LOG_DEBUG,"CRL lookup ...");
00521
00522
00523
00524 pubkey = X509_get_pubkey(xs);
00525 if (X509_CRL_verify(crl, pubkey) <= 0) {
00526 GRSTerrorLog(GRST_LOG_ERR,"Invalid signature on CRL\n");
00527 X509_STORE_CTX_set_error(ctx, X509_V_ERR_CRL_SIGNATURE_FAILURE);
00528 X509_OBJECT_free_contents(&obj);
00529 if (pubkey != NULL)
00530 EVP_PKEY_free(pubkey);
00531 return 0;
00532 }
00533
00534 if (pubkey != NULL)
00535 EVP_PKEY_free(pubkey);
00536
00537
00538
00539
00540 if ((t = X509_CRL_get_nextUpdate(crl)) == NULL) {
00541 GRSTerrorLog(GRST_LOG_ERR,"Found CRL has invalid enxtUpdate field\n");
00542 X509_STORE_CTX_set_error(ctx, X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD);
00543 X509_OBJECT_free_contents(&obj);
00544 return 0;
00545 }
00546 if (X509_cmp_current_time(t) < 0) {
00547 GRSTerrorLog(GRST_LOG_ERR,"Found CRL is expired - "
00548 "revoking all certificates until you get updated CRL\n");
00549 X509_STORE_CTX_set_error(ctx, X509_V_ERR_CRL_HAS_EXPIRED);
00550 X509_OBJECT_free_contents(&obj);
00551 return 0;
00552 }
00553 X509_OBJECT_free_contents(&obj);
00554 }
00555
00556
00557
00558
00559
00560
00561 memset((char *)&obj, 0, sizeof(obj));
00562 rc = SSL_X509_STORE_lookup(grst_store,X509_LU_CRL, issuer, &obj);
00563 crl = obj.data.crl;
00564 if (rc > 0 && crl != NULL) {
00565
00566
00567
00568 #if SSL_LIBRARY_VERSION < 0x00904000
00569 n = sk_num(X509_CRL_get_REVOKED(crl));
00570 #else
00571 n = sk_X509_REVOKED_num(X509_CRL_get_REVOKED(crl));
00572 #endif
00573 for (i = 0; i < n; i++) {
00574 #if SSL_LIBRARY_VERSION < 0x00904000
00575 revoked = (X509_REVOKED *)sk_value(X509_CRL_get_REVOKED(crl), i);
00576 #else
00577 revoked = sk_X509_REVOKED_value(X509_CRL_get_REVOKED(crl), i);
00578 #endif
00579 if (ASN1_INTEGER_cmp(revoked->serialNumber, X509_get_serialNumber(xs)) == 0) {
00580 serial = ASN1_INTEGER_get(revoked->serialNumber);
00581 cp = X509_NAME_oneline(issuer, NULL, 0);
00582 GRSTerrorLog(GRST_LOG_ERR,
00583 "Certificate with serial %ld (0x%lX) "
00584 "revoked per CRL from issuer %s\n",
00585 serial, serial, cp);
00586 OPENSSL_free(cp);
00587
00588 X509_STORE_CTX_set_error(ctx, X509_V_ERR_CERT_REVOKED);
00589 X509_OBJECT_free_contents(&obj);
00590 return 0;
00591 }
00592 }
00593 X509_OBJECT_free_contents(&obj);
00594 }
00595 return 1;
00596 }
00597
00598
00599
00600
00601
00602
00603
00604 X509_STORE *SSL_X509_STORE_create(char *cpFile, char *cpPath)
00605 {
00606 X509_STORE *pStore;
00607 X509_LOOKUP *pLookup;
00608
00609 if (cpFile == NULL && cpPath == NULL)
00610 return NULL;
00611 if ((pStore = X509_STORE_new()) == NULL)
00612 return NULL;
00613 if (cpFile != NULL) {
00614 if ((pLookup = X509_STORE_add_lookup(pStore, X509_LOOKUP_file())) == NULL) {
00615 X509_STORE_free(pStore);
00616 return NULL;
00617 }
00618 X509_LOOKUP_load_file(pLookup, cpFile, X509_FILETYPE_PEM);
00619 }
00620 if (cpPath != NULL) {
00621 if ((pLookup = X509_STORE_add_lookup(pStore, X509_LOOKUP_hash_dir())) == NULL) {
00622 X509_STORE_free(pStore);
00623 return NULL;
00624 }
00625 X509_LOOKUP_add_dir(pLookup, cpPath, X509_FILETYPE_PEM);
00626 }
00627 return pStore;
00628 }
00629
00630 int SSL_X509_STORE_lookup(X509_STORE *pStore, int nType,
00631 X509_NAME *pName, X509_OBJECT *pObj)
00632 {
00633 X509_STORE_CTX pStoreCtx;
00634 int rc;
00635
00636 X509_STORE_CTX_init(&pStoreCtx, pStore, NULL, NULL);
00637 rc = X509_STORE_get_by_subject(&pStoreCtx, nType, pName, pObj);
00638 X509_STORE_CTX_cleanup(&pStoreCtx);
00639 return rc;
00640 }