From cdbd21501cd34fe0493b238b072687140d67c066 Mon Sep 17 00:00:00 2001 From: Andrew McNab Date: Sun, 20 Feb 2005 22:38:09 +0000 Subject: [PATCH] Basic VOMS AC support --- org.gridsite.core/CHANGES | 5 + org.gridsite.core/VERSION | 2 +- org.gridsite.core/interface/gridsite.h | 25 +- org.gridsite.core/project/version.properties | 6 +- org.gridsite.core/src/Makefile | 69 ++-- org.gridsite.core/src/grst_asn1.c | 443 ++++++++++++++++++++++++++ org.gridsite.core/src/grst_x509.c | 168 +++++----- org.gridsite.core/src/real-gridsite-admin.cgi | Bin 99027 -> 105006 bytes org.gridsite.core/src/showx509exts.c | 78 +++++ 9 files changed, 682 insertions(+), 114 deletions(-) create mode 100644 org.gridsite.core/src/grst_asn1.c create mode 100644 org.gridsite.core/src/showx509exts.c diff --git a/org.gridsite.core/CHANGES b/org.gridsite.core/CHANGES index 304408a..375f8e1 100644 --- a/org.gridsite.core/CHANGES +++ b/org.gridsite.core/CHANGES @@ -1,3 +1,8 @@ +* Sun Feb 20 2005 Andrew McNab +- Add basic VOMS support (signature checking not yet + in) for X.509 Attribute Certificates. +* Tue Feb 8 2005 Andrew McNab +- ==== GridSite version 1.1.6 ==== * Tue Feb 8 2005 Andrew McNab - Include GRSTx509MakeProxyFileName() and GRSTx509StringToChain() (code to used hashes in cached diff --git a/org.gridsite.core/VERSION b/org.gridsite.core/VERSION index 87062a2..b51a96c 100644 --- a/org.gridsite.core/VERSION +++ b/org.gridsite.core/VERSION @@ -1,4 +1,4 @@ MAJOR_VERSION=1 MINOR_VERSION=1.1 -PATCH_VERSION=1.1.5 +PATCH_VERSION=1.1.6 VERSION=$(PATCH_VERSION) diff --git a/org.gridsite.core/interface/gridsite.h b/org.gridsite.core/interface/gridsite.h index c2d7729..a88a316 100644 --- a/org.gridsite.core/interface/gridsite.h +++ b/org.gridsite.core/interface/gridsite.h @@ -63,12 +63,6 @@ /// No such file or directory #define GRST_RET_NO_SUCH_FILE 1003 -#define GRST_PROXYCERTINFO_OID "1.3.6.1.4.1.3536.1.222" -#define GRST_VOMS_OID "1.3.6.1.4.1.8005.100.100.1" -#define GRST_VOMS_DIR "/etc/grid-security/vomsdir" - - - typedef struct { char *name; char *value; void *next; } GRSTgaclNamevalue; @@ -117,6 +111,19 @@ typedef struct { GRSTgaclCred *firstcred; #define GRST_DN_LISTS "/etc/grid-security/dn-lists" #define GRST_RECURS_LIMIT 9 +#define GRST_PROXYCERTINFO_OID "1.3.6.1.4.1.3536.1.222" +#define GRST_VOMS_OID "1.3.6.1.4.1.8005.100.100.5" +#define GRST_VOMS_DIR "/etc/grid-security/vomsdir" + +#define GRST_ASN1_MAXCOORDLEN 50 +#define GRST_ASN1_MAXTAGS 500 + +struct GRSTasn1TagList { char treecoords[GRST_ASN1_MAXCOORDLEN+1]; + int start; + int headerlength; + int length; + int tag; } ; + int GRSTgaclInit(void); /* #define GACLnewCred(x) GRSTgaclCredNew((x)) */ @@ -239,7 +246,6 @@ int GRSTx509NameCmp(char *, char *); int GRSTx509KnownCriticalExts(X509 *); -time_t GRSTasn1TimeToTimeT(char *); int GRSTx509IsCA(X509 *); int GRSTx509CheckChain(int *, X509_STORE_CTX *); int GRSTx509VerifyCallback(int, X509_STORE_CTX *); @@ -273,3 +279,8 @@ int GRSThttpCopy(GRSThttpBody *, char *); void GRSThttpWriteOut(GRSThttpBody *); int GRSThttpPrintHeaderFooter(GRSThttpBody *, char *, char *); char *GRSThttpGetCGI(char *); + +time_t GRSTasn1TimeToTimeT(char *); +int GRSTasn1SearchTaglist(struct GRSTasn1TagList taglist[], int *, char *); +int GRSTasn1ParseDump(BIO *, unsigned char *, long, + struct GRSTasn1TagList taglist[], int, int *); diff --git a/org.gridsite.core/project/version.properties b/org.gridsite.core/project/version.properties index dd123bc..dc4bf37 100644 --- a/org.gridsite.core/project/version.properties +++ b/org.gridsite.core/project/version.properties @@ -1,2 +1,4 @@ -module.version=1.1.5 -module.age=1 +#Thu Jan 13 03:09:57 CET 2005 +module.version=1.1.6 +module.build=134 +module.age=3 diff --git a/org.gridsite.core/src/Makefile b/org.gridsite.core/src/Makefile index 680a1f3..cc6fa11 100644 --- a/org.gridsite.core/src/Makefile +++ b/org.gridsite.core/src/Makefile @@ -64,38 +64,43 @@ build: libgridsite_globus.so.$(VERSION) libgridsite_globus.a # First, normal versions using system OpenSSL rather than Globus OpenSSL -libgridsite.so.$(VERSION): grst_x509.o grst_gacl.o grst_http.o +libgridsite.so.$(VERSION): grst_x509.o grst_gacl.o grst_http.o grst_asn1.o gcc -shared -Wl,-soname,libgridsite.so.$(MINOR_VERSION) \ - -o libgridsite.so.$(PATCH_VERSION) grst_x509.o grst_gacl.o grst_http.o + -o libgridsite.so.$(PATCH_VERSION) grst_x509.o grst_gacl.o grst_http.o grst_asn1.o -libgridsite.a: grst_x509.o grst_gacl.o grst_http.o - ar src libgridsite.a grst_x509.o grst_gacl.o grst_http.o +libgridsite.a: grst_x509.o grst_gacl.o grst_http.o grst_asn1.o + ar src libgridsite.a grst_x509.o grst_gacl.o grst_http.o grst_asn1.o grst_x509.o: grst_x509.c ../interface/gridsite.h - gcc $(MYCFLAGS) $(OPENSSL_GLOBUS_FLAGS) \ + gcc $(MYCFLAGS) \ -I/usr/kerberos/include -c grst_x509.c grst_gacl.o: grst_gacl.c ../interface/gridsite.h - gcc $(MYCFLAGS) $(OPENSSL_GLOBUS_FLAGS) \ + gcc $(MYCFLAGS) \ -I/usr/kerberos/include `xml2-config --cflags` -c grst_gacl.c grst_http.o: grst_http.c ../interface/gridsite.h - gcc $(MYCFLAGS) $(OPENSSL_GLOBUS_FLAGS) \ + gcc $(MYCFLAGS) \ -I/usr/kerberos/include -c grst_http.c +grst_asn1.o: grst_asn1.c ../interface/gridsite.h + gcc $(MYCFLAGS) \ + -I/usr/kerberos/include -c grst_asn1.c + # Then build versions using Globus OpenSSL if configured ifdef OPENSSL_GLOBUS_LIBS libgridsite_globus.so.$(VERSION): \ - grst_x509_globus.o grst_gacl_globus.o grst_http_globus.o + grst_x509_globus.o grst_gacl_globus.o grst_http_globus.o \ + grst_asn1_globus.o gcc -shared -Wl,-soname,libgridsite_globus.so.$(MINOR_VERSION) \ -o libgridsite_globus.so.$(PATCH_VERSION) \ - grst_x509_globus.o grst_gacl_globus.o grst_http_globus.o + grst_x509_globus.o grst_gacl_globus.o grst_http_globus.o grst_asn1_globus.o -libgridsite_globus.a: grst_x509_globus.o grst_gacl_globus.o grst_http_globus.o +libgridsite_globus.a: grst_x509_globus.o grst_gacl_globus.o grst_http_globus.o grst_asn1_globus.o ar src libgridsite_globus.a \ - grst_x509_globus.o grst_gacl_globus.o grst_http_globus.o + grst_x509_globus.o grst_gacl_globus.o grst_http_globus.o grst_asn1_globus.o grst_x509_globus.o: grst_x509.c ../interface/gridsite.h gcc $(MYCFLAGS) $(OPENSSL_GLOBUS_FLAGS) \ @@ -112,6 +117,11 @@ grst_http_globus.o: grst_http.c ../interface/gridsite.h -I/usr/kerberos/include -c grst_http.c \ -o grst_http_globus.o +grst_asn1_globus.o: grst_asn1.c ../interface/gridsite.h + gcc $(MYCFLAGS) $(OPENSSL_GLOBUS_FLAGS) \ + -I/usr/kerberos/include -c grst_asn1.c \ + -o grst_asn1_globus.o + else libgridsite_globus.so.$(VERSION): libgridsite.so.$(VERSION) @@ -125,7 +135,7 @@ endif urlencode: urlencode.c libgridsite.a gcc -DVERSION=\"$(PATCH_VERSION)\" $(MYCFLAGS) \ -o urlencode urlencode.c -L. \ - $(OPENSSL_GLOBUS_FLAGS) -I/usr/kerberos/include -lgridsite + -I/usr/kerberos/include -lgridsite htcp: htcp.c gcc -DVERSION=\"$(PATCH_VERSION)\" -I. -o htcp htcp.c \ @@ -133,7 +143,7 @@ htcp: htcp.c mod_gridsite.so: mod_gridsite.c mod_ssl-private.h libgridsite.a gcc $(MYCFLAGS) -shared -Wl,-soname=gridsite_module \ - $(OPENSSL_GLOBUS_FLAGS) -I/usr/kerberos/include \ + -I/usr/kerberos/include \ -I/usr/include/libxml2 \ -DVERSION=\"$(VERSION)\" -o mod_gridsite.so \ mod_gridsite.c $(MYLDFLAGS) -lxml2 -lm -lz -lgridsite @@ -144,22 +154,29 @@ real-gridsite-admin.cgi: grst_admin_main.c grst_admin_gacl.c \ grst_admin_main.c \ grst_admin_gacl.c \ grst_admin_file.c \ - $(OPENSSL_GLOBUS_FLAGS) -I/usr/kerberos/include \ - -DVERSION=\"$(VERSION)\" $(OPENSSL_GLOBUS_LIBS) -lgridsite -lssl$(FLAVOR_GLOBUS_EXT) -lcrypto$(FLAVOR_GLOBUS_EXT) -lxml2 -lz -lm + -I/usr/kerberos/include \ + -DVERSION=\"$(VERSION)\" -lgridsite -lssl -lcrypto -lxml2 -lz -lm findproxyfile: findproxyfile.c libgridsite.a gcc -DVERSION=\"$(PATCH_VERSION)\" $(MYCFLAGS) $(MYLDFLAGS) \ -o findproxyfile findproxyfile.c -L. \ - $(OPENSSL_GLOBUS_FLAGS) -I/usr/kerberos/include -lgridsite \ - $(OPENSSL_GLOBUS_LIBS) -lssl$(FLAVOR_GLOBUS_EXT) -lcrypto$(FLAVOR_GLOBUS_EXT) -lxml2 -lz -lm + -I/usr/kerberos/include -lgridsite \ + -lssl -lcrypto -lxml2 -lz -lm +showx509exts: showx509exts.c libgridsite.a + gcc -DVERSION=\"$(PATCH_VERSION)\" $(MYCFLAGS) $(MYLDFLAGS) \ + -o showx509exts showx509exts.c -L. \ + -I/usr/kerberos/include \ + -lgridsite \ + -lssl -lcrypto + apidoc: doxygen Doxyfile gaclexample: gaclexample.c libgridsite.a gcc -o gaclexample gaclexample.c -I. -L. \ - $(OPENSSL_GLOBUS_FLAGS) -I/usr/kerberos/include -lgridsite \ - -lssl$(FLAVOR_GLOBUS_EXT) -lcrypto$(FLAVOR_GLOBUS_EXT) -lxml2 -lz -lm + -I/usr/kerberos/include -lgridsite \ + -lssl -lcrypto -lxml2 -lz -lm # # Delegation machinery, including SOAP delegation portType. To build this @@ -183,30 +200,30 @@ gridsite-delegation.cgi: grst-delegation.c delegation.h delegation.wsdl \ soapC.c soapServer.c gcc $(MYCFLAGS) $(MYLDFLAGS) -o gridsite-delegation.cgi \ grst-delegation.c \ - $(OPENSSL_GLOBUS_FLAGS) -I/usr/kerberos/include -I$(GSOAPDIR)/include \ + -I/usr/kerberos/include -I$(GSOAPDIR)/include \ -DVERSION=\"$(VERSION)\" -L$(GSOAPDIR)/lib \ soapC.c soapServer.c -lgsoap \ - -lgridsite -lcurl -lz -lssl$(FLAVOR_GLOBUS_EXT) -lcrypto$(FLAVOR_GLOBUS_EXT) -lxml2 -lm + -lgridsite -lcurl -lz -lssl -lcrypto -lxml2 -lm htproxyput: htproxyput.c delegation.h delegation.wsdl \ soapC.c soapServer.c gcc $(MYCFLAGS) $(MYLDFLAGS) -o htproxyput \ htproxyput.c \ - $(OPENSSL_GLOBUS_FLAGS) -I/usr/kerberos/include \ + -I/usr/kerberos/include \ -g -DVERSION=\"$(VERSION)\" \ -I$(GSOAPDIR)/include -DWITH_OPENSSL -L$(GSOAPDIR)/lib \ soapC.c soapClient.c -lgsoap \ - -lgridsite -lcurl -lz -lssl$(FLAVOR_GLOBUS_EXT) -lcrypto$(FLAVOR_GLOBUS_EXT) -lxml2 -lm + -lgridsite -lcurl -lz -lssl -lcrypto -lxml2 -lm proxyput-example: proxyput-example.c delegation.h delegation.wsdl \ soapC.c soapServer.c libstdsoap2.a gcc $(MYCFLAGS) $(MYLDFLAGS) -o proxyput-example \ proxyput-example.c \ - $(OPENSSL_GLOBUS_FLAGS) -I/usr/kerberos/include \ + -I/usr/kerberos/include \ -g -DVERSION=\"$(VERSION)\" \ -I$(GSOAPDIR) -DWITH_OPENSSL \ soapC.c soapClient.c libstdsoap2.a \ - -lgridsite -lcurl -lz -lssl$(FLAVOR_GLOBUS_EXT) -lcrypto$(FLAVOR_GLOBUS_EXT) -lxml2 -lm + -lgridsite -lcurl -lz -lssl -lcrypto -lxml2 -lm clean: @@ -309,8 +326,6 @@ rpm: dist gridsite.spec $(MYRPMDIR)/SRPMS $(MYRPMDIR)/RPMS/i386 $(MYRPMDIR)/BUILDROOT cp -f ../gridsite-$(PATCH_VERSION).src.tar.gz $(MYRPMDIR)/SOURCES cp -f gridsite.spec $(MYRPMDIR)/SPECS - export OPENSSL_GLOBUS_FLAGS=$(OPENSSL_GLOBUS_FLAGS) ; export OPENSSL_GLOBUS_LIBS=$(OPENSSL_GLOBUS_LIBS) ; export FLAVOR_GLOBUS_EXT=$(FLAVOR_GLOBUS_EXT) ; \ - export GSOAPDIR=$(GSOAPDIR) ; \ export MYPREFIX=/usr ; export MYVERSION=$(PATCH_VERSION) ; \ $(RPMCMD) --define "_topdir $(MYRPMDIR)" \ -ba --buildroot $(MYRPMDIR)/BUILDROOT gridsite.spec diff --git a/org.gridsite.core/src/grst_asn1.c b/org.gridsite.core/src/grst_asn1.c new file mode 100644 index 0000000..7634c14 --- /dev/null +++ b/org.gridsite.core/src/grst_asn1.c @@ -0,0 +1,443 @@ + +#include +#include +#include +#include + +#include +#include +#include + +#include "gridsite.h" + +/// ASN1 time string (in a char *) to time_t +/** + * (Use ASN1_STRING_data() to convert ASN1_GENERALIZEDTIME to char * if + * necessary) + */ + +time_t GRSTasn1TimeToTimeT(char *asn1time) +{ + char zone; + struct tm time_tm; + + if ((sscanf(asn1time, "%02d%02d%02d%02d%02d%02d%c", + &(time_tm.tm_year), + &(time_tm.tm_mon), + &(time_tm.tm_mday), + &(time_tm.tm_hour), + &(time_tm.tm_min), + &(time_tm.tm_sec), + &zone) != 7) || (zone != 'Z')) return 0; /* dont understand */ + + /* time format fixups */ + + if (time_tm.tm_year < 90) time_tm.tm_year += 100; + --(time_tm.tm_mon); + + return timegm(&time_tm); +} + +/* this function is taken from OpenSSL without modification */ + +static int asn1_print_info(BIO *bp, int tag, int xclass, int constructed, + int indent) + { + static const char fmt[]="%-18s"; + static const char fmt2[]="%2d %-15s"; + char str[128]; + const char *p,*p2=NULL; + + if (constructed & V_ASN1_CONSTRUCTED) + p="cons: "; + else + p="prim: "; + if (BIO_write(bp,p,6) < 6) goto err; + BIO_indent(bp,indent,128); + + p=str; + if ((xclass & V_ASN1_PRIVATE) == V_ASN1_PRIVATE) + sprintf(str,"priv [ %d ] ",tag); + else if ((xclass & V_ASN1_CONTEXT_SPECIFIC) == V_ASN1_CONTEXT_SPECIFIC) + sprintf(str,"cont [ %d ]",tag); + else if ((xclass & V_ASN1_APPLICATION) == V_ASN1_APPLICATION) + sprintf(str,"appl [ %d ]",tag); + else p = ASN1_tag2str(tag); + + if (p2 != NULL) + { + if (BIO_printf(bp,fmt2,tag,p2) <= 0) goto err; + } + else + { + if (BIO_printf(bp,fmt,p) <= 0) goto err; + } + return(1); +err: + return(0); + } + +static void GRSTasn1AddToTaglist(struct GRSTasn1TagList taglist[], + int maxtag, int *lasttag, + char *treecoords, int start, int headerlength, + int length, int tag) +{ + if ((strlen(treecoords) > GRST_ASN1_MAXCOORDLEN) || + (*lasttag + 1 > maxtag)) return; + + ++(*lasttag); + + strncpy(taglist[*lasttag].treecoords, treecoords, GRST_ASN1_MAXCOORDLEN+1); + taglist[*lasttag].start = start; + taglist[*lasttag].headerlength = headerlength; + taglist[*lasttag].length = length; + taglist[*lasttag].tag = tag; +} + +int GRSTasn1SearchTaglist(struct GRSTasn1TagList taglist[], + int *lasttag, char *treecoords) +{ + int i; + + for (i=0; i <= *lasttag; ++i) + { + if (strcmp(treecoords, taglist[i].treecoords) == 0) return i; + } + + return -1; +} + +static int GRSTasn1Parse2(BIO *bp, unsigned char **pp, long length, int offset, + int depth, int indent, int dump, char *treecoords, + struct GRSTasn1TagList taglist[], int maxtag, int *lasttag) + { + int sibling = 0; + char sibtreecoords[512]; + + unsigned char *p,*ep,*tot,*op,*opp; + long len; + int tag,xclass,ret=0; + int nl,hl,j,r; + ASN1_OBJECT *o=NULL; + ASN1_OCTET_STRING *os=NULL; + int dump_indent; + + + dump_indent = 6; /* Because we know BIO_dump_indent() */ + p= *pp; + tot=p+length; + op=p-1; + while ((p < tot) && (op < p)) + { + op=p; + j=ASN1_get_object(&p,&len,&tag,&xclass,length); + + if (j & 0x80) + { + if ((bp != NULL) && + (BIO_write(bp,"Error in encoding\n",18) <= 0)) + goto end; + ret=0; + goto end; + } + hl=(p-op); + length-=hl; + + ++sibling; + sprintf(sibtreecoords, "%s-%d", treecoords, sibling); + + GRSTasn1AddToTaglist(taglist, maxtag, lasttag, sibtreecoords, + (int)offset+(int)(op - *pp), + (int) hl, len, tag); + + if (bp != NULL) + BIO_printf(bp, " %s %ld %ld %d %d\n", sibtreecoords, + (long)offset+(long)(op - *pp), hl, len, tag); + + + /* if j == 0x21 it is a constructed indefinite length object */ + if ((bp != NULL) && + (BIO_printf(bp,"%5ld:",(long)offset+(long)(op- *pp)) + <= 0)) goto end; + + if (j != (V_ASN1_CONSTRUCTED | 1)) + { + if ((bp != NULL) && + (BIO_printf(bp,"d=%-2d hl=%ld l=%4ld ", + depth,(long)hl,len) <= 0)) + goto end; + } + else + { + if ((bp != NULL) && + (BIO_printf(bp,"d=%-2d hl=%ld l=inf ", + depth,(long)hl) <= 0)) + goto end; + } + if ((bp != NULL) && + !asn1_print_info(bp,tag,xclass,j,(indent)?depth:0)) + goto end; + if (j & V_ASN1_CONSTRUCTED) + { + ep=p+len; + if ((bp != NULL) && + (BIO_write(bp,"\n",1) <= 0)) goto end; + if (len > length) + { + if (bp != NULL) BIO_printf(bp, + "length is greater than %ld\n",length); + ret=0; + goto end; + } + if ((j == 0x21) && (len == 0)) + { + for (;;) + { + r=GRSTasn1Parse2(bp,&p,(long)(tot-p), + offset+(p - *pp),depth+1, + indent,dump,sibtreecoords, + taglist, maxtag, lasttag); + if (r == 0) { ret=0; goto end; } + if ((r == 2) || (p >= tot)) break; + } + } + else + while (p < ep) + { + r=GRSTasn1Parse2(bp,&p,(long)len, + offset+(p - *pp),depth+1, + indent,dump,sibtreecoords, + taglist, maxtag, lasttag); + if (r == 0) { ret=0; goto end; } + } + } + else if (xclass != 0) + { + p+=len; + if ((bp != NULL) && + (BIO_write(bp,"\n",1) <= 0)) goto end; + } + else + { + nl=0; + if ( (tag == V_ASN1_PRINTABLESTRING) || + (tag == V_ASN1_T61STRING) || + (tag == V_ASN1_IA5STRING) || + (tag == V_ASN1_VISIBLESTRING) || + (tag == V_ASN1_UTCTIME) || + (tag == V_ASN1_GENERALIZEDTIME)) + { + if ((bp != NULL) && + (BIO_write(bp,":",1) <= 0)) goto end; + if ((len > 0) && (bp != NULL) && + BIO_write(bp,(char *)p,(int)len) + != (int)len) + goto end; + } + else if (tag == V_ASN1_OBJECT) + { + opp=op; + if (d2i_ASN1_OBJECT(&o,&opp,len+hl) != NULL) + { + if (bp != NULL) + { + if (BIO_write(bp,":",1) <= 0) goto end; + i2a_ASN1_OBJECT(bp,o); + } + } + else + { + if ((bp != NULL) && + (BIO_write(bp,":BAD OBJECT",11) <= 0)) + goto end; + } + } + else if (tag == V_ASN1_BOOLEAN) + { + int ii; + + opp=op; + ii=d2i_ASN1_BOOLEAN(NULL,&opp,len+hl); + if (ii < 0) + { + if ((bp != NULL) && + (BIO_write(bp,"Bad boolean\n",12))) + goto end; + } + if (bp != NULL) BIO_printf(bp,":%d",ii); + } + else if (tag == V_ASN1_BMPSTRING) + { + /* do the BMP thang */ + } + else if (tag == V_ASN1_OCTET_STRING) + { + int i,printable=1; + + opp=op; + os=d2i_ASN1_OCTET_STRING(NULL,&opp,len+hl); + if (os != NULL) + { + opp=os->data; + for (i=0; ilength; i++) + { + if (( (opp[i] < ' ') && + (opp[i] != '\n') && + (opp[i] != '\r') && + (opp[i] != '\t')) || + (opp[i] > '~')) + { + printable=0; + break; + } + } + if (printable && (os->length > 0)) + { + if ((bp != NULL) && + (BIO_write(bp,":",1) <= 0)) + goto end; + if ((bp != NULL) && + (BIO_write(bp,(char *)opp, + os->length) <= 0)) + goto end; + } + if (!printable && (os->length > 0) + && dump) + { + if (!nl) + { + if ((bp != NULL) && + (BIO_write(bp,"\n",1) <= 0)) + goto end; + } + if ((bp != NULL) && + (BIO_dump_indent(bp,(char *)opp, + ((dump == -1 || dump > os->length)?os->length:dump), + dump_indent) <= 0)) + goto end; + nl=1; + } + M_ASN1_OCTET_STRING_free(os); + os=NULL; + } + } + else if (tag == V_ASN1_INTEGER) + { + ASN1_INTEGER *bs; + int i; + + opp=op; + bs=d2i_ASN1_INTEGER(NULL,&opp,len+hl); + if (bs != NULL) + { + if ((bp != NULL) && + (BIO_write(bp,":",1) <= 0)) goto end; + if (bs->type == V_ASN1_NEG_INTEGER) + if ((bp != NULL) && + (BIO_write(bp,"-",1) <= 0)) + goto end; + for (i=0; ilength; i++) + { + if ((bp != NULL) && + (BIO_printf(bp,"%02X", + bs->data[i]) <= 0)) + goto end; + } + if (bs->length == 0) + { + if ((bp != NULL) && + (BIO_write(bp,"00",2) <= 0)) + goto end; + } + } + else + { + if ((bp != NULL) && + (BIO_write(bp,"BAD INTEGER",11) <= 0)) + goto end; + } + M_ASN1_INTEGER_free(bs); + } + else if (tag == V_ASN1_ENUMERATED) + { + ASN1_ENUMERATED *bs; + int i; + + opp=op; + bs=d2i_ASN1_ENUMERATED(NULL,&opp,len+hl); + if (bs != NULL) + { + if ((bp != NULL) && + (BIO_write(bp,":",1) <= 0)) goto end; + if (bs->type == V_ASN1_NEG_ENUMERATED) + if ((bp != NULL) && + (BIO_write(bp,"-",1) <= 0)) + goto end; + for (i=0; ilength; i++) + { + if ((bp != NULL) && + (BIO_printf(bp,"%02X", + bs->data[i]) <= 0)) + goto end; + } + if (bs->length == 0) + { + if ((bp != NULL) && + (BIO_write(bp,"00",2) <= 0)) + goto end; + } + } + else + { + if ((bp != NULL) && + (BIO_write(bp,"BAD ENUMERATED",11) <= 0)) + goto end; + } + M_ASN1_ENUMERATED_free(bs); + } + else if (len > 0 && dump) + { + if (!nl) + { + if ((bp != NULL) && + (BIO_write(bp,"\n",1) <= 0)) + goto end; + } + if ((bp != NULL) && + (BIO_dump_indent(bp,(char *)p, + ((dump == -1 || dump > len)?len:dump), + dump_indent) <= 0)) + goto end; + nl=1; + } + + if (!nl) + { + if ((bp != NULL) && + (BIO_write(bp,"\n",1) <= 0)) goto end; + } + p+=len; + if ((tag == V_ASN1_EOC) && (xclass == 0)) + { + ret=2; /* End of sequence */ + goto end; + } + } + + length-=len; + } + ret=1; +end: + if (o != NULL) ASN1_OBJECT_free(o); + if (os != NULL) M_ASN1_OCTET_STRING_free(os); + *pp=p; + return(ret); + } + +int GRSTasn1ParseDump(BIO *bp, unsigned char *pp, long len, + struct GRSTasn1TagList taglist[], + int maxtag, int *lasttag) + { + return(GRSTasn1Parse2(bp,&pp,len,0,0,0,0,"", + taglist, maxtag, lasttag)); + } diff --git a/org.gridsite.core/src/grst_x509.c b/org.gridsite.core/src/grst_x509.c index 75376dc..2195145 100644 --- a/org.gridsite.core/src/grst_x509.c +++ b/org.gridsite.core/src/grst_x509.c @@ -62,10 +62,6 @@ #include #include -#ifdef GRST_VOMS_SUPPORT -#include -#endif - #include "gridsite.h" #define GRST_KEYSIZE 512 @@ -145,6 +141,7 @@ int GRSTx509KnownCriticalExts(X509 *cert) #endif } +#if 0 /// ASN1 time string (in a char *) to time_t /** * (Use ASN1_STRING_data() to convert ASN1_GENERALIZEDTIME to char * if @@ -172,6 +169,7 @@ time_t GRSTasn1TimeToTimeT(char *asn1time) return timegm(&time_tm); } +#endif /// Check if certificate can be used as a CA to sign standard X509 certs /* @@ -397,80 +395,74 @@ int GRSTx509VerifyCallback (int ok, X509_STORE_CTX *ctx) // else return GRST_RET_FAILED; } -/// Get the VOMS attributes in the extensions to the given cert +/// Get the VOMS attributes in the given extension /* * Puts any VOMS credentials found into the Compact Creds string array * starting at *creds. Always returns GRST_RET_OK. */ -int GRSTx509GetVomsCreds(int *lastcred, int maxcreds, size_t credlen, - char *creds, X509 *cert, STACK_OF(X509) *certstack, - char *vomsdir) +int GRSTx509ParseVomsExt(int *lastcred, int maxcreds, size_t credlen, + char *creds, time_t *time1_time, time_t *time2_time, + X509_EXTENSION *ex, char *ucuser, char *vomsdir) { -#ifndef GRST_VOMS_SUPPORT - return GRST_RET_OK; -} -#else - -/* - int j; - unsigned int siglen=-1, datalength=-1, dataoffset = -1; - char s[80]; - unsigned char *charstr, *p, *time1 = NULL, *time2 = NULL, *vo = NULL, - *uri = NULL, *user = NULL, *group = "NULL", *role = "NULL", - *cap = "NULL", *server = NULL, *ucuser, *signature = NULL, - *data = NULL, *datalen = NULL; - X509_EXTENSION *ex; - ASN1_STRING *asn1str; - time_t now, time1_time = 0, time2_time = 0, - uctime1_time, uctime2_time; -*/ - - - struct vomsdata *vd; - int i, j, vomserror; - - vd = VOMS_Init(NULL, NULL); +#define MAXTAG 500 +#define FQAN_COORDS "-1-1-1-1-7-1-2-1-2-%d" + ASN1_OCTET_STRING *asn1data; + char *asn1string, s[81]; + long asn1length; + int lasttag=-1, itag, i; + struct GRSTasn1TagList taglist[MAXTAG+1]; + + asn1data = X509_EXTENSION_get_data(ex); + asn1string = ASN1_STRING_data(asn1data); + asn1length = ASN1_STRING_length(asn1data); + + GRSTasn1ParseDump(NULL, asn1string, asn1length, taglist, MAXTAG, &lasttag); + + for (i=1; ; ++i) + { +// should find signature and check it here, first + + sprintf(s, FQAN_COORDS, i); + itag = GRSTasn1SearchTaglist(taglist, &lasttag, s); - if (VOMS_Retrieve(cert, certstack, RECURSE_CHAIN, vd, &vomserror) && - (vd->data != NULL)) - { - for (i = 0; vd->data[i] != NULL; ++i) + if (itag > -1) { - if (vd->data[i]->fqan != NULL) - for (j = 0; vd->data[i]->fqan[j] != NULL; ++j) - { - if (*lastcred >= maxcreds - 1) - { - VOMS_Destroy(vd); - return GRST_RET_OK; - } - - ++(*lastcred); - - snprintf(&creds[*lastcred * (credlen + 1)], - credlen+1, - "VOMS %010lu %010lu 0 %s", - GRSTasn1TimeToTimeT(vd->data[i]->date1), - GRSTasn1TimeToTimeT(vd->data[i]->date2), - vd->data[i]->fqan[j]); - } + if (*lastcred < maxcreds - 1) + { + ++(*lastcred); + + snprintf(&creds[*lastcred * (credlen + 1)], credlen+1, + "VOMS %010lu %010lu 0 %.*s", + *time1_time, *time2_time, + taglist[itag].length, + &asn1string[taglist[itag].start+ + taglist[itag].headerlength]); + } } - } - else - { - FILE *fp = fopen("/tmp/getvoms.log", "w"); - fprintf(fp, "%d\n", vomserror); - fclose(fp); - } - - VOMS_Destroy(vd); + else break; + } + return GRST_RET_OK; } -#if 0 +/// Get the VOMS attributes in the extensions to the given cert stack +/* + * Puts any VOMS credentials found into the Compact Creds string array + * starting at *creds. Always returns GRST_RET_OK. + */ - time(&now); +int GRSTx509GetVomsCreds(int *lastcred, int maxcreds, size_t credlen, + char *creds, X509 *usercert, STACK_OF(X509) *certstack, + char *vomsdir) +{ + int i, j, vomsfound=0; + char s[80]; + unsigned char *ucuser; + X509_EXTENSION *ex; + ASN1_STRING *asn1str; + X509 *cert; + time_t time1_time = 0, time2_time = 0, uctime1_time, uctime2_time; uctime1_time = GRSTasn1TimeToTimeT(ASN1_STRING_data(X509_get_notBefore(usercert))); @@ -479,15 +471,38 @@ int GRSTx509GetVomsCreds(int *lastcred, int maxcreds, size_t credlen, ucuser = X509_NAME_oneline(X509_get_subject_name(usercert), NULL, 0); - for (i = 0; i < X509_get_ext_count(cert); ++i) - { - ex = X509_get_ext(cert, i); - - OBJ_obj2txt(s, sizeof(s), X509_EXTENSION_get_object(ex), 1); + for (j=sk_X509_num(certstack)-1; j >= 0; --j) + { + cert = sk_X509_value(certstack, j); - if (strcmp(s, GRST_VOMS_OID) == 0) /* a VOMS extension */ - { - asn1str = X509_EXTENSION_get_data(ex); + time1_time = + GRSTasn1TimeToTimeT(ASN1_STRING_data(X509_get_notBefore(cert))); + uctime1_time = (time1_time > uctime1_time) ? time1_time:uctime1_time; + + time2_time = + GRSTasn1TimeToTimeT(ASN1_STRING_data(X509_get_notAfter(cert))); + uctime2_time = (time2_time < uctime2_time) ? time2_time:uctime2_time; + + for (i=0; i < X509_get_ext_count(cert); ++i) + { + ex = X509_get_ext(cert, i); + OBJ_obj2txt(s, sizeof(s), X509_EXTENSION_get_object(ex), 1); + + if (strcmp(s, GRST_VOMS_OID) == 0) /* a VOMS extension */ + { + vomsfound=1; + GRSTx509ParseVomsExt(lastcred, maxcreds, credlen, creds, + &uctime1_time, &uctime2_time, + ex, ucuser, vomsdir); + } + } + + if (vomsfound) return GRST_RET_OK; + } + + return GRST_RET_OK; +} +#if 0 charstr = (char *) malloc(ASN1_STRING_length(asn1str) + 1); memcpy(charstr, ASN1_STRING_data(asn1str), ASN1_STRING_length(asn1str)); @@ -700,8 +715,6 @@ int GRSTx509GetVomsCreds(int *lastcred, int maxcreds, size_t credlen, } #endif -#endif - /// Turn a Compact Cred line into a GRSTgaclCred object /** * Returns pointer to created GRSTgaclCred or NULL or failure. @@ -825,9 +838,10 @@ int GRSTx509CompactCreds(int *lastcred, int maxcreds, size_t credlen, { ++(*lastcred); strcpy(&creds[*lastcred * (credlen + 1)], credtemp); - + GRSTx509GetVomsCreds(lastcred, maxcreds, credlen, creds, - gsiproxycert, certstack, vomsdir); + usercert, certstack, vomsdir); + } return GRST_RET_OK; diff --git a/org.gridsite.core/src/real-gridsite-admin.cgi b/org.gridsite.core/src/real-gridsite-admin.cgi index aa3f9e19ca75480470c47b1a945eab94fd9fdf39..0e1e8edec84dca415787e1cb93a41d89f423c608 100644 GIT binary patch literal 105006 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

%K-Hzg6l3 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 KW~28i;Qs|I8v!%` delta 40436 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 +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "gridsite.h" + +#define MAXTAG 500 + +main() +{ + X509 *cert, *tmpcert; + STACK_OF(X509) *certstack = sk_X509_new_null(); + FILE *fp; + struct vomsdata *vd; + int i, j, vomserror, i1, i2, j1, j2, lastobject; + X509_EXTENSION *ex; + ASN1_OBJECT *asnobject; + char s[80], *t; + ASN1_OCTET_STRING *asndata; + BIO *out; + unsigned char *p, *op, *tot, *p1, *p2, *q, *oq; + long len1, length1, len2, length2; + int tag,xclass,ret=0; + struct GRSTasn1TagList taglist[MAXTAG+1]; + int lasttag=-1, itag; + + + OpenSSL_add_all_algorithms(); + ERR_load_crypto_strings(); +// seed_prng(); + +// fp = fopen("proxy-with-voms", "r"); + fp = fopen("/tmp/x509up_u300", "r"); + + cert = PEM_read_X509(fp, NULL, NULL, NULL); + + fclose(fp); + + out=BIO_new(BIO_s_file()); + BIO_set_fp(out,stdout,BIO_NOCLOSE|BIO_FP_TEXT); + + for (i = 0; i < X509_get_ext_count(cert); ++i) + { + lasttag=-1; + + ex = X509_get_ext(cert, i); + + OBJ_obj2txt(s, sizeof(s), X509_EXTENSION_get_object(ex), 1); + printf("%d OID=%s\n", i, s); + + asnobject = X509_EXTENSION_get_object(ex); + asndata = X509_EXTENSION_get_data(ex); + + p1 = ASN1_STRING_data(asndata); + p = p1; + length1 = ASN1_STRING_length(asndata); + + GRSTasn1ParseDump(out, p1, length1, taglist, MAXTAG, &lasttag); +/* + itag = GRSTasn1SearchTaglist(taglist, &lasttag, + "1-1-1-1-1-7-1-2-1-2-1"); + + printf("tag=%d %s %d %.*s\n", + itag, taglist[itag].treecoords, taglist[itag].tag, + taglist[itag].length, + &p[taglist[itag].start+taglist[itag].headerlength]); +*/ + } +} -- 1.8.2.3