From 7276efca14a2950386abb564469f5e37ffb0d9a6 Mon Sep 17 00:00:00 2001 From: Andrew McNab Date: Tue, 30 Jun 2009 18:14:00 +0000 Subject: [PATCH] Sync --- org.gridsite.core/CHANGES | 4 + org.gridsite.core/VERSION | 4 +- org.gridsite.core/src/Makefile | 2 +- org.gridsite.core/src/grst_x509.c | 263 +++++++++++++++++++++++++++++++++++--- 4 files changed, 252 insertions(+), 21 deletions(-) diff --git a/org.gridsite.core/CHANGES b/org.gridsite.core/CHANGES index b0a6de9..da9995d 100644 --- a/org.gridsite.core/CHANGES +++ b/org.gridsite.core/CHANGES @@ -1,3 +1,7 @@ +* Tue Jun 30 2009 Andrew McNab +- Merge in VOMS LSC support +* Tue Jun 30 2009 Andrew McNab +- ==== GridSite version 1.7.1 ==== * Thu Jan 29 2009 Andrew McNab - Merge in private version changes from Yibiao Li. - Merge in major 1.7.x vs 1.5.x divergences. diff --git a/org.gridsite.core/VERSION b/org.gridsite.core/VERSION index 710b2eb..2897ddf 100644 --- a/org.gridsite.core/VERSION +++ b/org.gridsite.core/VERSION @@ -1,5 +1,5 @@ MAJOR_VERSION=1 MINOR_VERSION=1.7 -PATCH_VERSION=1.7.0 -DEFVERSION=010700 +PATCH_VERSION=1.7.1 +DEFVERSION=010701 VERSION=$(PATCH_VERSION) diff --git a/org.gridsite.core/src/Makefile b/org.gridsite.core/src/Makefile index af77054..1227959 100644 --- a/org.gridsite.core/src/Makefile +++ b/org.gridsite.core/src/Makefile @@ -49,7 +49,7 @@ export libdir=lib endif ifndef MYCFLAGS -export MYCFLAGS=-I. -I../interface -I/usr/include/httpd -I/usr/include/apache2 -I/usr/include/apr-0 -I/usr/include/apr-1 -I/usr/include/apr-1.0 -I/opt/glite/include -fPIC -DLINUX=2 -D_REENTRANT -D_GNU_SOURCE -D_LARGEFILE64_SOURCE $(HTTPD_FLAGS) +export MYCFLAGS=-I. -I../interface -I/usr/include/httpd -I/usr/include/apache2 -I/usr/include/apr-0 -I/usr/include/apr-1 -I/usr/include/apr-1.0 -I/opt/glite/include -fPIC -DLINUX=2 -D_REENTRANT -D_LARGEFILE64_SOURCE $(HTTPD_FLAGS) endif ifndef MYLDFLAGS diff --git a/org.gridsite.core/src/grst_x509.c b/org.gridsite.core/src/grst_x509.c index 2a0159a..6af1130 100644 --- a/org.gridsite.core/src/grst_x509.c +++ b/org.gridsite.core/src/grst_x509.c @@ -296,7 +296,6 @@ static int GRSTx509VerifyVomsSig(time_t *time1_time, time_t *time2_time, free(certpath); if (vomsDIR2 == NULL) continue; - while ((vomsdirent2 = readdir(vomsDIR2)) != NULL) { @@ -367,27 +366,218 @@ static int GRSTx509VerifyVomsSig(time_t *time1_time, time_t *time2_time, return GRST_RET_FAILED; } +/// Check the signature of the VOMS attributes using the LSC file cert +static int GRSTx509VerifyVomsSigCert(time_t *time1_time, time_t *time2_time, + unsigned char *asn1string, + struct GRSTasn1TagList taglist[], + int lasttag, + char *vomsdir, int acnumber, + int ivomscert, + char *capath, + char *acvomsdn, + char *voname) +/// +/// Returns GRST_RET_OK if signature is ok, other values if not. +{ +#define GRST_ASN1_COORDS_VOMS_DN "-1-1-%d-1-3-1-1-1-%%d-1-%%d" +#define GRST_ASN1_COORDS_VOMS_INFO "-1-1-%d-1" +#define GRST_ASN1_COORDS_VOMS_SIG "-1-1-%d-3" + int ret, isig, iinfo, chain_errors = GRST_RET_OK, + cadn_len, vomsdn_len, lsc_found = 0; + char *lscpath, dn_coords[200], + info_coords[200], sig_coords[200], *p, *cacertpath, + *vodir, *vomscert_cadn, *vomscert_vomsdn, + *lsc_cadn, *lsc_vomsdn; + unsigned char *q; + unsigned long issuerhash = 0; + DIR *voDIR; + struct dirent *vodirent; + X509 *cacert, *vomscert; + EVP_PKEY *prvkey; + FILE *fp; + EVP_MD_CTX ctx; + struct stat statbuf; + time_t tmp_time; + + if ((vomsdir == NULL) || (vomsdir[0] == '\0')) return GRST_RET_FAILED; + + q = &asn1string[taglist[ivomscert].start + 12]; + +{ +int i; +for (i=0; i < taglist[ivomscert].length - 8; ++i) + fprintf(stderr, "%4d %.03d %.02x %c\n", i, q[i], q[i], (q[i] > ' ') ? q[i] : '.'); + +fprintf(stderr, "voname=%s\n", voname); +} + + vomscert = d2i_X509(NULL, (const unsigned char **) &q, + taglist[ivomscert].length - 8); + + if (vomscert == NULL) + { + GRSTerrorLog(GRST_LOG_DEBUG, "Failed to read included VOMS cert in GRSTx509VerifyVomsSigCert()"); + return GRST_RET_FAILED; + } + + GRSTerrorLog(GRST_LOG_DEBUG, "Found included VOMS cert in GRSTx509VerifyVomsSigCert()"); + + /* check issuer CA certificate */ + + issuerhash = X509_NAME_hash(X509_get_issuer_name(vomscert)); + asprintf(&cacertpath, "%s/%.8x.0", capath, issuerhash); + +// need to check voms cert DN matches DN from AC +// need to check voms cert CA DN matches DN from CA file + + vomscert_vomsdn = X509_NAME_oneline(X509_get_subject_name(vomscert),NULL,0); + + if (strcmp(vomscert_vomsdn, acvomsdn) != 0) + { + free(vomscert_vomsdn); + + GRSTerrorLog(GRST_LOG_DEBUG, "Included VOMS cert DN does not match AC issuer DN!"); + return GRST_RET_FAILED; + } + + free(vomscert_vomsdn); + + GRSTerrorLog(GRST_LOG_DEBUG, "Look for CA root file %s", cacertpath); + + fp = fopen(cacertpath, "r"); + free(cacertpath); + + if (fp == NULL) return GRST_RET_FAILED; + else + { + cacert = PEM_read_X509(fp, NULL, NULL, NULL); + fclose(fp); + if (cacert != NULL) + GRSTerrorLog(GRST_LOG_DEBUG, " Loaded CA root cert from file"); + else + { + GRSTerrorLog(GRST_LOG_DEBUG, " Failed to load CA root cert file"); + return GRST_RET_FAILED; + } + } + + /* check times CA cert times, and reject if necessary */ + + tmp_time = GRSTasn1TimeToTimeT( + ASN1_STRING_data(X509_get_notBefore(cacert)), 0); + if (tmp_time > *time1_time) chain_errors |= GRST_CERT_BAD_TIME; + + tmp_time = GRSTasn1TimeToTimeT( + ASN1_STRING_data(X509_get_notAfter(cacert)), 0); + if (tmp_time < *time2_time) chain_errors |= GRST_CERT_BAD_TIME; + + /* check times VOMS cert times, and tighten if necessary */ + + tmp_time = GRSTasn1TimeToTimeT( + ASN1_STRING_data(X509_get_notBefore(vomscert)), 0); + if (tmp_time > *time1_time) chain_errors |= GRST_CERT_BAD_TIME; + + tmp_time = GRSTasn1TimeToTimeT( + ASN1_STRING_data(X509_get_notAfter(vomscert)), 0); + if (tmp_time < *time2_time) chain_errors |= GRST_CERT_BAD_TIME; + + ret = X509_check_issued(cacert, vomscert); + GRSTerrorLog(GRST_LOG_DEBUG, "X509_check_issued returns %d", ret); + + vomscert_cadn = X509_NAME_oneline(X509_get_issuer_name(vomscert),NULL,0); + + X509_free(cacert); + X509_free(vomscert); + + if (ret != X509_V_OK) return chain_errors | GRST_CERT_BAD_SIG; + + asprintf(&vodir, "%s/%s", vomsdir, voname); + + voDIR = opendir(vodir); + if (voDIR == NULL) return GRST_RET_FAILED; + + cadn_len = strlen(vomscert_cadn); + vomsdn_len = strlen(acvomsdn); + + lsc_cadn = malloc(cadn_len + 2); + lsc_vomsdn = malloc(vomsdn_len + 2); + + while (((vodirent = readdir(voDIR)) != NULL) && !lsc_found) + { + if (vodirent->d_name[0] == '.') continue; + + if (strlen(vodirent->d_name) < 5) continue; + + if (strcmp(&(vodirent->d_name[strlen(vodirent->d_name)-4]), ".lsc") != 0) continue; + + asprintf(&lscpath, "%s/%s", vodir, vodirent->d_name); + stat(lscpath, &statbuf); + + GRSTerrorLog(GRST_LOG_DEBUG, "Examine LSC file %s", lscpath); + + if ((fp = fopen(lscpath, "r")) != NULL) + { + lsc_cadn[0] = '\0'; + lsc_vomsdn[0] = '\0'; + + if ((fgets(lsc_vomsdn, vomsdn_len + 2, fp) != NULL) + && (fgets(lsc_cadn, cadn_len + 2, fp) != NULL)) + { + +fprintf(stderr, "accadn=%s lsc_cadn=%s acvomsdn=%s lsc_vomsdn=%s\n", +vomscert_cadn, lsc_cadn, acvomsdn, lsc_vomsdn); + if ((p = index(lsc_cadn, '\n')) != NULL) *p = '\0'; + + if ((p = index(lsc_vomsdn, '\n')) != NULL) *p = '\0'; + + if ((strcmp(lsc_cadn, vomscert_cadn) == 0) && + (strcmp(lsc_vomsdn, acvomsdn) == 0)) + { + GRSTerrorLog(GRST_LOG_DEBUG, "Matched LSC file %s", lscpath); + lsc_found = 1; + } + } + + fclose(fp); + } + + free(lscpath); + } + + closedir(voDIR); + free(vodir); + free(vomscert_cadn); + free(lsc_cadn); + free(lsc_vomsdn); + + if (!lsc_found) chain_errors |= GRST_CERT_BAD_SIG; + + return chain_errors; +} + /// Get the VOMS attributes in the given extension static int GRSTx509ChainVomsAdd(GRSTx509Cert **grst_cert, time_t time1_time, time_t time2_time, X509_EXTENSION *ex, - char *ucuserdn, char *vomsdir) + char *ucuserdn, char *vomsdir, char *capath) /// /// Add any VOMS credentials found into the chain. Always returns GRST_RET_OK /// - even for invalid credentials, which are flagged in errors field { #define MAXTAG 500 -#define GRST_ASN1_COORDS_FQAN "-1-1-%d-1-7-1-2-1-2-%d" -#define GRST_ASN1_COORDS_USER_DN "-1-1-%d-1-2-1-1-1-1-%%d-1-%%d" -#define GRST_ASN1_COORDS_VOMS_DN "-1-1-%d-1-3-1-1-1-%%d-1-%%d" -#define GRST_ASN1_COORDS_TIME1 "-1-1-%d-1-6-1" -#define GRST_ASN1_COORDS_TIME2 "-1-1-%d-1-6-2" +#define GRST_ASN1_COORDS_FQAN "-1-1-%d-1-7-1-2-1-2-%d" +#define GRST_ASN1_COORDS_USER_DN "-1-1-%d-1-2-1-1-1-1-%%d-1-%%d" +#define GRST_ASN1_COORDS_VOMS_DN "-1-1-%d-1-3-1-1-1-%%d-1-%%d" +#define GRST_ASN1_COORDS_TIME1 "-1-1-%d-1-6-1" +#define GRST_ASN1_COORDS_TIME2 "-1-1-%d-1-6-2" +#define GRST_ASN1_COORDS_VOMSCERT "-1-1-%d-1-8-4-2" ASN1_OCTET_STRING *asn1data; - char *asn1string, acuserdn[200], accadn[200], acvomsdn[200], + char *asn1string, acuserdn[200], acvomsdn[200], dn_coords[200], fqan_coords[200], time1_coords[200], - time2_coords[200]; + time2_coords[200], vomscert_coords[200], *voname = NULL; long asn1length; - int lasttag=-1, itag, i, acnumber = 1, chain_errors = 0; + int lasttag=-1, itag, i, j, acnumber = 1, chain_errors = 0, + ivomscert, tmp_chain_errors; struct GRSTasn1TagList taglist[MAXTAG+1]; time_t actime1 = 0, actime2 = 0, time_now; @@ -414,11 +604,6 @@ static int GRSTx509ChainVomsAdd(GRSTx509Cert **grst_cert, if (GRSTx509NameCmp(ucuserdn, acuserdn) != 0) chain_errors |= GRST_CERT_BAD_CHAIN; - if (GRSTx509VerifyVomsSig(&time1_time, &time2_time, - asn1string, taglist, lasttag, vomsdir, acnumber) - != GRST_RET_OK) - chain_errors |= GRST_CERT_BAD_SIG; - snprintf(time1_coords, sizeof(time1_coords), GRST_ASN1_COORDS_TIME1, acnumber); itag = GRSTasn1SearchTaglist(taglist, lasttag, time1_coords); @@ -444,6 +629,48 @@ static int GRSTx509ChainVomsAdd(GRSTx509Cert **grst_cert, if ((time1_time > time_now + 300) || (time2_time < time_now)) chain_errors |= GRST_CERT_BAD_TIME; + /* get first FQAN and use to get VO name */ + + snprintf(fqan_coords, sizeof(fqan_coords), GRST_ASN1_COORDS_FQAN, acnumber, 1); + itag = GRSTasn1SearchTaglist(taglist, lasttag, fqan_coords); + + if ((itag > -1) && + (asn1string[taglist[itag].start+taglist[itag].headerlength] == '/')) + { + for (j=1; + (asn1string[taglist[itag].start+taglist[itag].headerlength+j] != '/') && + (j < taglist[itag].length); + ++j) ; + + asprintf(&voname, "%.*s", j-1, + &(asn1string[taglist[itag].start+taglist[itag].headerlength+1])); + } + + snprintf(vomscert_coords, sizeof(vomscert_coords), + GRST_ASN1_COORDS_VOMSCERT, acnumber); + ivomscert = GRSTasn1SearchTaglist(taglist, lasttag, vomscert_coords); + + /* try using internal VOMS issuer cert */ + tmp_chain_errors = GRST_CERT_BAD_SIG; + if ((ivomscert > -1) && + (voname != NULL) && + (GRSTx509VerifyVomsSigCert(&time1_time, &time2_time, + asn1string, taglist, lasttag, vomsdir, acnumber, + ivomscert, capath, acvomsdn, + voname) == GRST_RET_OK)) tmp_chain_errors = 0; + + if (voname != NULL) + { + free(voname); + voname = NULL; + } + + if ((tmp_chain_errors != 0) && + (GRSTx509VerifyVomsSig(&time1_time, &time2_time, + asn1string, taglist, lasttag, vomsdir, acnumber) + != GRST_RET_OK)) + chain_errors |= GRST_CERT_BAD_SIG; + for (i=1; ; ++i) /* now go through FQANs */ { snprintf(fqan_coords, sizeof(fqan_coords), GRST_ASN1_COORDS_FQAN, acnumber, i); @@ -755,11 +982,11 @@ int GRSTx509ChainLoadCheck(GRSTx509Chain **chain, new_grst_cert->notafter, ex, ucuserdn, - vomsdir); + vomsdir, + capath); grst_cert->delegation = (lastcert == NULL) ? i : i+1; } - } - + } } } -- 1.8.2.3