From a523ea0b68ba1296b2c2eb5030e24cc180108085 Mon Sep 17 00:00:00 2001 From: Andrew McNab Date: Thu, 24 May 2007 13:01:54 +0000 Subject: [PATCH] 1.6 stuff, deprecate Compact Credentials, AURIs etc etc. --- org.gridsite.core/src/Makefile | 15 +- org.gridsite.core/src/gaclexample.c | 22 +- org.gridsite.core/src/grst_admin_gacl.c | 2 + org.gridsite.core/src/grst_gacl.c | 511 +++++++++++++++++++++----------- org.gridsite.core/src/grst_x509.c | 350 ++++++++++------------ org.gridsite.core/src/grst_xacml.c | 20 +- org.gridsite.core/src/htproxyput.c | 15 +- org.gridsite.core/src/mod_gridsite.c | 374 ++++++++++++++++------- 8 files changed, 803 insertions(+), 506 deletions(-) diff --git a/org.gridsite.core/src/Makefile b/org.gridsite.core/src/Makefile index e95abd5..a926168 100644 --- a/org.gridsite.core/src/Makefile +++ b/org.gridsite.core/src/Makefile @@ -60,7 +60,7 @@ endif build: apidoc build-lib \ htcp gridsite-copy.cgi mod_gridsite.so \ - urlencode findproxyfile real-gridsite-admin.cgi gsexec + urlencode findproxyfile gsexec # real-gridsite-admin.cgi build-lib: libgridsite_globus.so.$(VERSION) libgridsite_globus.a \ libgridsite.so.$(VERSION) libgridsite.a @@ -209,6 +209,12 @@ mod_gridsite.so: mod_gridsite.c mod_ssl-private.h libgridsite.so.$(VERSION) -DVERSION=\"$(VERSION)\" -o mod_gridsite.so \ mod_gridsite.c $(MYLDFLAGS) -lxml2 -lm -lz -lgridsite +mod_gridsite_example.so: mod_gridsite_example.c + gcc -g -shared -Wl,-soname=gridsite_example_module \ + -I/usr/include/httpd -I/usr/include/apr-0 \ + -DVERSION=\"$(VERSION)\" -o mod_gridsite_example.so \ + mod_gridsite_example.c + real-gridsite-admin.cgi: grst_admin_main.c grst_admin_gacl.c \ grst_admin_file.c grst_admin.h gcc -g $(MYCFLAGS) $(MYLDFLAGS) -o real-gridsite-admin.cgi \ @@ -253,12 +259,12 @@ apidoc: > $$i.html ; done gaclexample: gaclexample.c libgridsite.a - gcc -g -o gaclexample gaclexample.c -I. -L. \ + gcc -g -o gaclexample gaclexample.c -I../interface -L. \ -I/usr/kerberos/include -lgridsite \ -lssl -lcrypto -lxml2 -lz -lm xacmlexample: xacmlexample.c libgridsite.a - gcc -g -o xacmlexample xacmlexample.c -I. -L. \ + gcc -g -o xacmlexample xacmlexample.c -I../interface -L. \ -I/usr/kerberos/include -lgridsite \ -lssl -lcrypto -lxml2 -lz -lm # @@ -338,6 +344,7 @@ install: apidoc install-lib $(prefix)/share/man/man1 \ $(prefix)/share/man/man8 \ $(prefix)/lib/httpd/modules \ + mod_gridsite_example.c \ $(prefix)/share/doc/gridsite-$(MINOR_VERSION) cp -f ../interface/gridsite.h $(prefix)/include cp -f ../interface/gridsite-gacl.h $(prefix)/include @@ -441,7 +448,7 @@ dist: cp -f ../VERSION ../README ../LICENSE ../CHANGES ../INSTALL \ ../dist/gridsite-$(PATCH_VERSION) cp -f Makefile grst*.c htcp.c slashgrid.c slashgrid.init \ - urlencode.c findproxyfile.c gaclexample.c mod_gridsite.c \ + urlencode.c findproxyfile.c gaclexample.c mod_gridsite*.c \ htproxyput.c grst_admin.h mod_ssl-private.h \ gsexec.c gsexec.h gridsite-copy.c delegation.h \ roffit make-gridsite-spec \ diff --git a/org.gridsite.core/src/gaclexample.c b/org.gridsite.core/src/gaclexample.c index 5ad29b7..32aaaa4 100644 --- a/org.gridsite.core/src/gaclexample.c +++ b/org.gridsite.core/src/gaclexample.c @@ -1,5 +1,5 @@ /* - Copyright (c) 2002-3, Andrew McNab, University of Manchester + Copyright (c) 2002-7, Andrew McNab, University of Manchester All rights reserved. Redistribution and use in source and binary forms, with or @@ -61,9 +61,7 @@ int main() /* build up an ACL, starting with a credential */ - cred = GRSTgaclCredNew("person"); - - GRSTgaclCredAddValue(cred, "dn", "/O=Grid/CN=Mr Grid Person"); + cred = GRSTgaclCredCreate("dn:", "/O=Grid/CN=Mr Grid Person"); /* create an entry to put it in */ @@ -75,11 +73,10 @@ int main() /* add another credential */ - cred = GRSTgaclCredNew("dn-list"); - GRSTgaclCredAddValue(cred, "url", "example-dn-list"); + cred = GRSTgaclCredCreate("https://example-dn-list", NULL); /* DN List */ GRSTgaclEntryAddCred(entry, cred); - fp = fopen("example-dn-list", "w"); + fp = fopen("https%3A%2F%2Fexample-dn-list", "w"); fputs("/O=Grid/CN=Mr Grid Person\n", fp); fclose(fp); @@ -93,7 +90,7 @@ int main() perm0 = GRST_PERM_READ | GRST_PERM_WRITE; - printf("test perm should be %d\n", perm0); + printf("\n**** perm should be %d in the following tests! ****\n\n", perm0); /* create a new ACL and add the entry to it */ @@ -103,9 +100,10 @@ int main() /* create a GRSTgaclUser to compare with the ACL */ - usercred = GRSTgaclCredNew("person"); - + /* old style cred creation: use GRSTgaclCredCreate as above now */ + usercred = GRSTgaclCredNew("person"); GRSTgaclCredAddValue(usercred, "dn", "/O=Grid/CN=Mr Grid Person"); + /* end of old style cred creation */ user = GRSTgaclUserNew(usercred); @@ -116,7 +114,7 @@ int main() perm1 = GRSTgaclAclTestUser(acl1, user); - printf("test /O=Grid/CN=Mr Grid Person in acl = %d\n", perm1); + printf("test /O=Grid/CN=Mr Grid Person in acl, perm = %d\n", perm1); /* print and save the whole ACL */ @@ -138,7 +136,7 @@ int main() perm2 = GRSTgaclAclTestUser(acl2, user); - printf("test /O=Grid/CN=Mr Grid Person in acl = %d\n", perm2); + printf("test /O=Grid/CN=Mr Grid Person in acl, perm = %d\n", perm2); if (perm1 != perm0) return 1; if (perm2 != perm0) return 2; diff --git a/org.gridsite.core/src/grst_admin_gacl.c b/org.gridsite.core/src/grst_admin_gacl.c index bdcccbd..6bce4fb 100644 --- a/org.gridsite.core/src/grst_admin_gacl.c +++ b/org.gridsite.core/src/grst_admin_gacl.c @@ -43,6 +43,8 @@ extern char *grst_perm_syms[]; extern int grst_perm_vals[]; + + #include "grst_admin.h" // CGI GACL Editor interface functions diff --git a/org.gridsite.core/src/grst_gacl.c b/org.gridsite.core/src/grst_gacl.c index c2c4ecd..539a44e 100644 --- a/org.gridsite.core/src/grst_gacl.c +++ b/org.gridsite.core/src/grst_gacl.c @@ -36,9 +36,11 @@ #include #include #include +#include #include #include #include +#include #include #ifndef _GNU_SOURCE @@ -71,7 +73,7 @@ GRSTgaclPerm grst_perm_vals[] = { GRST_PERM_NONE, GRST_PERM_WRITE, GRST_PERM_ADMIN, -1 }; - + int GRSTgaclInit(void) { xmlInitParser(); @@ -92,37 +94,80 @@ GRSTgaclAcl *GRSTxacmlAclParse(xmlDocPtr, xmlNodePtr, GRSTgaclAcl *); * Functions to manipulate GRSTgaclCred structures * * */ -GRSTgaclCred *GRSTgaclCredNew(char *type) +GRSTgaclCred *GRSTgaclCredCreate(char *auri_prefix, char *auri_suffix) /* - GRSTgaclCredNew - allocate a new GRSTgaclCred structure, and return - it's pointer or NULL on (malloc) error. + GRSTgaclCredCreate - allocate a new GRSTgaclCred structure, and return + it's pointer or NULL on (malloc) error. */ { + int i; + char *auri; GRSTgaclCred *newcred; - if (type == NULL) return NULL; + if ((auri_prefix != NULL) && (auri_suffix == NULL)) + auri = strdup(auri_prefix); + else if ((auri_prefix == NULL) && (auri_suffix != NULL)) + auri = strdup(auri_suffix); + else if ((auri_prefix != NULL) && (auri_suffix != NULL)) + asprintf(&auri, "%s%s", auri_prefix, auri_suffix); + else return NULL; + + for (i=0; (auri[i] != '\0') && isspace(auri[i]); ++i) ; /* leading space */ + + for (i=strlen(auri) - 1; (i >= 0) && isspace(auri[i]); --i) + auri[i]='\0'; /* trailing space */ newcred = malloc(sizeof(GRSTgaclCred)); - if (newcred == NULL) return NULL; + if (newcred == NULL) + { + free(auri); + return NULL; + } - newcred->type = strdup(type); + newcred->auri = auri; newcred->delegation = 0; - newcred->firstname = NULL; + newcred->nist_loa = 0; + newcred->notbefore = 0; + newcred->notafter = 0; newcred->next = NULL; return newcred; } -int GRSTgaclCredAddValue(GRSTgaclCred *cred, char *rawname, char *rawvalue) +GRSTgaclCred *GRSTgaclCredNew(char *type) +/* + GRSTgaclCredNew - allocate a new GRSTgaclCred structure, and return + it's pointer or NULL on (malloc) error. +*/ +{ + if (type == NULL) return NULL; + + if ((strcmp(type, "person" ) == 0) || + (strcmp(type, "voms" ) == 0) || + (strcmp(type, "dn-list") == 0) || + (strcmp(type, "dns" ) == 0) || + (strcmp(type, "level" ) == 0)) return GRSTgaclCredCreate("", NULL); + + if (strcmp(type, "any-user") == 0) + return GRSTgaclCredCreate("gacl:", "any-user"); + + if (strcmp(type, "auth-user") == 0) + return GRSTgaclCredCreate("gacl:", "auth-user"); + + return NULL; +} + +int GRSTgaclCredAddValue(GRSTgaclCred *cred, char *name, char *rawvalue) /* GRSTgaclCredAddValue - add a name/value pair to a GRSTgaclCred */ { int i; - char *name, *value; - GRSTgaclNamevalue *p; + char *value; - name = strdup(rawname); + if ((cred == NULL) || (cred->auri == NULL)) return 0; + free(cred->auri); + cred->auri = NULL; /* no leading or trailing space in value */ @@ -130,42 +175,41 @@ int GRSTgaclCredAddValue(GRSTgaclCred *cred, char *rawname, char *rawvalue) while ((*value != '\0') && isspace(*value)) ++value; value = strdup(value); - for (i=strlen(value) - 1; (i >= 0) && isspace(value[i]); --i) value[i]='\0'; - - if (cred->firstname == NULL) + + if (strcmp(name, "dn") == 0) { - cred->firstname = malloc(sizeof (GRSTgaclNamevalue)); - (cred->firstname)->name = name; - (cred->firstname)->value = value; - (cred->firstname)->next = NULL; + asprintf(&(cred->auri), "dn:%s", value); + free(value); + return 1; } - else + else if (strcmp(name, "fqan") == 0) { - p = cred->firstname; - - while (p->next != NULL) p = (GRSTgaclNamevalue *) p->next; - - p->next = malloc(sizeof(GRSTgaclNamevalue)); - ((GRSTgaclNamevalue *) p->next)->name = name; - ((GRSTgaclNamevalue *) p->next)->value = value; - ((GRSTgaclNamevalue *) p->next)->next = NULL; - } - - return 1; -} - -static int GRSTgaclNamevalueFree(GRSTgaclNamevalue *p) -{ - if (p == NULL) return 1; - - if (p->next != NULL) - GRSTgaclNamevalueFree((GRSTgaclNamevalue *) p->next); - if (p->name != NULL) free(p->name); - if (p->value != NULL) free(p->value); - free(p); - - return 1; + asprintf(&(cred->auri), "fqan:%s", value); + free(value); + return 1; + } + else if (strcmp(name, "url") == 0) + { + asprintf(&(cred->auri), "%s", value); + free(value); + return 1; + } + else if (strcmp(name, "hostname") == 0) + { + asprintf(&(cred->auri), "dns:%s", value); + free(value); + return 1; + } + else if (strcmp(name, "nist-loa") == 0) + { + asprintf(&(cred->auri), "nist-loa:%s", value); + free(value); + return 1; + } + + free(value); + return 0; } int GRSTgaclCredFree(GRSTgaclCred *cred) @@ -176,8 +220,7 @@ int GRSTgaclCredFree(GRSTgaclCred *cred) { if (cred == NULL) return 1; - GRSTgaclNamevalueFree(cred->firstname); - if (cred->type != NULL) free(cred->type); + if (cred->auri != NULL) free(cred->auri); free(cred); return 1; @@ -259,18 +302,12 @@ int GRSTgaclCredPrint(GRSTgaclCred *cred, FILE *fp) */ { char *q; - GRSTgaclNamevalue *p; - if (cred->firstname != NULL) + if (cred->auri != NULL) { - fprintf(fp, "<%s>\n", cred->type); - - p = cred->firstname; - - do { - fprintf(fp, "<%s>", p->name); + fprintf(fp, "\n"); - for (q=p->value; *q != '\0'; ++q) + for (q=cred->auri; *q != '\0'; ++q) if (*q == '<') fputs("<", fp); else if (*q == '>') fputs(">", fp); else if (*q == '&') fputs("&" , fp); @@ -278,15 +315,16 @@ int GRSTgaclCredPrint(GRSTgaclCred *cred, FILE *fp) else if (*q == '"') fputs(""", fp); else fputc(*q, fp); - fprintf(fp, "\n", p->name); - - p = (GRSTgaclNamevalue *) p->next; - - } while (p != NULL); - - fprintf(fp, "\n", cred->type); + fprintf(fp, "\n"); + + if (cred->nist_loa > 0) + fprintf(fp, "%d\n", cred->nist_loa); + + if (cred->delegation > 0) + fprintf(fp, "%d\n", cred->delegation); + + fprintf(fp, "\n"); } - else fprintf(fp, "<%s/>\n", cred->type); return 1; } @@ -523,7 +561,7 @@ int GRSTgaclAclPrint(GRSTgaclAcl *acl, FILE *fp) { GRSTgaclEntry *entry; - fputs("\n", fp); + fputs("\n", fp); for (entry = acl->firstentry; entry != NULL; entry = entry->next) GRSTgaclEntryPrint(entry, fp); @@ -562,13 +600,51 @@ static GRSTgaclCred *GRSTgaclCredParse(xmlNodePtr cur) returning it as a pointer or NULL on error. */ { - xmlNodePtr cur2; - GRSTgaclCred *cred; - - cred = GRSTgaclCredNew((char *) cur->name); + xmlNodePtr cur2; + GRSTgaclCred *cred = NULL; + + /* generic AURI creds first */ + + if (strcmp((char *) cur->name, "cred") == 0) + { + for (cur2 = cur->xmlChildrenNode; cur2 != NULL; cur2=cur2->next) + { + if (!xmlIsBlankNode(cur2) && + (strcmp((char *) cur2->name, "auri") == 0)) + { + if (cred != NULL) /* multiple AURI */ + { + GRSTgaclCredFree(cred); + cred = NULL; + return NULL; + } + + cred = GRSTgaclCredCreate((char *) xmlNodeGetContent(cur2),NULL); + } + } + + if (cred == NULL) return NULL; + + for (cur2 = cur->xmlChildrenNode; cur2 != NULL; cur2=cur2->next) + { + if (xmlIsBlankNode(cur2)) continue; + + if (strcmp((char *) cur2->name, "nist-loa") == 0) + { + cred->nist_loa = atoi((char *) xmlNodeGetContent(cur2)); + } + else if (strcmp((char *) cur2->name, "delegation") == 0) + { + cred->delegation = atoi((char *) xmlNodeGetContent(cur2)); + } + } + + return cred; + } - cred->firstname = NULL; - cred->next = NULL; + /* backwards compatibility */ + + cred = GRSTgaclCredNew((char *) cur->name); for (cur2 = cur->xmlChildrenNode; cur2 != NULL; cur2=cur2->next) { @@ -827,9 +903,11 @@ GRSTgaclUser *GRSTgaclUserNew(GRSTgaclCred *cred) user = malloc(sizeof(GRSTgaclUser)); - if (user != NULL) user->firstcred = cred; - - user->dnlists = NULL; + if (user != NULL) + { + user->firstcred = cred; + user->dnlists = NULL; + } return user; } @@ -839,7 +917,7 @@ int GRSTgaclUserFree(GRSTgaclUser *user) if (user == NULL) return 1; if (user->firstcred != NULL) GRSTgaclCredsFree(user->firstcred); - + if (user->dnlists != NULL) free(user->dnlists); free(user); @@ -873,124 +951,64 @@ int GRSTgaclUserAddCred(GRSTgaclUser *user, GRSTgaclCred *cred) int GRSTgaclUserHasCred(GRSTgaclUser *user, GRSTgaclCred *cred) /* test if the user has the given credential */ { + int nist_loa = 999; GRSTgaclCred *crediter; - GRSTgaclNamevalue *usernamevalue, *crednamevalue; - if (cred == NULL) return 0; + if ((cred == NULL) || (cred->auri == NULL)) return 0; - if (strcmp(cred->type, "any-user") == 0) return 1; + if (strcmp(cred->auri, "any-user:") == 0) return 1; - if (user == NULL) return 0; + if ((user == NULL) || (user->firstcred == NULL)) return 0; - if (strcmp(cred->type, "dn-list") == 0) - { - if ((cred->firstname == NULL) || - (strcmp((cred->firstname)->name, "url") != 0) || - ((cred->firstname)->next != NULL)) return 0; - - return GRSTgaclDNlistHasUser((cred->firstname)->value, user); - } - - if (strcmp(cred->type, "dns") == 0) - { - if ((user->firstcred == NULL) || - ((user->firstcred)->firstname == NULL) || - (cred->firstname == NULL) || - (strcmp((cred->firstname)->name, "hostname") != 0) || - ((cred->firstname)->next != NULL)) return 0; - + if (strncmp(cred->auri, "dns:", 4) == 0) + { for (crediter=user->firstcred; crediter != NULL; crediter = crediter->next) - if (strcmp(crediter->type, "dns") == 0) - { - if ((crediter->firstname == NULL) || - (strcmp((crediter->firstname)->name, "hostname") != 0)) return 0; - - return (fnmatch((cred->firstname)->value, - (crediter->firstname)->value, FNM_CASEFOLD) == 0); - } - + if ((crediter->auri != NULL) && + (strncmp(crediter->auri, "dns:", 4) == 0)) + return (fnmatch(cred->auri, crediter->auri, FNM_CASEFOLD) == 0); return 0; } - if (strcmp(cred->type, "auth-user") == 0) + if (strcmp(cred->auri, "gacl:auth-user") == 0) { - if ((user->firstcred == NULL) || - ((user->firstcred)->firstname == NULL)) return 0; - for (crediter=user->firstcred; crediter != NULL; crediter = crediter->next) - if (strcmp(crediter->type, "person") == 0) return 1; + if ((crediter->auri != NULL) && + (strncmp(crediter->auri, "dn:", 3) == 0)) return 1; return 0; } - if (strcmp(cred->type, "level") == 0) + if (sscanf(cred->auri, "nist-loa:%d", &nist_loa) == 1) { - if ((user->firstcred == NULL) || - ((user->firstcred)->firstname == NULL)) return 0; - for (crediter=user->firstcred; crediter != NULL; crediter = crediter->next) - if (strcmp(crediter->type, "level") == 0) - { - if (atoi(user->firstcred->firstname->value) - >= atoi(crediter->firstname->value)) return 1; + if ((crediter->auri != NULL) && + (strncmp(crediter->auri, "dn:", 3) == 0) && + (crediter->nist_loa >= nist_loa)) return 1; - return 0; - } - return 0; } +// can remove this once we preload DN Lists etc as AURIs? + if ((strncmp(cred->auri, "http:", 5) == 0) || + (strncmp(cred->auri, "https:", 6) == 0)) + { + return GRSTgaclDNlistHasUser(cred->auri, user); + } + + /* generic AURI = AURI test */ + for (crediter=user->firstcred; crediter != NULL; crediter = crediter->next) - { - if (strcmp(crediter->type, cred->type) != 0) continue; - - if ((crediter->firstname == NULL) && - (cred->firstname == NULL)) return 1; - - if ((crediter->firstname == NULL) || - (cred->firstname == NULL)) continue; - - usernamevalue = crediter->firstname; - crednamevalue = cred->firstname; - - for (;;) - { - if (strcmp(usernamevalue->name,crednamevalue->name) != 0) break; - - if (strcmp(cred->type, "person") == 0) - { - if (GRSTx509NameCmp(usernamevalue->value, - crednamevalue->value) != 0) break; - } -/* - else if (strcmp(cred->type, "level") == 0) - { - if (atoi(usernamevalue->value) - < atoi(crednamevalue->value)) break; - } -*/ - else if (strcmp(usernamevalue->value, - crednamevalue->value) != 0) break; - - /* ok if cred list runs out before user's cred list */ - if (crednamevalue->next == NULL) return 1; - - /* but not ok if more names to match which user doesn't have */ - if (usernamevalue->next == NULL) break; - - crednamevalue = (GRSTgaclNamevalue *) crednamevalue->next; - usernamevalue = (GRSTgaclNamevalue *) usernamevalue->next; - } - } - - return 0; + if ((crediter->auri != NULL) && + (strcmp(crediter->auri, cred->auri) == 0)) return 1; + + return 0; } GRSTgaclCred *GRSTgaclUserFindCredtype(GRSTgaclUser *user, char *type) @@ -1004,7 +1022,18 @@ GRSTgaclCred *GRSTgaclUserFindCredtype(GRSTgaclUser *user, char *type) while (cred != NULL) { - if (strcmp(cred->type, type) == 0) return cred; + if ((strcmp(type, "person") == 0) && + (strncmp(cred->auri, "dn:", 3) == 0)) return cred; + + if ((strcmp(type, "voms") == 0) && + (strncmp(cred->auri, "fqan:", 5) == 0)) return cred; + + if ((strcmp(type, "dns") == 0) && + (strncmp(cred->auri, "dns:", 4) == 0)) return cred; + + if ((strcmp(type, "dn-list") == 0) && + ((strncmp(cred->auri, "http:", 5) == 0) || + (strncmp(cred->auri, "https:", 6) == 0))) return cred; cred = cred->next; } @@ -1014,12 +1043,150 @@ GRSTgaclCred *GRSTgaclUserFindCredtype(GRSTgaclUser *user, char *type) int GRSTgaclUserSetDNlists(GRSTgaclUser *user, char *dnlists) { - if ((user == NULL) || (dnlists == NULL)) return 0; - if (user->dnlists != NULL) free(user->dnlists); - user->dnlists = strdup(dnlists); + if (dnlists == NULL) user->dnlists = NULL; + else user->dnlists = strdup(dnlists); + + return GRSTgaclUserLoadDNlists(user, dnlists); +} + +static void recurse4dnlists(GRSTgaclUser *user, char *dir, + int recurse_level, GRSTgaclCred *dn_cred) +/* try to find file[] in dir[]. try subdirs if not found. + return full path to first found version or NULL on failure */ +{ + int fd, linestart, i; + char *fullfilename, *mapped, *q, *s; + size_t dn_len; + struct stat statbuf; + DIR *dirDIR; + struct dirent *file_ent; + GRSTgaclCred *cred; + + if (recurse_level >= GRST_RECURS_LIMIT) return; + + dn_len = strlen(dn_cred->auri) - 3; + /* search this directory */ + + dirDIR = opendir(dir); + + if (dirDIR == NULL) return; + + while ((file_ent = readdir(dirDIR)) != NULL) + { + if (file_ent->d_name[0] == '.') continue; + + asprintf(&fullfilename, "%s/%s", dir, file_ent->d_name); + + GRSTerrorLog(GRST_LOG_DEBUG, "recurse4dnlists opens %s", fullfilename); + + if ((fd = open(fullfilename, O_RDONLY)) < 0) + ; + else if (fstat(fd, &statbuf) != 0) + ; + else if (S_ISDIR(statbuf.st_mode)) + recurse4dnlists(user, fullfilename, recurse_level + 1, dn_cred); + else if ((S_ISREG(statbuf.st_mode) || S_ISLNK(statbuf.st_mode)) && + ((mapped = mmap(NULL, statbuf.st_size, + PROT_READ, MAP_PRIVATE, fd, 0)) != MAP_FAILED)) + { + linestart = 0; + + while (linestart + dn_len <= statbuf.st_size) + { + GRSTerrorLog(GRST_LOG_DEBUG, "recurse4dnlists at %ld in %s", + linestart, fullfilename); + + for (i=0; + (linestart + i < statbuf.st_size) && (i < dn_len); + ++i) + if (mapped[linestart + i] != dn_cred->auri[3+i]) break; + + GRSTerrorLog(GRST_LOG_DEBUG, "recurse4dnlists at %d %d %d %d", + linestart, i, dn_len, statbuf.st_size); + + if ((i == dn_len) && + ((linestart+i == statbuf.st_size) || + (mapped[linestart+i] == '\n') || + (mapped[linestart+i] == '\r'))) /* matched */ + { + s = GRSThttpUrlDecode(file_ent->d_name); + cred = GRSTgaclCredCreate(s, NULL); + GRSTerrorLog(GRST_LOG_DEBUG, + "recurse4dnlists adds %s", s); + free(s); + + GRSTgaclCredSetNotBefore(cred, dn_cred->notbefore); + GRSTgaclCredSetNotAfter(cred, dn_cred->notafter); + GRSTgaclCredSetDelegation(cred, dn_cred->delegation); + GRSTgaclCredSetNistLoa(cred, dn_cred->nist_loa); + + GRSTgaclUserAddCred(user, cred); + break; + } + + linestart += i; + + while ((linestart < statbuf.st_size) && + (mapped[linestart] != '\n') && + (mapped[linestart] != '\r')) ++linestart; + + while ((linestart < statbuf.st_size) && + ((mapped[linestart] == '\n') || + (mapped[linestart] == '\r'))) ++linestart; + } + + munmap(mapped, statbuf.st_size); + } + + if (fd < 0) close(fd); + free(fullfilename); + } + + closedir(dirDIR); +} + +int GRSTgaclUserLoadDNlists(GRSTgaclUser *user, char *dnlists) +/* + Examine DN Lists for attributes belonging to this user and + add them to *user as additional credentials. +*/ +{ + char *dn_lists_dirs, *dn_list_ptr, *filename, *dirname, *dn = NULL; + GRSTgaclCred *dn_cred; + + /* check for DN Lists */ + + if (dnlists == NULL) dnlists = getenv("GRST_DN_LISTS"); + + if (dnlists == NULL) dnlists = GRST_DN_LISTS; + + if (*dnlists == '\0') return 1; /* Didn't ask for anything: that's ok */ + + /* find this user's (first) DN */ + + if (user == NULL) return 1; /* No user! */ + + for (dn_cred = user->firstcred; dn_cred != NULL; dn_cred = dn_cred->next) + { + if (strncmp(dn_cred->auri, "dn:", 3) == 0) break; + } + + if (dn_cred == NULL) return 1; /* User has no DN! */ + + /* look through DN List files */ + + dn_lists_dirs = strdup(dnlists); /* we need to keep this for free() later! */ + dn_list_ptr = dn_lists_dirs; /* copy, for naughty function strsep() */ + + while ((dirname = strsep(&dn_list_ptr, ":")) != NULL) + { + recurse4dnlists(user, dirname, 0, dn_cred); + } + + free(dn_lists_dirs); return 1; } @@ -1110,10 +1277,8 @@ int GRSTgaclDNlistHasUser(char *listurl, GRSTgaclUser *user) while (cred != NULL) { - if ((strcmp(cred->type, "person") == 0) && - (cred->firstname != NULL) && - (strcmp("dn", (cred->firstname)->name) == 0) && - (GRSTx509NameCmp(line, (cred->firstname)->value) == 0)) + if ((strncmp(cred->auri, "dn:", 3) == 0) && + (GRSTx509NameCmp(line, &(cred->auri[3])) == 0)) { fclose(fp); free(dn_lists_dirs); @@ -1157,7 +1322,7 @@ GRSTgaclPerm GRSTgaclAclTestUser(GRSTgaclAcl *acl, GRSTgaclUser *user) for (cred = entry->firstcred; cred != NULL; cred = cred->next) if (!GRSTgaclUserHasCred(user, cred)) flag = 0; - else if (strcmp(cred->type, "any-user") != 0) onlyanyuser = 0; + else if (strcmp(cred->auri, "any-user:") != 0) onlyanyuser = 0; if (!flag) continue; /* flag false if a subtest failed */ @@ -1200,7 +1365,7 @@ GRSTgaclPerm GRSTgaclAclTestexclUser(GRSTgaclAcl *acl, GRSTgaclUser *user) for (cred = entry->firstcred; cred != NULL; cred = cred->next) { - if (strcmp(cred->type, "person") != 0) + if (strncmp(cred->auri, "dn:", 3) != 0) /* if we ever add support for other person-specific credentials, they must also be recognised here */ { diff --git a/org.gridsite.core/src/grst_x509.c b/org.gridsite.core/src/grst_x509.c index 99741d3..5ab98e6 100644 --- a/org.gridsite.core/src/grst_x509.c +++ b/org.gridsite.core/src/grst_x509.c @@ -1,5 +1,5 @@ /* - Copyright (c) 2002-6, Andrew McNab, University of Manchester + Copyright (c) 2002-7, Andrew McNab, University of Manchester All rights reserved. Redistribution and use in source and binary forms, with or @@ -72,14 +72,13 @@ /// Compare X509 Distinguished Name strings int GRSTx509NameCmp(char *a, char *b) -/** - * This function attempts to do with string representations what - * would ideally be done with OIDs/values. In particular, we equate - * "/Email=" == "/emailAddress=" to deal with this important change - * between OpenSSL 0.9.6 and 0.9.7. - * Other than that, it is currently the same as ordinary strcasecmp(3) - * (for consistency with EDG/LCG/EGEE gridmapdir case insensitivity.) - */ +/// +/// This function attempts to do with string representations what +/// would ideally be done with OIDs/values. In particular, we equate +/// "/Email=" == "/emailAddress=" to deal with this important change +/// between OpenSSL 0.9.6 and 0.9.7. +/// Other than that, it is currently the same as ordinary strcasecmp(3) +/// (for consistency with EDG/LCG/EGEE gridmapdir case insensitivity.) { int ret; char *aa, *bb, *p; @@ -110,17 +109,15 @@ int GRSTx509NameCmp(char *a, char *b) /// Check critical extensions -/** - * Returning GRST_RET_OK if all of extensions are known to us or - * OpenSSL; GRST_REF_FAILED otherwise. - * - * Since this function relies on functionality (X509_supported_extension) - * introduced in 0.9.7, then we do nothing and report an error - * (GRST_RET_FAILED) if one of the associated defines - * (X509_V_ERR_UNHANDLED_CRITICAL_EXTENSION) is absent. - */ - int GRSTx509KnownCriticalExts(X509 *cert) +/// +/// Returning GRST_RET_OK if all of extensions are known to us or +/// OpenSSL; GRST_REF_FAILED otherwise. +/// +/// Since this function relies on functionality (X509_supported_extension) +/// introduced in 0.9.7, then we do nothing and report an error +/// (GRST_RET_FAILED) if one of the associated defines +/// (X509_V_ERR_UNHANDLED_CRITICAL_EXTENSION) is absent. { int i; char s[80]; @@ -147,11 +144,9 @@ int GRSTx509KnownCriticalExts(X509 *cert) } /// Check if certificate can be used as a CA to sign standard X509 certs -/* - * Return GRST_RET_OK if true; GRST_RET_FAILED if not. - */ - int GRSTx509IsCA(X509 *cert) +/// +/// Return GRST_RET_OK if true; GRST_RET_FAILED if not. { int idret, purpose_id; @@ -191,14 +186,12 @@ int GRSTx509ChainFree(GRSTx509Chain *chain) } /// Check a specific signature against a specific (VOMS) cert -/* - * Returns GRST_RET_OK if signature is ok, other values if not. - */ - static int GRSTx509VerifySig(time_t *time1_time, time_t *time2_time, unsigned char *txt, int txt_len, unsigned char *sig, int sig_len, X509 *cert) +/// +/// Returns GRST_RET_OK if signature is ok, other values if not. { int ret; EVP_PKEY *prvkey; @@ -241,15 +234,13 @@ static int GRSTx509VerifySig(time_t *time1_time, time_t *time2_time, } /// Check the signature of the VOMS attributes -/* - * Returns GRST_RET_OK if signature is ok, other values if not. - */ - static int GRSTx509VerifyVomsSig(time_t *time1_time, time_t *time2_time, unsigned char *asn1string, struct GRSTasn1TagList taglist[], int lasttag, char *vomsdir, int acnumber) +/// +/// 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" @@ -375,15 +366,13 @@ static int GRSTx509VerifyVomsSig(time_t *time1_time, time_t *time2_time, } /// Get the VOMS attributes in the given extension -/* - * Add any VOMS credentials found into the chain. Always returns GRST_RET_OK - * - even for invalid credentials, which are flagged in errors field - */ - static int GRSTx509ChainVomsAdd(GRSTx509Cert **grst_cert, time_t time1_time, time_t time2_time, X509_EXTENSION *ex, char *ucuserdn, char *vomsdir) +/// +/// 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" @@ -399,7 +388,6 @@ static int GRSTx509ChainVomsAdd(GRSTx509Cert **grst_cert, int lasttag=-1, itag, i, acnumber = 1, chain_errors = 0; struct GRSTasn1TagList taglist[MAXTAG+1]; time_t actime1 = 0, actime2 = 0, time_now; - GRSTx509Cert *new_grst_cert; asn1data = X509_EXTENSION_get_data(ex); asn1string = ASN1_STRING_data(asn1data); @@ -465,8 +453,8 @@ static int GRSTx509ChainVomsAdd(GRSTx509Cert **grst_cert, *grst_cert = (*grst_cert)->next; bzero(*grst_cert, sizeof(GRSTx509Cert)); - (*grst_cert)->start = time1_time; - (*grst_cert)->finish = time2_time; + (*grst_cert)->notbefore = time1_time; + (*grst_cert)->notafter = time2_time; asprintf(&((*grst_cert)->value), "%.*s", taglist[itag].length, &asn1string[taglist[itag].start+ @@ -485,20 +473,18 @@ static int GRSTx509ChainVomsAdd(GRSTx509Cert **grst_cert, } /// Check certificate chain for GSI proxy acceptability. -/** - * Returns GRST_RET_OK if valid; OpenSSL X509 errors otherwise. - * - * The GridSite version handles old and new style Globus proxies, and - * proxies derived from user certificates issued with "X509v3 Basic - * Constraints: CA:FALSE" (eg UK e-Science CA) - * - * TODO: we do not yet check ProxyCertInfo and ProxyCertPolicy extensions - * (although via GRSTx509KnownCriticalExts() we can accept them.) - */ - int GRSTx509ChainLoadCheck(GRSTx509Chain **chain, STACK_OF(X509) *certstack, X509 *lastcert, char *capath, char *vomsdir) +/// +/// Returns GRST_RET_OK if valid; OpenSSL X509 errors otherwise. +/// +/// The GridSite version handles old and new style Globus proxies, and +/// proxies derived from user certificates issued with "X509v3 Basic +/// Constraints: CA:FALSE" (eg UK e-Science CA) +/// +/// TODO: we do not yet check ProxyCertInfo and ProxyCertPolicy extensions +/// (although via GRSTx509KnownCriticalExts() we can accept them.) { X509 *cert; /* Points to the current cert in the loop */ X509 *cacert = NULL; /* The CA root cert */ @@ -560,6 +546,8 @@ int GRSTx509ChainLoadCheck(GRSTx509Chain **chain, 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"); } *chain = malloc(sizeof(GRSTx509Chain)); @@ -602,28 +590,44 @@ int GRSTx509ChainLoadCheck(GRSTx509Chain **chain, { /* if first cert does not claim to be a self-signed copy of a CA root cert in the store, we check the signature */ - - ret = X509_check_issued(cacert, cert); - GRSTerrorLog(GRST_LOG_DEBUG, + if (cacert == NULL) + { + chain_errors |= GRST_CERT_BAD_CHAIN; + ret = X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT; + } + else + { + ret = X509_check_issued(cacert, cert); + + GRSTerrorLog(GRST_LOG_DEBUG, "Cert sig check %d returns %d", i, ret); - if (ret != X509_V_OK) + if (ret != X509_V_OK) new_grst_cert->errors |= GRST_CERT_BAD_SIG; + } } else if ((i == depth - 2) && (subjecthash == issuerhash)) { /* first cert claimed to be a self-signed copy of a CA root cert in the store, we check the signature of the second cert, using OUR copy of the CA cert DIRECT from the store */ - - ret = X509_check_issued(cacert, cert); - GRSTerrorLog(GRST_LOG_DEBUG, + if (cacert == NULL) + { + chain_errors |= GRST_CERT_BAD_CHAIN; + ret = X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT; + } + else + { + ret = X509_check_issued(cacert, cert); + + GRSTerrorLog(GRST_LOG_DEBUG, "Cert sig check %d returns %d", i, ret); - if (ret != X509_V_OK) + if (ret != X509_V_OK) new_grst_cert->errors |= GRST_CERT_BAD_SIG; + } } else if (i < depth - 1) { @@ -645,17 +649,17 @@ int GRSTx509ChainLoadCheck(GRSTx509Chain **chain, new_grst_cert->serial = (int) ASN1_INTEGER_get( X509_get_serialNumber(cert)); - new_grst_cert->start = GRSTasn1TimeToTimeT( + new_grst_cert->notbefore = GRSTasn1TimeToTimeT( ASN1_STRING_data(X509_get_notBefore(cert)), 0); - new_grst_cert->finish = GRSTasn1TimeToTimeT( + new_grst_cert->notafter = GRSTasn1TimeToTimeT( ASN1_STRING_data(X509_get_notAfter(cert)), 0); /* we check times and record if invalid */ - if (now < new_grst_cert->start) + if (now < new_grst_cert->notbefore) new_grst_cert->errors |= GRST_CERT_BAD_TIME; - if (now > new_grst_cert->finish) + if (now > new_grst_cert->notafter) new_grst_cert->errors |= GRST_CERT_BAD_TIME; new_grst_cert->dn = X509_NAME_oneline(X509_get_subject_name(cert),NULL,0); @@ -683,14 +687,19 @@ int GRSTx509ChainLoadCheck(GRSTx509Chain **chain, new_grst_cert->type = GRST_CERT_TYPE_EEC; first_non_ca = i; ucuserdn = new_grst_cert->dn; + new_grst_cert->delegation + = (lastcert == NULL) ? i : i + 1; } } else { new_grst_cert->type = GRST_CERT_TYPE_PROXY; - IsCA = FALSE; + + IsCA = FALSE; /* Force proxy check next iteration. Important because I can sign any CA I create! */ + + new_grst_cert->delegation = (lastcert == NULL) ? i : i + 1; } if (!prevIsCA) @@ -728,7 +737,7 @@ int GRSTx509ChainLoadCheck(GRSTx509Chain **chain, new_grst_cert->errors |= GRST_CERT_BAD_CHAIN; chain_errors |= GRST_CERT_BAD_CHAIN; } - + if (strncmp(proxy_part_DN, "/CN=limited proxy", 17) == 0) prevIsLimited = 1; /* ready for next cert ... */ @@ -740,11 +749,12 @@ int GRSTx509ChainLoadCheck(GRSTx509Chain **chain, if (strcmp(s, GRST_VOMS_OID) == 0) /* a VOMS extension */ { GRSTx509ChainVomsAdd(&grst_cert, - new_grst_cert->start, - new_grst_cert->finish, + new_grst_cert->notbefore, + new_grst_cert->notafter, ex, ucuserdn, vomsdir); + grst_cert->delegation = (lastcert == NULL) ? i : i+1; } } @@ -760,24 +770,22 @@ int GRSTx509ChainLoadCheck(GRSTx509Chain **chain, } /// Check certificate chain for GSI proxy acceptability. -/** - * Returns X509_V_OK/GRST_RET_OK if valid; OpenSSL X509 errors otherwise. - * - * Inspired by GSIcheck written by Mike Jones, SVE, Manchester Computing, - * The University of Manchester. - * - * The GridSite version handles old and new style Globus proxies, and - * proxies derived from user certificates issued with "X509v3 Basic - * Constraints: CA:FALSE" (eg UK e-Science CA) - * - * We do not check chain links between certs here: this is done by - * GRST_check_issued/X509_check_issued in mod_ssl's ssl_engine_init.c - * - * TODO: we do not yet check ProxyCertInfo and ProxyCertPolicy extensions - * (although via GRSTx509KnownCriticalExts() we can accept them.) - */ - int GRSTx509CheckChain(int *first_non_ca, X509_STORE_CTX *ctx) +/// +/// Returns X509_V_OK/GRST_RET_OK if valid; OpenSSL X509 errors otherwise. +/// +/// Inspired by GSIcheck written by Mike Jones, SVE, Manchester Computing, +/// The University of Manchester. +/// +/// The GridSite version handles old and new style Globus proxies, and +/// proxies derived from user certificates issued with "X509v3 Basic +/// Constraints: CA:FALSE" (eg UK e-Science CA) +/// +/// We do not check chain links between certs here: this is done by +/// GRST_check_issued/X509_check_issued in mod_ssl's ssl_engine_init.c +/// +/// TODO: we do not yet check ProxyCertInfo and ProxyCertPolicy extensions +/// (although via GRSTx509KnownCriticalExts() we can accept them.) { STACK_OF(X509) *certstack; /* Points to the client's cert chain */ X509 *cert; /* Points to the client's cert */ @@ -927,11 +935,6 @@ int GRSTx509CheckChain(int *first_non_ca, X509_STORE_CTX *ctx) } /// Example VerifyCallback routine - -/** - * - */ - int GRSTx509VerifyCallback (int ok, X509_STORE_CTX *ctx) { int errnum = X509_STORE_CTX_get_error(ctx); @@ -966,15 +969,13 @@ int GRSTx509VerifyCallback (int ok, X509_STORE_CTX *ctx) } /// 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 - even for invalid - * credentials, which are just ignored. - */ - int GRSTx509ParseVomsExt(int *lastcred, int maxcreds, size_t credlen, char *creds, time_t time1_time, time_t time2_time, X509_EXTENSION *ex, char *ucuserdn, char *vomsdir) +/// +/// Puts any VOMS credentials found into the Compact Creds string array +/// starting at *creds. Always returns GRST_RET_OK - even for invalid +/// credentials, which are just ignored. { #define MAXTAG 500 #define GRST_ASN1_COORDS_FQAN "-1-1-%d-1-7-1-2-1-2-%d" @@ -1052,14 +1053,12 @@ int GRSTx509ParseVomsExt(int *lastcred, int maxcreds, size_t credlen, } /// 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. - */ - int GRSTx509GetVomsCreds(int *lastcred, int maxcreds, size_t credlen, char *creds, X509 *usercert, STACK_OF(X509) *certstack, char *vomsdir) +/// +/// Puts any VOMS credentials found into the Compact Creds string array +/// starting at *creds. Always returns GRST_RET_OK. { int i, j; char s[80]; @@ -1106,11 +1105,9 @@ int GRSTx509GetVomsCreds(int *lastcred, int maxcreds, size_t credlen, } /// Turn a Compact Cred line into a GRSTgaclCred object -/** - * Returns pointer to created GRSTgaclCred or NULL or failure. - */ - GRSTgaclCred *GRSTx509CompactToCred(char *grst_cred) +/// +/// Returns pointer to created GRSTgaclCred or NULL or failure. { int delegation; char *p; @@ -1167,16 +1164,14 @@ GRSTgaclCred *GRSTx509CompactToCred(char *grst_cred) } /// Get the credentials in an X509 cert/GSI proxy, including any VOMS -/** - * Credentials are placed in Compact Creds string array at *creds. - * - * Function returns GRST_RET_OK on success, or GRST_RET_FAILED if - * some inconsistency found in certificate. - */ - int GRSTx509CompactCreds(int *lastcred, int maxcreds, size_t credlen, char *creds, STACK_OF(X509) *certstack, char *vomsdir, X509 *peercert) +/// +/// Credentials are placed in Compact Creds string array at *creds. +/// +/// Function returns GRST_RET_OK on success, or GRST_RET_FAILED if +/// some inconsistency found in certificate. { int i, j, delegation = 0; char credtemp[credlen+1]; @@ -1252,12 +1247,10 @@ int GRSTx509CompactCreds(int *lastcred, int maxcreds, size_t credlen, } /// Find proxy file name of the current user -/** - * Return a string with the proxy file name or NULL if not present. - * This function does not check if the proxy has expired. - */ - char *GRSTx509FindProxyFileName(void) +/// +/// Return a string with the proxy file name or NULL if not present. +/// This function does not check if the proxy has expired. { char *p; @@ -1282,14 +1275,12 @@ static void mpcerror(FILE *debugfp, char *msg) } /// Make a GSI Proxy chain from a request, certificate and private key -/** - * The proxy chain is returned in *proxychain. If debugfp is non-NULL, - * errors are output to that file pointer. The proxy will expired in - * the given number of minutes starting from the current time. - */ - int GRSTx509MakeProxyCert(char **proxychain, FILE *debugfp, char *reqtxt, char *cert, char *key, int minutes) +/// +/// The proxy chain is returned in *proxychain. If debugfp is non-NULL, +/// errors are output to that file pointer. The proxy will expired in +/// the given number of minutes starting from the current time. { char *ptr, *certchain; int i, subjAltName_pos, ncerts; @@ -1518,18 +1509,15 @@ int GRSTx509MakeProxyCert(char **proxychain, FILE *debugfp, } /// Find a proxy file in the proxy cache -/** - * Returns the full path and file name of proxy file associated - * with given delegation ID and user DN. - */ - char *GRSTx509CachedProxyFind(char *proxydir, char *delegation_id, char *user_dn) -/* - Return a pointer to a malloc'd string with the full path of the - proxy file corresponding to the given delegation_id, or NULL - if not found. -*/ +/// +/// Returns the full path and file name of proxy file associated +/// with given delegation ID and user DN. +/// +/// Return a pointer to a malloc'd string with the full path of the +/// proxy file corresponding to the given delegation_id, or NULL +/// if not found. { char *user_dn_enc, *proxyfile; struct stat statbuf; @@ -1551,18 +1539,15 @@ char *GRSTx509CachedProxyFind(char *proxydir, char *delegation_id, } /// Find a temporary proxy private key file in the proxy cache -/** - * Returns the full path and file name of the private key file associated - * with given delegation ID and user DN. - */ - char *GRSTx509CachedProxyKeyFind(char *proxydir, char *delegation_id, char *user_dn) -/* - Return a pointer to a malloc'd string with the full path of the - private proxy key corresponding to the given delegation_id, or NULL - if not found. -*/ +/// +/// Returns the full path and file name of the private key file associated +/// with given delegation ID and user DN. +/// +/// Return a pointer to a malloc'd string with the full path of the +/// private proxy key corresponding to the given delegation_id, or NULL +/// if not found. { char *user_dn_enc, *prvkeyfile; struct stat statbuf; @@ -1599,12 +1584,10 @@ static void mkdir_printf(mode_t mode, char *fmt, ...) } /// Create a X.509 request for a GSI proxy and its private key -/** - * Returns GRST_RET_OK on success, non-zero otherwise. Request string - * and private key are PEM encoded strings - */ - int GRSTx509CreateProxyRequest(char **reqtxt, char **keytxt, char *ocspurl) +/// +/// Returns GRST_RET_OK on success, non-zero otherwise. Request string +/// and private key are PEM encoded strings { int i; char *ptr; @@ -1674,14 +1657,12 @@ int GRSTx509CreateProxyRequest(char **reqtxt, char **keytxt, char *ocspurl) } /// Make and store a X.509 request for a GSI proxy -/** - * Returns GRST_RET_OK on success, non-zero otherwise. Request string - * is PEM encoded, and the key is stored in the temporary cache under - * proxydir - */ - int GRSTx509MakeProxyRequest(char **reqtxt, char *proxydir, char *delegation_id, char *user_dn) +/// +/// Returns GRST_RET_OK on success, non-zero otherwise. Request string +/// is PEM encoded, and the key is stored in the temporary cache under +/// proxydir { int i; char *docroot, *prvkeyfile, *ptr, *user_dn_enc; @@ -1771,13 +1752,11 @@ int GRSTx509MakeProxyRequest(char **reqtxt, char *proxydir, } /// Destroy stored GSI proxy files -/** - * Returns GRST_RET_OK on success, non-zero otherwise. - * (Including GRST_RET_NO_SUCH_FILE if the private key or cert chain - * were not found.) - */ - int GRSTx509ProxyDestroy(char *proxydir, char *delegation_id, char *user_dn) +/// +/// Returns GRST_RET_OK on success, non-zero otherwise. +/// (Including GRST_RET_NO_SUCH_FILE if the private key or cert chain +/// were not found.) { int ret = GRST_RET_OK; char *docroot, *filename, *user_dn_enc; @@ -1818,13 +1797,11 @@ int GRSTx509ProxyDestroy(char *proxydir, char *delegation_id, char *user_dn) } /// Get start and finish validity times of stored GSI proxy file -/** - * Returns GRST_RET_OK on success, non-zero otherwise. - * (Including GRST_RET_NO_SUCH_FILE if the cert chain was not found.) - */ - int GRSTx509ProxyGetTimes(char *proxydir, char *delegation_id, char *user_dn, time_t *start, time_t *finish) +/// +/// Returns GRST_RET_OK on success, non-zero otherwise. +/// (Including GRST_RET_NO_SUCH_FILE if the cert chain was not found.) { char *docroot, *filename, *user_dn_enc; FILE *fp; @@ -1859,15 +1836,12 @@ int GRSTx509ProxyGetTimes(char *proxydir, char *delegation_id, char *user_dn, } /// Create a stack of X509 certificate from a PEM-encoded string -/** - * Creates a dynamically allocated stack of X509 certificate objects - * by walking through the PEM-encoded X509 certificates. - * - * Returns GRST_RET_OK on success, non-zero otherwise. - * - */ - int GRSTx509StringToChain(STACK_OF(X509) **certstack, char *certstring) +/// +/// Creates a dynamically allocated stack of X509 certificate objects +/// by walking through the PEM-encoded X509 certificates. +/// +/// Returns GRST_RET_OK on success, non-zero otherwise. { STACK_OF(X509_INFO) *sk=NULL; BIO *certbio; @@ -1912,12 +1886,10 @@ int GRSTx509StringToChain(STACK_OF(X509) **certstack, char *certstring) } /// Returns a Delegation ID based on hash of GRST_CRED_0, ... -/** - * Returns a malloc'd string with Delegation ID made by SHA1-hashing the - * values of the compact credentials exported by mod_gridsite - */ - char *GRSTx509MakeDelegationID(void) +/// +/// Returns a malloc'd string with Delegation ID made by SHA1-hashing the +/// values of the compact credentials exported by mod_gridsite { unsigned char hash_delegation_id[EVP_MAX_MD_SIZE]; int size_needed = 0, i, delegation_id_len; @@ -1954,17 +1926,15 @@ char *GRSTx509MakeDelegationID(void) #if 0 /// Return the short file name for the given delegation_id and user_dn -/** - * Returns a malloc'd string with the short file name (no paths) that - * derived from the hashed delegation_id and user_dn - * - * File name is SHA1_HASH(DelegationID)+"-"+SHA1_HASH(DN) where DN - * is DER encoded version of user_dn with any trailing CN=proxy removed - * Hashes are the most significant 8 bytes, in lowercase hexadecimal. - */ - char *GRSTx509MakeProxyFileName(char *delegation_id, STACK_OF(X509) *certstack) +/// +/// Returns a malloc'd string with the short file name (no paths) that +/// derived from the hashed delegation_id and user_dn +/// +/// File name is SHA1_HASH(DelegationID)+"-"+SHA1_HASH(DN) where DN +/// is DER encoded version of user_dn with any trailing CN=proxy removed +/// Hashes are the most significant 8 bytes, in lowercase hexadecimal. { int i, depth, prevIsCA = 1, IsCA, hash_name_len, delegation_id_len, der_name_len; @@ -2043,14 +2013,12 @@ char *GRSTx509MakeProxyFileName(char *delegation_id, #endif /// Store a GSI proxy chain in the proxy cache, along with the private key -/** - * Returns GRST_RET_OK on success, non-zero otherwise. The existing - * private key with the same delegation ID and user DN is moved out of - * the temporary cache. - */ - int GRSTx509CacheProxy(char *proxydir, char *delegation_id, char *user_dn, char *proxychain) +/// +/// Returns GRST_RET_OK on success, non-zero otherwise. The existing +/// private key with the same delegation ID and user DN is moved out of +/// the temporary cache. { int c, len = 0, i, ret; char *user_dn_enc, *p, *ptr, *prvkeyfile, *proxyfile; diff --git a/org.gridsite.core/src/grst_xacml.c b/org.gridsite.core/src/grst_xacml.c index c4c88ee..2ced7ff 100644 --- a/org.gridsite.core/src/grst_xacml.c +++ b/org.gridsite.core/src/grst_xacml.c @@ -101,7 +101,6 @@ static GRSTgaclCred *GRSTxacmlCredParse(xmlNodePtr cur) cred = GRSTgaclCredNew((char *) xmlNodeGetContent(attr_des->properties->children)); - cred->firstname = NULL; cred->next = NULL; //Assumed that there is only one name/value pair per credential @@ -405,20 +404,14 @@ int GRSTxacmlCredPrint(GRSTgaclCred *cred, FILE *fp) GRSTxacmlCredPrint - print a credential and any name-value pairs is contains in XACML form */ { - char *q; - GRSTgaclNamevalue *p; + char *q; - if (cred->firstname != NULL) + if (cred->auri != NULL) { - - p = cred->firstname; - - do { - fputs("\t\t\t\t\n", fp); fputs("\t\t\t\t\t\n", fp); fputs("\t\t\t\t\t\t", fp); - for (q=p->value; *q != '\0'; ++q) + for (q=cred->auri; *q != '\0'; ++q) if (*q == '<') fputs("<", fp); else if (*q == '>') fputs(">", fp); else if (*q == '&') fputs("&" , fp); @@ -431,14 +424,11 @@ int GRSTxacmlCredPrint(GRSTgaclCred *cred, FILE *fp) fputs("\t\t\t\t\t\ttype); + fprintf(fp, "\"cred\"\n"); fputs("\t\t\t\t\t\t\tDataType=", fp); - fprintf(fp, "\"%s\"/>\n", p->name); + fprintf(fp, "\"auri\"/>\n"); fputs("\t\t\t\t\t\n", fp); fputs("\t\t\t\t\n", fp); - p = (GRSTgaclNamevalue *) p->next; - } while (p != NULL); - } else fputs("\t\t\t\t\n", fp); diff --git a/org.gridsite.core/src/htproxyput.c b/org.gridsite.core/src/htproxyput.c index 688b509..1078953 100644 --- a/org.gridsite.core/src/htproxyput.c +++ b/org.gridsite.core/src/htproxyput.c @@ -591,7 +591,7 @@ int main(int argc, char *argv[]) (grst_cert->type == GRST_CERT_TYPE_VOMS) ? grst_cert->value : grst_cert->dn); - printf(" Status : %d ( %s%s%s%s%s%s)\n", grst_cert->errors, + printf(" Status : %d ( %s%s%s%s%s%s)\n", grst_cert->errors, (grst_cert->errors == 0) ? "OK " : "", (grst_cert->errors & GRST_CERT_BAD_FORMAT) ? "BAD_FORMAT ":"", (grst_cert->errors & GRST_CERT_BAD_CHAIN) ? "BAD_CHAIN ":"", @@ -599,18 +599,19 @@ int main(int argc, char *argv[]) (grst_cert->errors & GRST_CERT_BAD_TIME) ? "BAD_TIME ":"", (grst_cert->errors & GRST_CERT_BAD_OCSP) ? "BAD_OCSP ":""); - printf(" Start : %s", ctime(&(grst_cert->start))); - printf(" Finish : %s", ctime(&(grst_cert->finish))); + printf(" Start : %s", ctime(&(grst_cert->notbefore))); + printf(" Finish : %s", ctime(&(grst_cert->notafter))); + printf(" Delegation : %d\n", grst_cert->delegation); if (grst_cert->type == GRST_CERT_TYPE_VOMS) { - printf(" User DN : %s\n", grst_cert->dn); - printf(" VOMS DN : %s\n\n", grst_cert->issuer); + printf(" User DN : %s\n", grst_cert->dn); + printf(" VOMS DN : %s\n\n", grst_cert->issuer); } else { - printf(" Serial : %d\n", grst_cert->serial); - printf(" Issuer : %s\n\n", grst_cert->issuer); + printf(" Serial : %d\n", grst_cert->serial); + printf(" Issuer : %s\n\n", grst_cert->issuer); } } diff --git a/org.gridsite.core/src/mod_gridsite.c b/org.gridsite.core/src/mod_gridsite.c index 16febab..fcbb7d2 100644 --- a/org.gridsite.core/src/mod_gridsite.c +++ b/org.gridsite.core/src/mod_gridsite.c @@ -1,5 +1,5 @@ /* - Copyright (c) 2003-6, Andrew McNab, Shiv Kaushal, Joseph Dada, + Copyright (c) 2003-7, Andrew McNab, Shiv Kaushal, Joseph Dada, and Yibiao Li, University of Manchester. All rights reserved. Redistribution and use in source and binary forms, with or @@ -216,7 +216,7 @@ char *make_admin_footer(request_rec *r, mod_gridsite_dir_cfg *conf, */ { char *out, *https, *p, *dn = NULL, *file = NULL, *permstr = NULL, - *temp, modified[99], *dir_uri, *grst_cred_0 = NULL; + *temp, modified[99], *dir_uri, *grst_cred_auri_0 = NULL; GRSTgaclPerm perm = GRST_PERM_NONE; struct tm mtime_tm; time_t mtime_time; @@ -263,26 +263,16 @@ char *make_admin_footer(request_rec *r, mod_gridsite_dir_cfg *conf, out = apr_pstrcat(r->pool, out, "
", NULL); if (r->connection->notes != NULL) - grst_cred_0 = (char *) - apr_table_get(r->connection->notes, "GRST_CRED_0"); + { + grst_cred_auri_0 = (char *) + apr_table_get(r->connection->notes, "GRST_CRED_AURI_0"); + } - if ((grst_cred_0 != NULL) && - (strncmp(grst_cred_0, "X509USER ", sizeof("X509USER")) == 0)) + if ((grst_cred_auri_0 != NULL) && + (strncmp(grst_cred_auri_0, "dn:", 3) == 0)) { - p = index(grst_cred_0, ' '); - if (p != NULL) - { - p = index(++p, ' '); - if (p != NULL) - { - p = index(++p, ' '); - if (p != NULL) - { - p = index(++p, ' '); - if (p != NULL) dn = p; - } - } - } + dn = &grst_cred_auri_0[3]; + if (dn[0] == '\0') dn = NULL; } if (dn != NULL) @@ -779,13 +769,21 @@ int http_gridhttp(request_rec *r, mod_gridsite_dir_cfg *conf) for (i=0; ; ++i) { - envname_i = apr_psprintf(r->pool, "GRST_CRED_%d", i); + envname_i = apr_psprintf(r->pool, "GRST_CRED_AURI_%d", i); + if (grst_cred_i = (char *) + apr_table_get(r->connection->notes, envname_i)) + { + apr_file_printf(fp, "%s=%s\n", envname_i, grst_cred_i); + } + else break; /* GRST_CRED_AURI_i are numbered consecutively */ + + envname_i = apr_psprintf(r->pool, "GRST_CRED_VALID_%d", i); if (grst_cred_i = (char *) apr_table_get(r->connection->notes, envname_i)) { apr_file_printf(fp, "%s=%s\n", envname_i, grst_cred_i); } - else break; /* GRST_CRED_i are numbered consecutively */ + else break; /* GRST_CRED_VALID_i are numbered consecutively */ } if (apr_file_close(fp) != APR_SUCCESS) @@ -2161,16 +2159,27 @@ int GRST_load_ssl_creds(SSL *ssl, conn_rec *conn) while (apr_file_gets(line, sizeof(line), fp) == APR_SUCCESS) { - if (sscanf(line, "GRST_CRED_%d=", &i) == 1) + if (sscanf(line, "GRST_CRED_AURI_%d=", &i) == 1) { + if ((p = index(line, '\n')) != NULL) *p = '\0'; p = index(line, '='); apr_table_setn(conn->notes, - apr_psprintf(conn->pool, "GRST_CRED_%d", i), + apr_psprintf(conn->pool, "GRST_CRED_AURI_%d", i), + apr_pstrdup(conn->pool, &p[1])); + } + else if (sscanf(line, "GRST_CRED_VALID_%d=", &i) == 1) + { + if ((p = index(line, '\n')) != NULL) *p = '\0'; + p = index(line, '='); + + apr_table_setn(conn->notes, + apr_psprintf(conn->pool, "GRST_CRED_VALID_%d", i), apr_pstrdup(conn->pool, &p[1])); } else if (sscanf(line, "GRST_OCSP_URL_%d=", &i) == 1) { + if ((p = index(line, '\n')) != NULL) *p = '\0'; p = index(line, '='); apr_table_setn(conn->notes, @@ -2188,25 +2197,23 @@ int GRST_load_ssl_creds(SSL *ssl, conn_rec *conn) } /* - Save result of GRSTx509CompactCreds() into connection notes, and - write out in an SSL session creds file. + Save result of AURIs and validity info from chain into connection notes, + and write out in an SSL session creds file. */ -void GRST_save_ssl_creds(conn_rec *conn, - STACK_OF(X509) *certstack, X509 *peercert) +void GRST_save_ssl_creds(conn_rec *conn, GRSTx509Chain *grst_chain) { int i, lastcred; - const int maxcreds = 99; - const size_t credlen = 1024; - char creds[maxcreds][credlen+1], envname[14], *tempfile = NULL, + char envname[14], *tempfile = NULL, *sessionfile, session_id[(SSL_MAX_SSL_SESSION_ID_LENGTH+1)*2]; apr_file_t *fp = NULL; SSL *ssl; SSLConnRec *sslconn; + GRSTx509Cert *grst_cert = NULL; /* check if already done */ - if ((certstack != NULL) && (conn->notes != NULL) && + if ((grst_chain != NULL) && (conn->notes != NULL) && (apr_table_get(conn->notes, "GRST_save_ssl_creds") != NULL)) return; /* we at least need to say we've been run */ @@ -2234,27 +2241,67 @@ void GRST_save_ssl_creds(conn_rec *conn, APR_CREATE | APR_WRITE | APR_EXCL, conn->pool); } - if (GRSTx509CompactCreds(&lastcred, maxcreds, credlen, (char *) creds, - certstack, GRST_VOMS_DIR, peercert) == GRST_RET_OK) - { - for (i=0; i <= lastcred; ++i) + grst_cert = grst_chain->firstcert; + + for (i=0; grst_cert != NULL; grst_cert = grst_cert->next) + { + if (grst_cert->type == GRST_CERT_TYPE_VOMS) { apr_table_setn(conn->notes, - apr_psprintf(conn->pool, "GRST_CRED_%d", i), - apr_pstrdup(conn->pool, creds[i])); + apr_psprintf(conn->pool, "GRST_CRED_AURI_%d", i), + apr_pstrcat(conn->pool, "fqan:", grst_cert->value, NULL)); + + if (fp != NULL) apr_file_printf(fp, "GRST_CRED_AURI_%d=fqan:%s\n", + i, grst_cert->value); + + apr_table_setn(conn->notes, + apr_psprintf(conn->pool, "GRST_CRED_VALID_%d", i), + apr_psprintf(conn->pool, + "notbefore=%ld notafter=%ld delegation=%d nist-loa=%d", + grst_cert->notbefore, + grst_cert->notafter, 0, 0)); + + if (fp != NULL) apr_file_printf(fp, + "GRST_CRED_VALID_%d=notbefore=%ld notafter=%ld delegation=%d nist-loa=%d\n", + i, grst_cert->notbefore, + grst_cert->notafter, 0, 0); ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, conn->base_server, - "store GRST_CRED_%d=%s", i, creds[i]); + "store GRST_CRED_AURI_%d=fqan:%s", i, grst_cert->value); - if (fp != NULL) apr_file_printf(fp, "GRST_CRED_%d=%s\n", - i, creds[i]); + ++i; } - - /* free remaining dup'd certs? */ - } + else if ((grst_cert->type == GRST_CERT_TYPE_EEC) || + (grst_cert->type == GRST_CERT_TYPE_PROXY)) + { + apr_table_setn(conn->notes, + apr_psprintf(conn->pool, "GRST_CRED_AURI_%d", i), + apr_pstrcat(conn->pool, "dn:", grst_cert->dn, NULL)); - /* this needs to be merged into compactcreds in grst_x509? */ + if (fp != NULL) apr_file_printf(fp, "GRST_CRED_AURI_%d=dn:%s\n", + i, grst_cert->dn); + + apr_table_setn(conn->notes, + apr_psprintf(conn->pool, "GRST_CRED_VALID_%d", i), + apr_psprintf(conn->pool, + "notbefore=%ld notafter=%ld delegation=%d nist-loa=%d", + grst_cert->notbefore, + grst_cert->notafter, 0, 0)); + + if (fp != NULL) apr_file_printf(fp, + "GRST_CRED_VALID_%d=notbefore=%ld notafter=%ld delegation=%d nist-loa=%d\n", + i, grst_cert->notbefore, + grst_cert->notafter, 0, 0); + + ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, conn->base_server, + "store GRST_CRED_AURI_%d=dn:%s", i, grst_cert->dn); + ++i; + } + } + + /* this needs to be merged into grst_x509? */ +#if 0 if (ocspmodes != NULL) { int j; @@ -2292,7 +2339,7 @@ void GRST_save_ssl_creds(conn_rec *conn, } } } - +#endif /* end of bit that needs to go into grst_x509 */ if (fp != NULL) @@ -2383,14 +2430,15 @@ static int mod_gridsite_perm_handler(request_rec *r) We also publish environment variables here if requested by GridSiteEnv. */ { - int retcode = DECLINED, i, n, file_is_acl = 0, - destination_is_acl = 0, proxylevel, ishttps = 0; - char *dn, *p, envname[14], *grst_cred_0 = NULL, *dir_path, - *remotehost, s[99], *grst_cred_i, *cookies, *file, *https, + int retcode = DECLINED, i, n, file_is_acl = 0, cc_delegation, + destination_is_acl = 0, ishttps = 0, nist_loa, delegation; + char *dn, *p, envname1[30], envname2[30], + *grst_cred_auri_0 = NULL, *dir_path, + *remotehost, s[99], *grst_cred_auri_i, *cookies, *file, *https, *gridauthpasscode = NULL, *cookiefile, oneline[1025], *key_i, *destination = NULL, *destination_uri = NULL, *querytmp, *destination_prefix = NULL, *destination_translated = NULL, - *aclpath = NULL; + *aclpath = NULL, *grst_cred_valid_0 = NULL, *grst_cred_valid_i; char *vomsAttribute = NULL, *loa; const char *content_type; time_t now, notbefore, notafter; @@ -2448,15 +2496,12 @@ static int mod_gridsite_perm_handler(request_rec *r) if (dn != NULL) { - cred = GRSTgaclCredNew("person"); - GRSTgaclCredAddValue(cred, "dn", dn); - user = GRSTgaclUserNew(cred); - cred = GRSTgaclCredNew("level"); + cred = GRSTgaclCredCreate("dn:", dn); - if (loa != NULL) GRSTgaclCredAddValue(cred, "nist-loa", loa); - else GRSTgaclCredAddValue(cred, "nist-loa", "2"); + if (loa != NULL) GRSTgaclCredSetNistLoa(cred, atoi(loa)); + else GRSTgaclCredSetNistLoa(cred, 2); - GRSTgaclUserAddCred(user, cred); + user = GRSTgaclUserNew(cred); } /* Set up user credential based on VOMS Attribute from Shibboleth? */ @@ -2467,8 +2512,7 @@ static int mod_gridsite_perm_handler(request_rec *r) ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, "VOMS-Attribute: %s", vomsAttribute); - cred = GRSTgaclCredNew("voms"); - GRSTgaclCredAddValue(cred, "fqan", vomsAttribute); + cred = GRSTgaclCredCreate("fqan:", vomsAttribute); if (user == NULL) user = GRSTgaclUserNew(cred); else GRSTgaclUserAddCred(user, cred); } @@ -2492,67 +2536,152 @@ static int mod_gridsite_perm_handler(request_rec *r) "Restored SSL session data from session cache file"); } - proxylevel = ((mod_gridsite_dir_cfg *) cfg)->gsiproxylimit + 1; + delegation = ((mod_gridsite_dir_cfg *) cfg)->gsiproxylimit + 1; if ((user == NULL) && (r->connection->notes != NULL) && - ((grst_cred_0 = (char *) - apr_table_get(r->connection->notes, "GRST_CRED_0")) != NULL) && - (sscanf(grst_cred_0, "X509USER %*d %*d %d ", &proxylevel) == 1) && - (proxylevel <= ((mod_gridsite_dir_cfg *) cfg)->gsiproxylimit)) + ((grst_cred_auri_0 = (char *) + apr_table_get(r->connection->notes, "GRST_CRED_AURI_0")) != NULL) && + (strncmp(grst_cred_auri_0, "dn:", 3) == 0) && + ((grst_cred_valid_0 = (char *) + apr_table_get(r->connection->notes, "GRST_CRED_VALID_0")) != NULL) && + (sscanf(grst_cred_valid_0, + "notbefore=%ld notafter=%ld delegation=%d nist-loa=%d", + ¬before, ¬after, &delegation, &nist_loa) == 4) && + (delegation <= ((mod_gridsite_dir_cfg *) cfg)->gsiproxylimit)) { - apr_table_setn(env, "GRST_CRED_0", grst_cred_0); - - cred_0 = GRSTx509CompactToCred(grst_cred_0); + cred_0 = GRSTgaclCredCreate(grst_cred_auri_0, NULL); if (cred_0 != NULL) { ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, - "Using identity %s from SSL/TLS", grst_cred_0); + "Using identity %s from SSL/TLS", grst_cred_auri_0); + + GRSTgaclCredSetNotBefore( cred_0, notbefore); + GRSTgaclCredSetNotAfter( cred_0, notafter); + GRSTgaclCredSetDelegation(cred_0, delegation); + + if (delegation == 0) GRSTgaclCredSetNistLoa(cred_0, 3); + else GRSTgaclCredSetNistLoa(cred_0, 2); user = GRSTgaclUserNew(cred_0); - /* check for VOMS GRST_CRED_i too */ + /* check for VOMS etc in GRST_CRED_AURI_i too */ for (i=1; ; ++i) { - snprintf(envname, sizeof(envname), "GRST_CRED_%d", i); - if (grst_cred_i = (char *) - apr_table_get(r->connection->notes,envname)) + snprintf(envname1, sizeof(envname1), "GRST_CRED_AURI_%d", i); + snprintf(envname2, sizeof(envname2), "GRST_CRED_VALID_%d", i); + + if ((grst_cred_auri_i = (char *) + apr_table_get(r->connection->notes,envname1)) && + (grst_cred_valid_i = (char *) + apr_table_get(r->connection->notes,envname2))) { - if (((mod_gridsite_dir_cfg *) cfg)->envs) - apr_table_setn(env, - apr_pstrdup(r->pool, envname), - grst_cred_i); - - if (cred = GRSTx509CompactToCred(grst_cred_i)) - GRSTgaclUserAddCred(user, cred); + cred = GRSTgaclCredCreate(grst_cred_auri_i, NULL); + if (cred != NULL) + { + notbefore = 0; + notafter = 0; + delegation = 0; + nist_loa = 0; + + sscanf(grst_cred_valid_i, + "notbefore=%ld notafter=%ld delegation=%d nist-loa=%d", + ¬before, ¬after, &delegation, &nist_loa); + + GRSTgaclCredSetNotBefore( cred, notbefore); + GRSTgaclCredSetNotAfter( cred, notafter); + GRSTgaclCredSetDelegation(cred, delegation); + GRSTgaclCredSetDelegation(cred, nist_loa); + + GRSTgaclUserAddCred(user, cred); + } } - else break; /* GRST_CRED_i are numbered consecutively */ + else break; /* GRST_CRED_AURI_i are numbered consecutively */ } - - cred = GRSTgaclCredNew("level"); - if (proxylevel == 0) GRSTgaclCredAddValue(cred, "nist-loa", "3"); - else GRSTgaclCredAddValue(cred, "nist-loa", "2"); - GRSTgaclUserAddCred(user, cred); } } if ((user != NULL) && ((mod_gridsite_dir_cfg *) cfg)->dnlists) - GRSTgaclUserSetDNlists(user, ((mod_gridsite_dir_cfg *) cfg)->dnlists); + GRSTgaclUserLoadDNlists(user, ((mod_gridsite_dir_cfg *) cfg)->dnlists); /* add DNS credential */ remotehost = (char *) ap_get_remote_host(r->connection, r->per_dir_config, REMOTE_DOUBLE_REV, NULL); if ((remotehost != NULL) && (*remotehost != '\0')) - { - cred = GRSTgaclCredNew("dns"); - GRSTgaclCredAddValue(cred, "hostname", remotehost); + { + cred = GRSTgaclCredCreate("dns:", remotehost); + + if (user == NULL) user = GRSTgaclUserNew(cred); + else GRSTgaclUserAddCred(user, cred); + } + + /* add IP credential */ + + remotehost = (char *) ap_get_remote_host(r->connection, + r->per_dir_config, REMOTE_DOUBLE_REV, NULL); + if ((remotehost != NULL) && (*remotehost != '\0')) + { + cred = GRSTgaclCredCreate("ip:", r->connection->remote_ip); if (user == NULL) user = GRSTgaclUserNew(cred); else GRSTgaclUserAddCred(user, cred); } + /* write contents of user to per-request environment variables */ + + if (((mod_gridsite_dir_cfg *) cfg)->envs && (user != NULL)) + { + cred = user->firstcred; + + /* old-style Compact Credentials have the same delegation level + for all credentials. eg Using EEC delegation=0; using 1st GSI + Proxy then delegation=1 for X509USER _and_ GSIPROXY credentials. + So we remember the delegation level of any X509USER here */ + if (cred != NULL) cc_delegation = cred->delegation; + + for (i=0; (cred != NULL) && (cred->auri != NULL); ++i) + { + if (strncmp(cred->auri, "dn:", 3) == 0) + { + apr_table_setn(env, + apr_psprintf(r->pool, "GRST_CRED_%d", i), + apr_psprintf(r->pool, + "%s %ld %ld %d %s", + (i=0) ? "X509USER" : "GSIPROXY", + cred->notbefore, + cred->notafter, + cc_delegation, + &(cred->auri[3]))); + } + else if (strncmp(cred->auri, "fqan:", 5) == 0) + { + apr_table_setn(env, + apr_psprintf(r->pool, "GRST_CRED_%d", i), + apr_psprintf(r->pool, + "VOMS %ld %ld 0 %s", + notbefore, notafter, + &(cred->auri[5]))); + } + + apr_table_setn(env, + apr_psprintf(r->pool, "GRST_CRED_AURI_%d", i), + apr_pstrdup(r->pool, cred->auri)); + + apr_table_setn(env, + apr_psprintf(r->pool, "GRST_CRED_VALID_%d", i), + apr_psprintf(r->pool, + "notbefore=%ld notafter=%ld delegation=%d nist-loa=%d", + cred->notbefore, + cred->notafter, + cred->delegation, + cred->nist_loa)); + + cred = cred->next; + } + } + /* check for Destination: header and evaluate if present */ if ((destination = (char *) apr_table_get(r->headers_in, @@ -2601,13 +2730,26 @@ static int mod_gridsite_perm_handler(request_rec *r) } } - /* this checks for NULL arguments itself */ - if (GRSTgaclDNlistHasUser(((mod_gridsite_dir_cfg *) cfg)->adminlist, user)) - { - perm = GRST_PERM_ALL; - if (destination_translated != NULL) destination_perm = GRST_PERM_ALL; + if ((((mod_gridsite_dir_cfg *) cfg)->adminlist != NULL) && (user != NULL)) + { + cred = user->firstcred; + + while ((cred != NULL) && (cred->auri != NULL)) + { + if (strcmp(((mod_gridsite_dir_cfg *) cfg)->adminlist, + cred->auri) == 0) + { + perm = GRST_PERM_ALL; + if (destination_translated != NULL) + destination_perm = GRST_PERM_ALL; + break; + } + + cred = cred->next; + } } - else + + if (perm != GRST_PERM_ALL) /* cannot improve on perfection... */ { if (((mod_gridsite_dir_cfg *) cfg)->aclpath != NULL) { @@ -2965,11 +3107,12 @@ int GRST_callback_SSLVerify_wrapper(int ok, X509_STORE_CTX *ctx) int returned_ok; int first_non_ca; STACK_OF(X509) *certstack; + GRSTx509Chain *grst_chain; /* * GSI Proxy user-cert-as-CA handling: * we skip Invalid CA errors at this stage, since we will check this - * again at errdepth=0 for the full chain using GRSTx509CheckChain + * again at errdepth=0 for the full chain using GRSTx509ChainLoadCheck */ if (errnum == X509_V_ERR_INVALID_CA) { @@ -3017,7 +3160,11 @@ int GRST_callback_SSLVerify_wrapper(int ok, X509_STORE_CTX *ctx) * CAs or, failing that, GSI-proxy validity using GRSTx509CheckChain. */ { - errnum = GRSTx509CheckChain(&first_non_ca, ctx); + certstack = (STACK_OF(X509) *) X509_STORE_CTX_get_chain(ctx); + + errnum = GRSTx509ChainLoadCheck(&grst_chain, certstack, NULL, + "/etc/grid-security/certificates", + "/etc/grid-security/vomsdir"); if (errnum != X509_V_OK) { @@ -3031,13 +3178,13 @@ int GRST_callback_SSLVerify_wrapper(int ok, X509_STORE_CTX *ctx) else { ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, "Valid certificate" - " chain reported by GRSTx509CheckChain()"); + " chain reported by GRSTx509ChainLoadCheck()"); - /* Put result of GRSTx509CompactCreds() into connection notes */ - if ((certstack = - (STACK_OF(X509) *) X509_STORE_CTX_get_chain(ctx)) != NULL) - GRST_save_ssl_creds(conn, certstack, NULL); + /* Put result of GRSTx509ChainLoadCheck into connection notes */ + GRST_save_ssl_creds(conn, grst_chain); } + + GRSTx509ChainFree(grst_chain); } return returned_ok; @@ -3451,6 +3598,23 @@ static int mod_gridsite_server_post_config(apr_pool_t *pPool, return OK; } + +static server_rec *mod_gridsite_log_func_server; +static void mod_gridsite_log_func(char *file, int line, int level, + char *fmt, ...) +{ + char *mesg; + va_list ap; + + va_start(ap, fmt); + vasprintf(&mesg, fmt, ap); + va_end(ap); + + ap_log_error(file, line, level, + 0, mod_gridsite_log_func_server, "%s", mesg); + + free(mesg); +} static void mod_gridsite_child_init(apr_pool_t *pPool, server_rec *pServer) { @@ -3461,6 +3625,8 @@ static void mod_gridsite_child_init(apr_pool_t *pPool, server_rec *pServer) SSLSrvConfigRec *sc = ap_get_module_config(pServer->module_config, &ssl_module); GRSTgaclInit(); + mod_gridsite_log_func_server = pServer; + GRSTerrorLogFunc = mod_gridsite_log_func; /* expire old ssl creds files */ @@ -3552,7 +3718,7 @@ static void register_hooks(apr_pool_t *p) ap_hook_fixups(mod_gridsite_first_fixups,NULL,NULL,APR_HOOK_FIRST); - ap_hook_fixups(mod_gridsite_perm_handler,NULL,NULL,APR_HOOK_REALLY_LAST); + ap_hook_fixups(mod_gridsite_perm_handler,NULL,NULL,APR_HOOK_LAST); ap_hook_handler(mod_gridsite_handler, NULL, NULL, APR_HOOK_FIRST); -- 1.8.2.3