grst_gacl.c

Go to the documentation of this file.
00001 /*
00002    Copyright (c) 2002-6, Andrew McNab, University of Manchester
00003    All rights reserved.
00004 
00005    Redistribution and use in source and binary forms, with or
00006    without modification, are permitted provided that the following
00007    conditions are met:
00008 
00009      o Redistributions of source code must retain the above
00010        copyright notice, this list of conditions and the following
00011        disclaimer. 
00012      o Redistributions in binary form must reproduce the above
00013        copyright notice, this list of conditions and the following
00014        disclaimer in the documentation and/or other materials
00015        provided with the distribution. 
00016 
00017    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
00018    CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
00019    INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
00020    MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
00021    DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
00022    BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
00023    EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
00024    TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
00025    DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
00026    ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
00027    OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
00028    OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00029    POSSIBILITY OF SUCH DAMAGE.
00030 */
00031 /*---------------------------------------------------------------*
00032  * For more information about GridSite: http://www.gridsite.org/ *
00033  *---------------------------------------------------------------*/
00034 
00035 
00036 #include <sys/types.h>
00037 #include <sys/stat.h>
00038 #include <sys/mman.h>
00039 #include <unistd.h>              
00040 #include <string.h>
00041 #include <dirent.h>
00042 #include <fcntl.h>
00043 #include <ctype.h>
00044 #include <strings.h>
00045 
00046 #ifndef _GNU_SOURCE
00047 #define _GNU_SOURCE
00048 #include <stdio.h>
00049 #include <stdlib.h>
00050 #endif
00051 #include <fnmatch.h>
00052 
00053 #include <libxml/xmlmemory.h>
00054 #include <libxml/tree.h>
00055 #include <libxml/parser.h>
00056 
00057 #include "gridsite.h"
00058 
00059 #ifdef SUNCC
00060 /* SUN does not know strsep .... */
00061 
00062 static char* strsep(char** str, const char* delims)
00063 {
00064   char* token;
00065   if (*str==NULL) {
00066     /* No more tokens */
00067     return NULL;
00068   }
00069   
00070   token=*str;
00071   while (**str!='\0') {
00072     if (strchr(delims,**str)!=NULL) {
00073       **str='\0';
00074       (*str)++;
00075       return token;
00076     }
00077     (*str)++;
00078   }
00079   /* There is no other token */
00080   *str=NULL;
00081   return token;
00082 }
00083 
00084 #endif
00085 
00086 /*                                                                      *
00087  * Global variables, shared by all GACL functions but private to libgacl *
00088  *                                                                      */
00089  
00090 char     *grst_perm_syms[] =  { "none",
00091                                 "read",
00092                                 "exec",
00093                                 "list",
00094                                 "write",
00095                                 "admin",
00096                                 NULL              };
00097 
00098 GRSTgaclPerm grst_perm_vals[] =  {   GRST_PERM_NONE,
00099                                      GRST_PERM_READ,
00100                                      GRST_PERM_EXEC,
00101                                      GRST_PERM_LIST,
00102                                      GRST_PERM_WRITE,
00103                                      GRST_PERM_ADMIN,
00104                                      -1                };
00105 
00106 int GRSTgaclInit(void)
00107 {
00108   xmlInitParser();
00109 
00110   LIBXML_TEST_VERSION
00111 
00112   xmlKeepBlanksDefault(0);
00113 
00114   return 1;
00115 }                             
00116 
00117 /* declare these two private functions at the start */
00118 
00119 GRSTgaclAcl *GRSTgaclAclParse(xmlDocPtr, xmlNodePtr, GRSTgaclAcl *);
00120 GRSTgaclAcl *GRSTxacmlAclParse(xmlDocPtr, xmlNodePtr, GRSTgaclAcl *);
00121 
00122 /*                                             *
00123  * Functions to manipulate GRSTgaclCred structures *
00124  *                                             */
00125 
00126 GRSTgaclCred *GRSTgaclCredCreate(char *auri_prefix, char *auri_suffix)
00127 /*
00128     GRSTgaclCredCreate - allocate a new GRSTgaclCred structure, and return
00129                          it's pointer or NULL on (malloc) error.
00130 */
00131 {
00132   int           i;
00133   char          auri[16384];
00134   GRSTgaclCred *newcred; 
00135 
00136   if      ((auri_prefix != NULL) && (auri_suffix == NULL))
00137    sprintf(auri,"%s",auri_prefix);
00138   else if ((auri_prefix == NULL) && (auri_suffix != NULL))
00139    sprintf(auri,"%s",auri_suffix);
00140   else if ((auri_prefix != NULL) && (auri_suffix != NULL))
00141    sprintf(auri, "%s%s", auri_prefix, auri_suffix);
00142   else return NULL;
00143 
00144   for (i=0; (auri[i] != '\0') && isspace(auri[i]); ++i) ; /* leading space */
00145 
00146   for (i=strlen(auri) - 1; (i >= 0) && isspace(auri[i]); --i)
00147                                            auri[i]='\0'; /* trailing space */
00148 
00149   newcred = malloc(sizeof(GRSTgaclCred));
00150   if (newcred == NULL) 
00151     {
00152       return NULL;
00153     }
00154   
00155   newcred->auri       = auri;
00156   newcred->delegation = 0;
00157   newcred->nist_loa   = 0;
00158   newcred->notbefore  = 0;
00159   newcred->notafter   = 0;
00160   newcred->next       = NULL;
00161 
00162   return newcred;
00163 }
00164 
00165 GRSTgaclCred *GRSTgaclCredNew(char *type)
00166 /*
00167     GRSTgaclCredNew - allocate a new GRSTgaclCred structure, and return
00168                       it's pointer or NULL on (malloc) error.
00169 */
00170 {
00171   if (type == NULL) return NULL;
00172   
00173   if ((strcmp(type, "person" ) == 0) ||
00174       (strcmp(type, "voms"   ) == 0) ||
00175       (strcmp(type, "dn-list") == 0) ||
00176       (strcmp(type, "dns"    ) == 0) ||
00177       (strcmp(type, "level"  ) == 0)) return GRSTgaclCredCreate("", NULL);
00178       
00179   if (strcmp(type, "any-user") == 0) 
00180        return GRSTgaclCredCreate("gacl:", "any-user");
00181                                   
00182   if (strcmp(type, "auth-user") == 0) 
00183        return GRSTgaclCredCreate("gacl:", "auth-user");
00184 
00185   return NULL;
00186 }
00187 
00188 int GRSTgaclCredAddValue(GRSTgaclCred *cred, char *name, char *rawvalue)
00189 /*
00190     GRSTgaclCredAddValue - add a name/value pair to a GRSTgaclCred
00191 */
00192 {
00193   int                i;
00194   char              *value, *encoded_value;
00195 
00196   if ((cred == NULL) || (cred->auri == NULL)) return 0;
00197   free(cred->auri);
00198   cred->auri = NULL;
00199 
00200   /* no leading or trailing space in value */
00201 
00202   value = rawvalue; 
00203   while ((*value != '\0') && isspace(*value)) ++value;
00204 
00205   value = strdup(value);
00206   for (i=strlen(value) - 1; (i >= 0) && isspace(value[i]); --i) value[i]='\0';
00207 
00208   encoded_value = GRSThttpUrlMildencode(value);
00209 
00210   if (strcmp(name, "dn") == 0)
00211     {
00212       sprintf(cred->auri, "dn:%s", encoded_value);
00213       free(value);
00214       free(encoded_value);
00215       return 1;
00216     }
00217   else if (strcmp(name, "fqan") == 0)
00218     {
00219       sprintf(cred->auri, "fqan:%s", encoded_value);
00220       free(value);
00221       free(encoded_value);
00222       return 1;
00223     }
00224   else if (strcmp(name, "url") == 0)
00225     {
00226       sprintf(cred->auri, "%s", encoded_value);
00227       free(value);
00228       free(encoded_value);
00229       return 1;
00230     }
00231   else if (strcmp(name, "hostname") == 0)
00232     {
00233       sprintf(cred->auri, "dns:%s", encoded_value);
00234       free(value);
00235       free(encoded_value);
00236       return 1;
00237     }
00238   else if (strcmp(name, "nist-loa") == 0)
00239     {
00240       sprintf(cred->auri, "nist-loa:%s", encoded_value);
00241       free(value);
00242       free(encoded_value);
00243       return 1;
00244     }
00245     
00246   free(value);  
00247   free(encoded_value);
00248   return 0;
00249 }
00250 
00251 int GRSTgaclCredFree(GRSTgaclCred *cred)
00252 /*
00253     GRSTgaclCredFree - free memory structures of a GRSTgaclCred, 
00254     returning 1 always!
00255 */
00256 {
00257   if (cred == NULL) return 1;
00258 
00259   if (cred->auri != NULL) free(cred->auri);
00260   free(cred);
00261   
00262   return 1;
00263 }
00264 
00265 static int GRSTgaclCredsFree(GRSTgaclCred *firstcred)
00266 /*
00267     GRSTgaclCredsFree - free a cred and all the creds in its *next chain
00268 */
00269 {
00270   if (firstcred == NULL) return 0;
00271   
00272   if (firstcred->next != NULL) GRSTgaclCredsFree(firstcred->next);
00273   
00274   return GRSTgaclCredFree(firstcred);
00275 }
00276 
00277 static int GRSTgaclCredInsert(GRSTgaclCred *firstcred, GRSTgaclCred *newcred)
00278 /* 
00279     GRSTgaclCredInsert - insert a cred in the *next chain of firstcred
00280 
00281     FOR THE MOMENT THIS JUST APPENDS!
00282 */
00283 {
00284   if (firstcred == NULL) return 0;
00285   
00286   if (firstcred->next == NULL)
00287     {
00288       firstcred->next = newcred;
00289       return 1;
00290     }
00291 
00292   return GRSTgaclCredInsert(firstcred->next, newcred);     
00293 }
00294 
00295 int GRSTgaclEntryAddCred(GRSTgaclEntry *entry, GRSTgaclCred *cred)
00296 /*  
00297     GRSTaddCred - add a new credential to an existing entry, returning 1
00298     on success or 0 on error 
00299 */ 
00300 {
00301   if (entry == NULL) return 0;
00302  
00303   if (entry->firstcred == NULL) 
00304     {
00305       entry->firstcred = cred;
00306       return 1;
00307     }
00308   else return GRSTgaclCredInsert(entry->firstcred, cred);
00309 }
00310 
00311 static int GRSTgaclCredRemoveCred(GRSTgaclCred *firstcred, GRSTgaclCred *oldcred)
00312 /* 
00313     (Private)
00314 
00315     GRSTgaclCredRemoveCred - remove a cred in the *next chain of firstcred
00316                      and relink the chain
00317 */
00318 {
00319   if (firstcred == NULL) return 0;
00320 
00321   return 1;
00322 }
00323 
00324 int GRSTgaclEntryDelCred(GRSTgaclEntry *entry, GRSTgaclCred *cred)
00325 /*  
00326     GRSTgaclEntryDelCred - remove a new cred from an entry, returning 1
00327     on success (or absense) or 0 on error.
00328 */ 
00329 {
00330   if (entry == NULL) return 0;
00331 
00332   return GRSTgaclCredRemoveCred(entry->firstcred, cred);
00333 }
00334 
00335 int GRSTgaclCredPrint(GRSTgaclCred *cred, FILE *fp)
00336 /* 
00337    GRSTgaclCredPrint - print a credential and the AURI value it contains
00338 */
00339 {
00340   char *q;
00341 
00342   if ((cred->auri != NULL) && (cred->auri[0] != '\0'))
00343     {
00344       fprintf(fp, "<cred>\n<auri>");
00345 
00346       for (q=cred->auri; *q != '\0'; ++q)
00347               if      (*q == '<')  fputs("&lt;",   fp);
00348               else if (*q == '>')  fputs("&gt;",   fp);
00349               else if (*q == '&')  fputs("&amp;" , fp);
00350               else if (*q == '\'') fputs("&apos;", fp);
00351               else if (*q == '"')  fputs("&quot;", fp);
00352               else                 fputc(*q, fp);
00353 
00354       fprintf(fp, "</auri>\n");
00355       
00356       if (cred->nist_loa > 0) 
00357             fprintf(fp, "<nist-loa>%d</nist-loa>\n", cred->nist_loa);
00358       
00359       if (cred->delegation > 0) 
00360             fprintf(fp, "<delegation>%d</delegation>\n", cred->delegation);
00361       
00362       fprintf(fp, "</cred>\n");
00363 
00364       return 1;
00365     }
00366     
00367   return 0;
00368 }
00369 
00370 int GRSTgaclCredCmpAuri(GRSTgaclCred *cred1, GRSTgaclCred *cred2)
00371 /*
00372     GRSTgaclCredCmp - compare two credentials for exact match in AURI values
00373                       (this means a string match, not just any-user=DN etc)
00374 */
00375 {
00376   if ((cred1 == NULL) && (cred2 == NULL)) return 0;
00377   
00378   if (cred1 == NULL) return -1;
00379 
00380   if (cred2 == NULL) return 1;
00381   
00382   if ((cred1->auri == NULL) && (cred2->auri == NULL)) return 0;
00383   
00384   if (cred1->auri == NULL) return -1;
00385 
00386   if (cred2->auri == NULL) return 1;
00387   
00388   return strcmp(cred1->auri, cred2->auri);
00389 }
00390 
00391 /*                                              *
00392  * Functions to manipulate GRSTgaclEntry structures *
00393  *                                              */
00394 
00395 GRSTgaclEntry *GRSTgaclEntryNew(void)
00396 /*
00397     GRSTgaclEntryNew - allocate space for a new entry, returning its pointer
00398                    or NULL on failure.
00399 */
00400 {
00401   GRSTgaclEntry *newentry;
00402   
00403   newentry = (GRSTgaclEntry *) malloc(sizeof(GRSTgaclEntry));
00404   if (newentry == NULL) return NULL;
00405 
00406   newentry->firstcred    = NULL;
00407   newentry->allowed      = 0;
00408   newentry->denied       = 0;
00409   newentry->next         = NULL;
00410 
00411   return newentry;
00412 }
00413 
00414 int GRSTgaclEntryFree(GRSTgaclEntry *entry)
00415 /* 
00416     GRSTgaclEntryFree - free up space used by an entry (always returns 1)
00417 */
00418 {
00419   if (entry == NULL) return 1;
00420 
00421   GRSTgaclCredsFree(entry->firstcred);  
00422 
00423   free(entry);
00424   
00425   return 1;
00426 }
00427 
00428 static int GRSTgaclEntriesFree(GRSTgaclEntry *entry)
00429 /*
00430     GRSTgaclEntriesFree - free up entry and all entries linked to in its *next 
00431                       chain
00432 */
00433 {
00434   if (entry == NULL) return 0;
00435   
00436   if (entry->next != NULL) GRSTgaclEntriesFree(entry->next);
00437   
00438   return GRSTgaclEntryFree(entry);  
00439 }
00440 
00441 static int GRSTgaclEntryInsert(GRSTgaclEntry *firstentry, GRSTgaclEntry *newentry)
00442 /* 
00443     GRSTgaclEntryInsert - insert an entry in the *next chain of firstentry
00444 
00445     FOR THE MOMENT THIS JUST APPENDS
00446 */
00447 {
00448   if (firstentry == NULL) return 0;
00449   
00450   if (firstentry->next == NULL)
00451     {
00452       firstentry->next = newentry;
00453       return 1;
00454     }
00455 
00456   return GRSTgaclEntryInsert(firstentry->next, newentry);     
00457 }
00458 
00459 int GRSTgaclAclAddEntry(GRSTgaclAcl *acl, GRSTgaclEntry *entry)
00460 /*  
00461     GRSTgaclAclAddEntry - add a new entry to an existing acl, returning 1
00462     on success or 0 on error 
00463 */ 
00464 {
00465   if (acl == NULL) return 0;
00466 
00467   if (acl->firstentry == NULL) 
00468     { 
00469       acl->firstentry = entry;
00470       return 1;
00471     }
00472   else return GRSTgaclEntryInsert(acl->firstentry, entry);
00473 }
00474 
00475 int GRSTgaclEntryPrint(GRSTgaclEntry *entry, FILE *fp)
00476 {
00477   GRSTgaclCred  *cred;
00478   GRSTgaclPerm  i;
00479 
00480   fputs("<entry>\n", fp);
00481   
00482   for (cred = entry->firstcred; cred != NULL; cred = cred->next)
00483                                             GRSTgaclCredPrint(cred, fp);
00484 
00485   if (entry->allowed)
00486     {
00487       fputs("<allow>", fp);
00488 
00489       for (i=GRST_PERM_READ; i <= GRST_PERM_ADMIN; ++i)
00490        if ((entry->allowed) & i) GRSTgaclPermPrint(i, fp);
00491 
00492       fputs("</allow>\n", fp);
00493     }
00494     
00495 
00496   if (entry->denied)
00497     {
00498       fputs("<deny>", fp);
00499 
00500       for (i=GRST_PERM_READ; i <= GRST_PERM_ADMIN; ++i)
00501        if (entry->denied & i) GRSTgaclPermPrint(i, fp);
00502 
00503       fputs("</deny>\n", fp);
00504     }
00505     
00506   fputs("</entry>\n", fp);
00507 
00508   return 1;
00509 }
00510 
00511 /*                                         *
00512  * Functions to manipulate GRSTgaclPerm items *
00513  *                                         */
00514 
00515 int GRSTgaclPermPrint(GRSTgaclPerm perm, FILE *fp)
00516 {
00517   GRSTgaclPerm i;
00518   
00519   for (i=GRST_PERM_READ; grst_perm_syms[i] != NULL; ++i)
00520        if (perm == grst_perm_vals[i]) 
00521          {
00522            fprintf(fp, "<%s/>", grst_perm_syms[i]);
00523            return 1;
00524          }
00525          
00526   return 0;
00527 }
00528 
00529 int GRSTgaclEntryAllowPerm(GRSTgaclEntry *entry, GRSTgaclPerm perm)
00530 {
00531   entry->allowed = entry->allowed | perm;
00532 
00533   return 1;
00534 }
00535 
00536 int GRSTgaclEntryUnallowPerm(GRSTgaclEntry *entry, GRSTgaclPerm perm)
00537 {
00538   entry->allowed = entry->allowed & ~perm;
00539 
00540   return 1;
00541 }
00542 
00543 int GRSTgaclEntryDenyPerm(GRSTgaclEntry *entry, GRSTgaclPerm perm)
00544 {
00545   entry->denied = entry->denied | perm;
00546 
00547   return 1;
00548 }
00549 
00550 int GRSTgaclEntryUndenyPerm(GRSTgaclEntry *entry, GRSTgaclPerm perm)
00551 {
00552   entry->denied = entry->denied & ~perm;
00553 
00554   return 1;
00555 }
00556 
00557 char *GRSTgaclPermToChar(GRSTgaclPerm perm)
00558 /*
00559    GRSTgaclPermToChar - return char * or NULL corresponding to most significant
00560                      set bit of perm.
00561 */
00562 {
00563   char      *p = NULL;
00564   GRSTgaclPerm  i;
00565   
00566   for (i=0; grst_perm_syms[i] != NULL; ++i)
00567        if (perm & grst_perm_vals[i]) p = grst_perm_syms[i];
00568 
00569   return p;
00570 }
00571 
00572 GRSTgaclPerm GRSTgaclPermFromChar(char *s)
00573 /*
00574    GRSTgaclPermToChar - return access perm corresponding to symbol s[]
00575 */
00576 {
00577   GRSTgaclPerm i;
00578 
00579   for (i=0; grst_perm_syms[i] != NULL; ++i)
00580        if (strcasecmp(grst_perm_syms[i], s) == 0) return grst_perm_vals[i];
00581 
00582   return -1; 
00583 }
00584 
00585 /*                                            *
00586  * Functions to manipulate GRSTgaclAcl structures *
00587  *                                            */
00588 
00589 GRSTgaclAcl *GRSTgaclAclNew(void)
00590 /*  
00591     GRSTgaclAclNew - allocate a new acl and return its pointer (or NULL 
00592                  on failure.)
00593 */
00594 {
00595   GRSTgaclAcl *newacl;
00596   
00597   newacl = (GRSTgaclAcl *) malloc(sizeof(GRSTgaclAcl));
00598   if (newacl == NULL) return NULL;
00599   
00600   newacl->firstentry = NULL;
00601 
00602   return newacl;
00603 }
00604 
00605 int GRSTgaclAclFree(GRSTgaclAcl *acl)
00606 /*
00607     GRSTgaclAclFree - free up space used by *acl. Always returns 1.
00608 */
00609 {
00610   if (acl == NULL) return 1;
00611 
00612   GRSTgaclEntriesFree(acl->firstentry);  
00613 
00614   return 1;
00615 }
00616 
00617 int GRSTgaclAclPrint(GRSTgaclAcl *acl, FILE *fp)
00618 {
00619   GRSTgaclEntry *entry;
00620   
00621   fputs("<gacl version=\"0.9.0\">\n", fp);
00622   
00623   for (entry = acl->firstentry; entry != NULL; entry = entry->next)
00624                                             GRSTgaclEntryPrint(entry, fp);
00625 
00626   fputs("</gacl>\n", fp);
00627 
00628   return 1;
00629 }
00630 
00631 int GRSTgaclAclSave(GRSTgaclAcl *acl, char *filename)
00632 {
00633   int   ret;
00634   FILE *fp;
00635   
00636   fp = fopen(filename, "w");
00637   if (fp == NULL) return 0;
00638   
00639   fputs("<?xml version=\"1.0\"?>\n", fp);
00640   
00641   ret = GRSTgaclAclPrint(acl, fp);
00642   
00643   fclose(fp);
00644   
00645   return ret;
00646 }
00647 
00648 /*                                                    *
00649  * Functions for loading and parsing XML using libxml *
00650  *                                                    */
00651  
00652 // need to check these for libxml memory leaks? - what needs to be freed?
00653 
00654 static GRSTgaclCred *GRSTgaclCredParse(xmlNodePtr cur)
00655 /*
00656     GRSTgaclCredParse - parse a credential stored in the libxml structure cur, 
00657                     returning it as a pointer or NULL on error.
00658 */
00659 {
00660   xmlNodePtr    cur2;
00661   GRSTgaclCred *cred = NULL;
00662  
00663   /* generic AURI creds first */
00664 
00665   if (strcmp((char *) cur->name, "cred") == 0)
00666     {
00667       for (cur2 = cur->xmlChildrenNode; cur2 != NULL; cur2=cur2->next)
00668          {
00669            if (!xmlIsBlankNode(cur2) &&
00670                (strcmp((char *) cur2->name, "auri") == 0))               
00671              {
00672                if (cred != NULL) /* multiple AURI */
00673                  {
00674                    GRSTgaclCredFree(cred);
00675                    cred = NULL;
00676                    return NULL;
00677                  }
00678 
00679                cred = GRSTgaclCredCreate((char *) xmlNodeGetContent(cur2),NULL);
00680              }
00681          }
00682          
00683       if (cred == NULL) return NULL;
00684       
00685       for (cur2 = cur->xmlChildrenNode; cur2 != NULL; cur2=cur2->next)
00686          {
00687            if (xmlIsBlankNode(cur2)) continue;
00688            
00689            if (strcmp((char *) cur2->name, "nist-loa") == 0)
00690              {
00691                cred->nist_loa = atoi((char *) xmlNodeGetContent(cur2));
00692              }
00693            else if (strcmp((char *) cur2->name, "delegation") == 0)
00694              {
00695                cred->delegation = atoi((char *) xmlNodeGetContent(cur2));
00696              }
00697          }
00698     
00699       return cred;
00700     }
00701   
00702   /* backwards compatibility */
00703 
00704   cred = GRSTgaclCredNew((char *) cur->name);
00705   
00706   for (cur2 = cur->xmlChildrenNode; cur2 != NULL; cur2=cur2->next)
00707      {
00708        if (!xmlIsBlankNode(cur2))
00709         GRSTgaclCredAddValue(cred, (char *) cur2->name, 
00710                              (char *) xmlNodeGetContent(cur2));
00711      }
00712 
00713   return cred;
00714 }
00715 
00716 static GRSTgaclEntry *GRSTgaclEntryParse(xmlNodePtr cur)
00717 /*
00718     GRSTgaclEntryParse - parse an entry stored in the libxml structure cur,
00719                      returning it as a pointer or NULL on error.
00720 */
00721 {
00722   int        i;
00723   xmlNodePtr cur2;
00724   GRSTgaclEntry *entry;
00725   GRSTgaclCred  *cred;
00726 
00727   if (xmlStrcmp(cur->name, (const xmlChar *) "entry") != 0) return NULL;
00728   
00729   cur = cur->xmlChildrenNode;
00730 
00731   entry = GRSTgaclEntryNew();
00732   
00733   while (cur != NULL)
00734        {
00735          if (xmlIsBlankNode(cur))
00736            {
00737              cur=cur->next;
00738              continue;
00739            }
00740          else if (xmlStrcmp(cur->name, (const xmlChar *) "allow") == 0)
00741            {
00742              for (cur2 = cur->xmlChildrenNode; cur2 != NULL; cur2=cur2->next)
00743                 if (!xmlIsBlankNode(cur2))
00744                   {                
00745                     for (i=0; grst_perm_syms[i] != NULL; ++i)
00746                      if (xmlStrcmp(cur2->name, 
00747                              (const xmlChar *) grst_perm_syms[i]) == 0)
00748                        GRSTgaclEntryAllowPerm(entry, grst_perm_vals[i]);
00749                   }
00750            }
00751          else if (xmlStrcmp(cur->name, (const xmlChar *) "deny") == 0)
00752            {
00753              for (cur2 = cur->xmlChildrenNode; cur2 != NULL; cur2=cur2->next)
00754                 if (!xmlIsBlankNode(cur2))
00755                   {
00756                     for (i=0; grst_perm_syms[i] != NULL; ++i)
00757                      if (xmlStrcmp(cur2->name, 
00758                              (const xmlChar *) grst_perm_syms[i]) == 0)
00759                        GRSTgaclEntryDenyPerm(entry, grst_perm_vals[i]);
00760                   }
00761            }
00762          else if ((cred = GRSTgaclCredParse(cur)) != NULL) 
00763            {
00764              if (!GRSTgaclEntryAddCred(entry, cred))
00765                { 
00766                  GRSTgaclCredFree(cred);                
00767                  GRSTgaclEntryFree(entry);
00768                  return NULL;
00769                }
00770            }
00771          else /* I cannot parse this - give up rather than get it wrong */
00772            {
00773              GRSTgaclEntryFree(entry);
00774              return NULL;
00775            }
00776            
00777          cur=cur->next;
00778        } 
00779        
00780   return entry;
00781 }
00782 
00783 GRSTgaclAcl *GRSTgaclAclLoadFile(char *filename)
00784 {
00785   xmlDocPtr   doc;
00786   xmlNodePtr  cur;
00787   GRSTgaclAcl    *acl=NULL;
00788 
00789   GRSTerrorLog(GRST_LOG_DEBUG, "GRSTgaclAclLoadFile() starting");
00790 
00791   if (filename == NULL) 
00792     {
00793       GRSTerrorLog(GRST_LOG_DEBUG, "GRSTgaclAclLoadFile() cannot open a NULL filename");
00794       return NULL;
00795     }
00796 
00797   doc = xmlParseFile(filename);
00798   if (doc == NULL) 
00799     {
00800       GRSTerrorLog(GRST_LOG_DEBUG, "GRSTgaclAclLoadFile failed to open ACL file %s", filename);
00801       return NULL;
00802     }
00803 
00804   cur = xmlDocGetRootElement(doc);
00805   if (cur == NULL) 
00806     {
00807       xmlFreeDoc(doc);
00808       GRSTerrorLog(GRST_LOG_DEBUG, "GRSTgaclAclLoadFile failed to parse root of ACL file %s", filename);
00809       return NULL;
00810     }
00811 
00812   if (!xmlStrcmp(cur->name, (const xmlChar *) "Policy")) 
00813     { 
00814       GRSTerrorLog(GRST_LOG_DEBUG, "GRSTgaclAclLoadFile parsing XACML");
00815       acl=GRSTxacmlAclParse(doc, cur, acl);
00816     }
00817   else if (!xmlStrcmp(cur->name, (const xmlChar *) "gacl")) 
00818     {
00819       GRSTerrorLog(GRST_LOG_DEBUG, "GRSTgaclAclLoadFile parsing GACL");
00820       acl=GRSTgaclAclParse(doc, cur, acl);
00821     }
00822   else /* ACL format not recognised */
00823     {
00824       xmlFreeDoc(doc);
00825       return NULL;
00826     }
00827     
00828   xmlFreeDoc(doc);
00829   return acl;
00830 }
00831 
00832 GRSTgaclAcl *GRSTgaclAclParse(xmlDocPtr doc, xmlNodePtr cur, GRSTgaclAcl *acl)
00833 {
00834   GRSTgaclEntry  *entry;
00835 
00836   cur = cur->xmlChildrenNode;
00837 
00838   acl = GRSTgaclAclNew();
00839 
00840   while (cur != NULL)
00841        {
00842          if (!xmlIsBlankNode(cur))
00843            {
00844              entry = GRSTgaclEntryParse(cur);
00845              if (entry == NULL)
00846                {
00847                  GRSTgaclAclFree(acl);
00848 
00849                  return NULL;
00850                }
00851 
00852              GRSTgaclAclAddEntry(acl, entry);
00853            }
00854 
00855          cur=cur->next;
00856        }
00857 
00858   return acl;
00859 }
00860 int GRSTgaclFileIsAcl(char *pathandfile)
00861 /* Return 1 if filename in *pathandfile starts GRST_ACL_FILE
00862    Return 0 otherwise. */
00863 {
00864   char *filename;
00865 
00866   filename = rindex(pathandfile, '/');
00867   if (filename == NULL) filename = pathandfile;
00868   else                  filename++;
00869 
00870   return (strncmp((const char*)filename, GRST_ACL_FILE, sizeof(GRST_ACL_FILE) - 1) == 0);
00871 }
00872 
00873 char *GRSTgaclFileFindAclname(char *pathandfile)
00874 /* Return malloc()ed ACL filename that governs the given file or directory 
00875    (for directories, the ACL file is in the directory itself), or NULL if none
00876    can be found. */
00877 {
00878   int          len;
00879   char        *path, *file, *p;
00880   struct stat  statbuf;
00881 
00882   len = strlen(pathandfile);
00883   if (len == 0) return NULL;
00884   
00885   path = malloc(len + sizeof(GRST_ACL_FILE) + 2);
00886   strcpy(path, pathandfile);
00887 
00888   if ((stat(path, &statbuf) == 0)       &&
00889        S_ISDIR(statbuf.st_mode)         &&
00890       (path[len-1] != '/'))
00891     {
00892       strcat(path, "/");
00893       ++len;
00894     }
00895     
00896   if (path[len-1] != '/')
00897     {
00898       p = rindex(pathandfile, '/');
00899       if (p != NULL)
00900         {
00901           file = &p[1];          
00902           p = rindex(path, '/');          
00903           sprintf(p, "/%s:%s", GRST_ACL_FILE, file);
00904 
00905           if (stat(path, &statbuf) == 0) return path;
00906 
00907           *p = '\0'; /* otherwise strip off any filename */
00908         }
00909     }
00910 
00911   while (path[0] != '\0')
00912        {
00913          strcat(path, "/");
00914          strcat(path, GRST_ACL_FILE);
00915          
00916          if (stat(path, &statbuf) == 0) return path;
00917            
00918          p = rindex(path, '/');
00919          *p = '\0';     /* strip off the / we added for ACL */
00920 
00921          p = rindex(path, '/');
00922          if (p == NULL) break; /* must start without / and we there now ??? */
00923 
00924          *p = '\0';     /* strip off another layer of / */                 
00925        }
00926        
00927   free(path);
00928   return NULL;
00929 }
00930 
00931 GRSTgaclAcl *GRSTgaclAclLoadforFile(char *pathandfile)
00932 /* Return ACL that governs the given file or directory (for directories,
00933    the ACL file is in the directory itself.) */
00934 {
00935   char        *path;
00936   GRSTgaclAcl     *acl;
00937 
00938   path = GRSTgaclFileFindAclname(pathandfile);
00939   
00940   if (path != NULL)
00941     {
00942       acl = GRSTgaclAclLoadFile(path);
00943       free(path);
00944       return acl;
00945     }
00946     
00947   return NULL;
00948 }
00949 
00950 /*                                        *
00951  * Functions to create and query GACLuser *
00952  *                                        */
00953 
00954 GRSTgaclUser *GRSTgaclUserNew(GRSTgaclCred *cred)
00955 {
00956   GRSTgaclUser *user;
00957   
00958   if (cred == NULL) return NULL;
00959   
00960   user = malloc(sizeof(GRSTgaclUser));
00961   
00962   if (user != NULL)   
00963     { 
00964       user->firstcred = cred;
00965       user->dnlists   = NULL;
00966     }
00967   
00968   return user;
00969 }
00970 
00971 int GRSTgaclUserFree(GRSTgaclUser *user)
00972 {
00973   if (user == NULL) return 1;
00974   
00975   if (user->firstcred != NULL) GRSTgaclCredsFree(user->firstcred);
00976   
00977   if (user->dnlists != NULL) free(user->dnlists);
00978   
00979   free(user);
00980   
00981   return 1;
00982 }
00983 
00984 int GRSTgaclUserAddCred(GRSTgaclUser *user, GRSTgaclCred *cred)
00985 {
00986   GRSTgaclCred *crediter;
00987 
00988   if ((user == NULL) || (cred == NULL)) return 0;
00989 
00990   if (user->firstcred == NULL) 
00991     {
00992       user->firstcred = cred;
00993       cred->next = NULL; /* so cannot be used to add whole lists */
00994       return 1;
00995     }
00996   
00997   crediter = user->firstcred;  
00998 
00999   while (crediter->next != NULL) crediter = crediter->next;
01000 
01001   crediter->next = cred;
01002   cred->next = NULL; /* so cannot be used to add whole lists */
01003        
01004   return 1;
01005 }
01006 
01007 int GRSTgaclUserHasCred(GRSTgaclUser *user, GRSTgaclCred *cred)
01008 /* test if the user has the given credential */
01009 {
01010   int                nist_loa = 999;
01011   GRSTgaclCred      *crediter;
01012 
01013   if ((cred == NULL) || (cred->auri == NULL)) return 0;
01014 
01015   if (strcmp(cred->auri, "gacl:any-user") == 0) return 1;
01016   
01017   if ((user == NULL) || (user->firstcred == NULL)) return 0;
01018   
01019   if (strncmp((const char*)cred->auri, "dns:", 4) == 0)
01020     {      
01021       for (crediter=user->firstcred; 
01022            crediter != NULL; 
01023            crediter = crediter->next)
01024         if ((crediter->auri != NULL) &&
01025             (strncmp((const char*)crediter->auri, "dns:", 4) == 0))
01026 #ifdef SUNCC
01027           return (fnmatch(cred->auri, crediter->auri, 0) == 0);
01028 #else
01029           return (fnmatch(cred->auri, crediter->auri, FNM_CASEFOLD) == 0);
01030 #endif
01031            
01032       return 0;    
01033     }
01034     
01035   if (strcmp(cred->auri, "gacl:auth-user") == 0)
01036     {
01037       for (crediter=user->firstcred; 
01038            crediter != NULL; 
01039            crediter = crediter->next)
01040         if ((crediter->auri != NULL) &&
01041             (strncmp((const char*)crediter->auri, "dn:", 3) == 0)) return 1;
01042                 
01043       return 0;    
01044     }
01045   
01046   if (sscanf(cred->auri, "nist-loa:%d", &nist_loa) == 1)
01047     {
01048       for (crediter=user->firstcred; 
01049            crediter != NULL; 
01050            crediter = crediter->next)
01051         if ((crediter->auri != NULL) &&
01052             (strncmp((const char*)crediter->auri, "dn:", 3) == 0) &&
01053             (crediter->nist_loa >= nist_loa)) return 1;
01054 
01055       return 0;    
01056     }
01057 
01058 /*
01059 // can remove this once we preload DN Lists etc as AURIs?
01060   if ((strncmp((const char*)cred->auri, "http:",  5) == 0) ||
01061       (strncmp((const char*)cred->auri, "https:", 6) == 0))
01062     {      
01063       return GRSTgaclDNlistHasUser(cred->auri, user);
01064     }
01065 */
01066   /* generic AURI = AURI test */
01067 
01068   for (crediter=user->firstcred; crediter != NULL; crediter = crediter->next)
01069      if ((crediter->auri != NULL) &&
01070          (strcmp(crediter->auri, cred->auri) == 0)) return 1;
01071            
01072   return 0;    
01073 }
01074 
01075 GRSTgaclCred *GRSTgaclUserFindCredtype(GRSTgaclUser *user, char *type)
01076 /* find the first credential of a given type for this user */
01077 {
01078   GRSTgaclCred *cred;
01079 
01080   if (user == NULL) return NULL;
01081   
01082   cred = user->firstcred;  
01083 
01084   while (cred != NULL)
01085        {
01086          if ((strcmp(type, "person") == 0) &&       
01087              (strncmp((const char*)cred->auri, "dn:", 3) == 0)) return cred;
01088 
01089          if ((strcmp(type, "voms") == 0) &&       
01090              (strncmp((const char*)cred->auri, "fqan:", 5) == 0)) return cred;
01091 
01092          if ((strcmp(type, "dns") == 0) &&
01093              (strncmp((const char*)cred->auri, "dns:", 4) == 0)) return cred;
01094 
01095          if ((strcmp(type, "dn-list") == 0) &&
01096              ((strncmp((const char*)cred->auri, "http:",  5) == 0) || 
01097               (strncmp((const char*)cred->auri, "https:", 6) == 0))) return cred;
01098          
01099          cred = cred->next;       
01100        }
01101        
01102   return NULL;
01103 }
01104 
01105 int GRSTgaclUserSetDNlists(GRSTgaclUser *user, char *dnlists)
01106 {
01107   if (user->dnlists != NULL) free(user->dnlists);
01108 
01109   if (dnlists == NULL) user->dnlists = NULL;
01110   else                 user->dnlists = strdup(dnlists);
01111 
01112   return GRSTgaclUserLoadDNlists(user, dnlists);
01113 }
01114 
01115 static void recurse4dnlists(GRSTgaclUser *user, char *dir,
01116                             int recurse_level, GRSTgaclCred *dn_cred)
01117 /* try to find file[] in dir[]. try subdirs if not found. 
01118    return full path to first found version or NULL on failure */
01119 {
01120   int            fd, linestart, i;
01121   char          *mapped, *s;
01122   char           fullfilename[16384]; 
01123   size_t         dn_len;
01124   struct stat    statbuf;
01125   DIR           *dirDIR;
01126   struct dirent *file_ent;
01127   GRSTgaclCred  *cred;
01128 
01129   if (recurse_level >= GRST_RECURS_LIMIT) return;
01130 
01131   dn_len = strlen(dn_cred->auri) - 3;
01132 
01133   /* search this directory */
01134   
01135   dirDIR = opendir(dir);
01136   
01137   if (dirDIR == NULL) return;
01138   
01139   while ((file_ent = readdir(dirDIR)) != NULL)
01140        {
01141          if (file_ent->d_name[0] == '.') continue;
01142        
01143          sprintf(fullfilename, "%s/%s", dir, file_ent->d_name);
01144 
01145          GRSTerrorLog(GRST_LOG_DEBUG, "recurse4dnlists opens %s", fullfilename);
01146 
01147          if ((fd = open(fullfilename, O_RDONLY)) < 0)
01148            ;
01149          else if (fstat(fd, &statbuf) != 0)
01150            ;
01151          else if (S_ISDIR(statbuf.st_mode))
01152            recurse4dnlists(user, fullfilename, recurse_level + 1, dn_cred);
01153          else if ((S_ISREG(statbuf.st_mode) || S_ISLNK(statbuf.st_mode)) &&
01154                   ((mapped = mmap(NULL, statbuf.st_size, 
01155                                PROT_READ, MAP_PRIVATE, fd, 0)) != MAP_FAILED))
01156            {  
01157              linestart = 0;
01158              
01159              while (linestart + dn_len <= statbuf.st_size)
01160                   {
01161                     GRSTerrorLog(GRST_LOG_DEBUG, "recurse4dnlists at %ld in %s", 
01162                           linestart, fullfilename);
01163 
01164                     for (i=0; 
01165                          (linestart + i < statbuf.st_size) && (i < dn_len);
01166                          ++i)
01167                        if (mapped[linestart + i] != dn_cred->auri[3+i]) break;
01168 
01169                     GRSTerrorLog(GRST_LOG_DEBUG, "recurse4dnlists at %d %d %d %d", 
01170                           linestart, i, dn_len, statbuf.st_size);
01171 
01172                     if ((i == dn_len) && 
01173                         ((linestart+i == statbuf.st_size) ||
01174                          (mapped[linestart+i] == '\n') ||
01175                          (mapped[linestart+i] == '\r')))  /* matched */                    
01176                       {                        
01177                         s = GRSThttpUrlDecode(file_ent->d_name);                    
01178                         cred = GRSTgaclCredCreate(s, NULL);
01179                         GRSTerrorLog(GRST_LOG_DEBUG, 
01180                                      "recurse4dnlists adds %s", s);
01181                         free(s);
01182                     
01183                         GRSTgaclCredSetNotBefore(cred,  dn_cred->notbefore);
01184                         GRSTgaclCredSetNotAfter(cred,   dn_cred->notafter);
01185                         GRSTgaclCredSetDelegation(cred, dn_cred->delegation);
01186                         GRSTgaclCredSetNistLoa(cred,    dn_cred->nist_loa);
01187 
01188                         GRSTgaclUserAddCred(user, cred);
01189                         break;
01190                       }                    
01191                       
01192                     linestart += i;
01193 
01194                     while ((linestart < statbuf.st_size) &&
01195                            (mapped[linestart] != '\n') && 
01196                            (mapped[linestart] != '\r')) ++linestart;
01197 
01198                     while ((linestart < statbuf.st_size) &&
01199                            ((mapped[linestart] == '\n') || 
01200                             (mapped[linestart] == '\r'))) ++linestart;
01201                   }
01202              
01203              munmap(mapped, statbuf.st_size);
01204            }
01205 
01206          if (fd < 0) close(fd);
01207        }
01208   
01209   closedir(dirDIR);  
01210 }
01211 
01212 int GRSTgaclUserLoadDNlists(GRSTgaclUser *user, char *dnlists)
01213 /*
01214     Examine DN Lists for attributes belonging to this user and
01215     add them to *user as additional credentials.
01216 */
01217 {
01218   char *dn_lists_dirs, *dn_list_ptr, *dirname;
01219   GRSTgaclCred *dn_cred;
01220 
01221   /* check for DN Lists */
01222 
01223   if (dnlists == NULL) dnlists = getenv("GRST_DN_LISTS");
01224 
01225   if (dnlists == NULL) dnlists = GRST_DN_LISTS;
01226   
01227   if (*dnlists == '\0') return 1; /* Didn't ask for anything: that's ok */
01228   
01229   /* find this user's (first) DN */
01230   
01231   if (user == NULL) return 1; /* No user! */
01232 
01233   for (dn_cred = user->firstcred; dn_cred != NULL; dn_cred = dn_cred->next)
01234      { 
01235        if (strncmp((const char*)dn_cred->auri, "dn:", 3) == 0) break;
01236      }
01237      
01238   if (dn_cred == NULL) return 1; /* User has no DN! */
01239 
01240   /* look through DN List files */
01241   
01242   dn_lists_dirs = strdup(dnlists); /* we need to keep this for free() later! */
01243   dn_list_ptr   = dn_lists_dirs;   /* copy, for naughty function strsep()    */
01244 
01245   while ((dirname = strsep(&dn_list_ptr, ":")) != NULL)
01246        {
01247          recurse4dnlists(user, dirname, 0, dn_cred);
01248        }
01249        
01250   free(dn_lists_dirs);
01251   return 1;
01252 }
01253 
01254 /*                                                     *
01255  * Functions to test for access perm of an individual  *
01256  *                                                     */
01257 
01258 #if 0
01259 static char *recurse4file(char *dir, char *file, int recurse_level)
01260 /* try to find file[] in dir[]. try subdirs if not found. 
01261    return full path to first found version or NULL on failure */
01262 {
01263   char           fullfilename[16384], fulldirname[16384];
01264   struct stat    statbuf;
01265   DIR           *dirDIR;
01266   struct dirent *file_ent;
01267 
01268   /* try to find in current directory */
01269 
01270   sprintf(fullfilename, "%s/%s", dir, file);  
01271   if (stat(fullfilename, &statbuf) == 0) return fullfilename;
01272 
01273   /* maybe search in subdirectories */
01274   
01275   if (recurse_level >= GRST_RECURS_LIMIT) return NULL;
01276 
01277   dirDIR = opendir(dir);
01278   
01279   if (dirDIR == NULL) return NULL;
01280   
01281   while ((file_ent = readdir(dirDIR)) != NULL)
01282        {
01283          if (file_ent->d_name[0] == '.') continue;
01284        
01285          sprintf(fulldirname, "%s/%s", dir, file_ent->d_name);
01286 
01287          if ((stat(fulldirname, &statbuf) == 0) &&
01288              S_ISDIR(statbuf.st_mode) &&
01289              ((fullfilename = recurse4file(fulldirname, file, 
01290                                              recurse_level + 1)) != NULL))
01291            {
01292              closedir(dirDIR);             
01293              return fullfilename;
01294            }
01295            
01296        }
01297   
01298   closedir(dirDIR);  
01299 
01300   return NULL;
01301 }
01302 #endif
01303 
01304 int GRSTgaclDNlistHasUser(char *listurl, GRSTgaclUser *user)
01305 {
01306   return GRSTgaclUserHasAURI(user, listurl);
01307 }
01308 
01309 int GRSTgaclUserHasAURI(GRSTgaclUser *user, char *auri)
01310 {
01311   GRSTgaclCred *cred;
01312     
01313   if ((auri == NULL) || (user == NULL)) return 0;
01314   
01315   for (cred = user->firstcred; cred != NULL; cred = cred->next)
01316      {
01317        if (strcmp(auri, cred->auri) == 0) return 1;
01318      }
01319 
01320   return 0;
01321 }
01322 
01323 GRSTgaclPerm GRSTgaclAclTestUser(GRSTgaclAcl *acl, GRSTgaclUser *user)
01324 /*
01325     GACLgaclAclTestUser - return bit fields depending on access perms user has
01326                       for given acl. All zero for no access. If *user is
01327                       NULL, matching to "any-user" will still work.
01328 */
01329 {
01330   int        flag, onlyanyuser;
01331   GRSTgaclPerm   allowperms = 0, denyperms = 0, allowed;
01332   GRSTgaclEntry *entry;
01333   GRSTgaclCred  *cred;
01334   
01335   if (acl == NULL) return 0;
01336   
01337   for (entry = acl->firstentry; entry != NULL; entry = entry->next)
01338      {
01339        flag = 1;        /* begin by assuming this entry applies to us */
01340        onlyanyuser = 1; /* begin by assuming just <any-user/> */
01341        
01342        /* now go through creds, checking they all do apply to us */
01343      
01344        for (cred = entry->firstcred; cred != NULL; cred = cred->next)
01345              if (!GRSTgaclUserHasCred(user, cred)) flag = 0;
01346              else if (strcmp(cred->auri, "gacl:any-user") != 0) onlyanyuser = 0;
01347 
01348        if (!flag) continue; /* flag false if a subtest failed */
01349 
01350        /* does apply to us, so we remember this entry's perms */
01351        
01352        /* we dont allow Write or Admin on the basis of any-user alone */
01353 
01354        allowed = entry->allowed;
01355 
01356        if (onlyanyuser)
01357             allowed = entry->allowed & ~GRST_PERM_WRITE & ~GRST_PERM_ADMIN;
01358        else allowed = entry->allowed;
01359 
01360        allowperms = allowperms | allowed;
01361        denyperms  = denyperms  | entry->denied;
01362      }
01363 
01364   return (allowperms & (~ denyperms)); 
01365   /* for each perm type, any deny we saw kills any allow */
01366 }
01367 
01368 GRSTgaclPerm GRSTgaclAclTestexclUser(GRSTgaclAcl *acl, GRSTgaclUser *user)
01369 /*
01370     GRSTgaclAclTestexclUser - 
01371                       return bit fields depending on ALLOW perms OTHER users 
01372                       have for given acl. All zero if they have no access.
01373                       (used for testing if a user has exclusive access)
01374 */
01375 {
01376   int        flag;
01377   GRSTgaclPerm  perm = 0;
01378   GRSTgaclEntry *entry;
01379   GRSTgaclCred  *cred;
01380   
01381   if (acl == NULL) return 0;
01382   
01383   for (entry = acl->firstentry; entry != NULL; entry = entry->next)
01384      {
01385        flag = 0; /* flag will be set if cred implies other users */
01386      
01387        for (cred = entry->firstcred; cred != NULL; cred = cred->next)
01388           {
01389             if (strncmp((const char*)cred->auri, "dn:", 3) != 0)
01390              /* if we ever add support for other person-specific credentials,
01391                 they must also be recognised here */
01392               {
01393                 flag = 1;
01394                 break; 
01395               }
01396 
01397             if (!GRSTgaclUserHasCred(user, cred))
01398                  /* if user doesnt have this person credential, assume
01399                     it refers to a different individual */
01400               {
01401                 flag = 1;
01402                 break;
01403               }
01404           }
01405 
01406        if (flag) perm = perm | entry->allowed;
01407      }
01408 
01409   return perm;     
01410 }
01411 
01412 /* 
01413     Wrapper functions for gridsite-gacl.h support of legacy API
01414 */
01415 
01416 GRSTgaclEntry *GACLparseEntry(xmlNodePtr cur)
01417 {
01418   return GRSTgaclEntryParse(cur);
01419 }

Generated on Tue Jul 5 14:47:00 2011 for ROOT_528-00b_version by  doxygen 1.5.1