added files for XACML functions and example source code.
authorShiv Kaushal <shiv.kaushal@manchester.ac.uk>
Mon, 23 May 2005 11:51:23 +0000 (11:51 +0000)
committerShiv Kaushal <shiv.kaushal@manchester.ac.uk>
Mon, 23 May 2005 11:51:23 +0000 (11:51 +0000)
org.gridsite.core/src/Makefile
org.gridsite.core/src/grst_xacml.c [new file with mode: 0644]
org.gridsite.core/src/xacmlexample.c [new file with mode: 0644]

index 0acfe92..e7e48ac 100644 (file)
@@ -64,12 +64,12 @@ build: libgridsite_globus.so.$(VERSION) libgridsite_globus.a
 
 # First, normal versions using system OpenSSL rather than Globus OpenSSL
 
-libgridsite.so.$(VERSION): grst_x509.o grst_gacl.o grst_http.o grst_asn1.o
+libgridsite.so.$(VERSION): grst_x509.o grst_gacl.o grst_xacml.o grst_http.o grst_asn1.o
        gcc -shared -Wl,-soname,libgridsite.so.$(MINOR_VERSION) \
-         -o libgridsite.so.$(PATCH_VERSION) grst_x509.o grst_gacl.o grst_http.o grst_asn1.o
+         -o libgridsite.so.$(PATCH_VERSION) grst_x509.o grst_gacl.o grst_xacml.o grst_http.o grst_asn1.o
 
-libgridsite.a: grst_x509.o grst_gacl.o grst_http.o grst_asn1.o
-       ar src libgridsite.a grst_x509.o grst_gacl.o grst_http.o grst_asn1.o
+libgridsite.a: grst_x509.o grst_gacl.o grst_xacml.o grst_http.o grst_asn1.o
+       ar src libgridsite.a grst_x509.o grst_gacl.o grst_xacml.o grst_http.o grst_asn1.o
 
 grst_x509.o: grst_x509.c ../interface/gridsite.h
        gcc $(MYCFLAGS) \
@@ -79,6 +79,10 @@ grst_gacl.o: grst_gacl.c ../interface/gridsite.h
        gcc $(MYCFLAGS) \
             -I/usr/kerberos/include `xml2-config --cflags` -c grst_gacl.c
 
+grst_xacml.o: grst_xacml.c ../interface/gridsite.h
+       gcc $(MYCFLAGS) \
+            -I/usr/kerberos/include `xml2-config --cflags` -c grst_xacml.c
+
 grst_http.o: grst_http.c ../interface/gridsite.h
        gcc $(MYCFLAGS) \
                         -I/usr/kerberos/include -c grst_http.c
@@ -176,7 +180,12 @@ apidoc:
 gaclexample: gaclexample.c libgridsite.a
        gcc -o gaclexample gaclexample.c -I. -L. \
             -I/usr/kerberos/include -lgridsite \
-            -lssl -lcrypto -lxml2 -lz -lm 
+            -lssl -lcrypto -lxml2 -lz -lm
+           
+xacmlexample: xacmlexample.c libgridsite.a
+       gcc -o xacmlexample xacmlexample.c -I. -L. \
+            -I/usr/kerberos/include -lgridsite \
+            -lssl -lcrypto -lxml2 -lz -lm
 
 #
 # Delegation machinery, including SOAP delegation portType. To build this
diff --git a/org.gridsite.core/src/grst_xacml.c b/org.gridsite.core/src/grst_xacml.c
new file mode 100644 (file)
index 0000000..6beff98
--- /dev/null
@@ -0,0 +1,556 @@
+/*
+   Andrew McNab and Shiv Kaushal, University of Manchester.
+   Copyright (c) 2002-3. All rights reserved.
+
+   Redistribution and use in source and binary forms, with or
+   without modification, are permitted provided that the following
+   conditions are met:
+
+     o Redistributions of source code must retain the above
+       copyright notice, this list of conditions and the following
+       disclaimer.
+     o Redistributions in binary form must reproduce the above
+       copyright notice, this list of conditions and the following
+       disclaimer in the documentation and/or other materials
+       provided with the distribution.
+
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+   CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+   INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+   MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+   DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+   BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+   EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+   TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+   ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+   OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+   OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+   POSSIBILITY OF SUCH DAMAGE.
+*/
+/*------------------------------------------------------------------------*
+ * For more information about GridSite: http://www.gridpp.ac.uk/gridsite/ *
+ *------------------------------------------------------------------------*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <string.h>
+#include <dirent.h>
+#include <ctype.h>
+
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE
+#endif
+#include <fnmatch.h>
+
+#include <libxml/xmlmemory.h>
+#include <libxml/tree.h>
+#include <libxml/parser.h>
+
+#include "gridsite.h"
+
+//#define XACML_DEBUG
+
+#ifdef XACML_DEBUG
+  #define XACML_DEBUG_FILE "/tmp/grstxacmldebug.out"
+#endif
+
+
+/*                                                                      *
+ * Global variables, shared by all GACL functions by private to libgacl *
+ *                                                                      */
+
+extern char     *grst_perm_syms[];
+extern GRSTgaclPerm grst_perm_vals[];
+
+
+FILE* debugfile;
+
+
+/*                                                     *
+ * Functions to read in XACML 1.1 compliant format ACL *
+ * Functions based on method for opening GACL format   *
+ *                                                     */
+
+// need to check these for libxml memory leaks? - what needs to be freed?
+
+
+static GRSTgaclCred *GRSTxacmlCredParse(xmlNodePtr cur)
+/*
+    GRSTxacmlCredParse - parse a credential stored in the libxml structure cur,
+    returning it as a pointer or NULL on error.
+*/
+{
+  xmlNodePtr  attr_val;
+  xmlNodePtr  attr_des;
+  GRSTgaclCred   *cred;
+
+  // cur points to <Subject> or <AnySubjects/>, loop done outside this function.
+
+  if ( (xmlStrcmp(cur->name, (const xmlChar *) "AnySubject") == 0)) cred = GRSTgaclCredNew("any-user");
+
+  else{
+
+  attr_val=cur->xmlChildrenNode->xmlChildrenNode;
+  attr_des=attr_val->next;
+
+  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
+  GRSTgaclCredAddValue(cred, (char *) xmlNodeGetContent(attr_des->properties->next->children),
+                             (char *) xmlNodeGetContent(attr_val));
+  }
+
+  return cred;
+}
+
+static GRSTgaclEntry *GRSTxacmlEntryParse(xmlNodePtr cur)
+/*
+    GRSTxacmlEntryParse - parse an entry stored in the libxml structure cur,
+    returning it as a pointer or NULL on error. Also checks to see if the following
+    <Rule> tag refers to the same <Target> by checking the <RuleId> of both
+*/
+{
+  int        i, check=0;
+  xmlDocPtr  doc=cur->doc;
+  xmlNodePtr cur2;
+  xmlNodePtr rule_root=cur;
+  GRSTgaclEntry *entry;
+  GRSTgaclCred  *cred;
+  GRSTgaclPerm  perm;
+
+
+  // Next line not needed as function only called if <Rule> tag found
+  // if (xmlStrcmp(cur->name, (const xmlChar *) "Rule") != 0) return NULL;
+  // cur and rule_root point to the <Rule> tag
+
+  cur = cur->xmlChildrenNode->xmlChildrenNode;
+  // cur should now be pointing at <Subjects> tag
+#ifdef XACML_DEBUG
+  fprintf (debugfile, "Starting to Parse Entry\n");
+#endif
+  entry = GRSTgaclEntryNew();
+
+  while (cur!=NULL){
+
+    if (xmlStrcmp(cur->name, (const xmlChar *) "Subjects") == 0){
+#ifdef XACML_DEBUG
+      fprintf (debugfile, "Starting to Parse Credentials\n");
+#endif
+      if (check==0){
+        // cur still pointing at <Subjects> tag make cur2 point to <Subject> and loop over them.
+       cur2=cur->xmlChildrenNode;
+       while (cur2!=NULL){
+          if ( ((cred = GRSTxacmlCredParse(cur2)) != NULL) && (!GRSTgaclEntryAddCred(entry, cred))){
+            GRSTgaclCredFree(cred);
+            GRSTgaclEntryFree(entry);
+            return NULL;
+         }
+         cur2=cur2->next;
+        }
+      }
+    }
+
+    else if (xmlStrcmp(cur->name, (const xmlChar *) "Actions") == 0){
+#ifdef XACML_DEBUG
+      fprintf (debugfile, "Starting to Parse Permissions\n");
+#endif
+      if (xmlStrcmp(xmlNodeGetContent(rule_root->properties->next->children), (const xmlChar *) "Permit") == 0 ){
+#ifdef XACML_DEBUG
+       fprintf (debugfile, "\tPermit-ed actions: ");
+#endif
+        for (cur2 = cur->xmlChildrenNode; cur2 != NULL; cur2=cur2->next) //cur2-><Action>
+          for (i=0; grst_perm_syms[i] != NULL; ++i)
+            if (xmlStrcmp(xmlNodeGetContent(cur2->xmlChildrenNode->xmlChildrenNode), (const xmlChar *) grst_perm_syms[i]) == 0)
+            {
+#ifdef XACML_DEBUG
+              fprintf (debugfile, "%s ", grst_perm_syms[i]);
+#endif
+             GRSTgaclEntryAllowPerm(entry, grst_perm_vals[i]);
+           }
+      }
+
+      if (xmlStrcmp(xmlNodeGetContent(rule_root->properties->next->children), (const xmlChar *) "Deny") == 0 ) {
+#ifdef XACML_DEBUG
+       fprintf (debugfile, "\tDeny-ed actions: ");
+#endif
+        for (cur2 = cur->xmlChildrenNode; cur2 != NULL; cur2=cur2->next) //cur2-><Action>
+          for (i=0; grst_perm_syms[i] != NULL; ++i)
+            if (xmlStrcmp(xmlNodeGetContent(cur2->xmlChildrenNode->xmlChildrenNode), (const xmlChar *) grst_perm_syms[i]) == 0)
+            {
+              
+#ifdef XACML_DEBUG
+             fprintf (debugfile, "%s ", grst_perm_syms[i]);
+#endif
+             GRSTgaclEntryDenyPerm(entry, grst_perm_vals[i]);
+           }
+      }
+
+    }
+    else{ // I cannot parse this - give up rather than get it wrong
+#ifdef XACML_DEBUG
+      fprintf (debugfile, "OOOPSIE\n");
+#endif
+      GRSTgaclEntryFree(entry);
+      return NULL;
+    }
+
+    cur=cur->next;
+
+    // Check if next Rule should be included when end of current rule reached
+    // If RuleId are from the same entry (eg Entry1A and Entry1D)
+    // make cur point to the next Rule's <Subjects> tag
+    if (cur==NULL)
+      if (check==0)
+        if (rule_root->next!=NULL)
+         if ( strncmp(xmlNodeGetContent(rule_root->properties->children), // RuleId of this Rule
+                xmlNodeGetContent(rule_root->next->properties->children), // RuleId of next Rule
+                6) == 0){
+#ifdef XACML_DEBUG
+           fprintf (debugfile, "End of perms and creds, next is %s \n", xmlNodeGetContent(rule_root->next->properties->children));
+#endif
+           rule_root=rule_root->next;
+           cur=rule_root->xmlChildrenNode->xmlChildrenNode;
+#ifdef XACML_DEBUG
+           fprintf (debugfile, "skipped to <%s> tag of next Rule\n", cur->name);
+#endif
+           check++;
+         }
+  }
+
+  return entry;
+}
+
+GRSTgaclAcl *GRSTxacmlAclLoadFile(char *filename)
+{
+  xmlDocPtr   doc;
+  xmlNodePtr  cur;
+  GRSTgaclAcl    *acl;
+  GRSTgaclEntry  *entry;
+#ifdef XACML_DEBUG
+  debugfile=fopen(XACML_DEBUG_FILE, "w");
+  fprintf (debugfile, "Loading acl..\n");
+#endif
+  doc = xmlParseFile(filename);
+  if (doc == NULL) return NULL;
+
+  cur = xmlDocGetRootElement(doc);
+  if (cur == NULL) return NULL;
+   if (xmlStrcmp(cur->name, (const xmlChar *) "Policy"))
+    {
+      free(doc);
+      free(cur);
+      return NULL;
+    }
+#ifdef XACML_DEBUG
+  fprintf (debugfile, "Error Checks done, load acl\n");
+#endif
+  // Have an XACML policy file.
+  // Skip <Target> tag and set cur to first <Rule> tag
+  cur = cur->xmlChildrenNode->next;
+
+  acl = GRSTgaclAclNew();
+
+  while (cur != NULL){
+
+
+    if ( xmlStrcmp(cur->name, (const xmlChar *)"Rule") == 0 ){ // IF statement not needed?
+#ifdef XACML_DEBUG
+      fprintf (debugfile, "Rule %s found\n", xmlNodeGetContent(cur->properties->children) );
+      fprintf (debugfile, "Parsing Entry for this rule\n");
+#endif
+      entry = GRSTxacmlEntryParse(cur);
+
+      if (entry == NULL){
+        GRSTgaclAclFree(acl);
+        xmlFreeDoc(doc);
+        return NULL;
+      }
+      else GRSTgaclAclAddEntry(acl, entry);
+#ifdef XACML_DEBUG
+      fprintf (debugfile, "Entry read in\n\n");
+#endif
+    }
+    // If the current and next Rules are part of the same entry then advance two Rules
+    // If not then advance 1
+    if (cur->next != NULL)
+      if ( strncmp(xmlNodeGetContent(cur->properties->children),       // RuleId of this Rule
+                   xmlNodeGetContent(cur->next->properties->children), // RuleId of next Rule
+                   6) == 0) {
+#ifdef XACML_DEBUG
+                  fprintf (debugfile, "skipping next rule %s, should have been caught previously\n\n", xmlNodeGetContent(cur->next->properties->children) );
+#endif
+                  cur=cur->next;
+                  } // Check first 6 characters i.e. Entry1**/
+    cur=cur->next;
+
+  }
+#ifdef XACML_DEBUG
+  fprintf (debugfile, "Finished loading ACL - Fanfare!\n");
+  fclose(debugfile);
+#endif
+  xmlFreeDoc(doc);
+  return acl;
+}
+
+int GRSTxacmlFileIsAcl(char *pathandfile)
+/* Return 1 if filename in *pathandfile starts GRST_ACL_FILE
+   Return 0 otherwise. */
+{
+  char *filename;
+
+  filename = rindex(pathandfile, '/');
+  if (filename == NULL) filename = pathandfile;
+  else                  filename++;
+
+  return (strncmp(filename, GRST_ACL_FILE, sizeof(GRST_ACL_FILE) - 1) == 0);
+}
+
+char *GRSTxacmlFileFindAclname(char *pathandfile)
+/* Return malloc()ed ACL filename that governs the given file or directory
+   (for directories, the ACL file is in the directory itself), or NULL if none
+   can be found. */
+{
+  char        *path, *p;
+  struct stat  statbuf;
+
+  path = malloc(strlen(pathandfile) + sizeof(GRST_ACL_FILE) + 1);
+  strcpy(path, pathandfile);
+
+  if (stat(path, &statbuf) == 0)
+    {
+      if (!S_ISDIR(statbuf.st_mode)) /* can strip this / off straightaway */
+        {
+          p = rindex(path, '/');
+          if (p != NULL) *p = '\0';
+        }
+    }
+
+  while (path[0] != '\0')
+       {
+         strcat(path, "/");
+         strcat(path, GRST_ACL_FILE);
+
+         if (stat(path, &statbuf) == 0) return path;
+
+         p = rindex(path, '/');
+         *p = '\0';     /* strip off the / we added for ACL */
+
+         p = rindex(path, '/');
+         if (p == NULL) break; /* must start without / and we there now ??? */
+
+         *p = '\0';     /* strip off another layer of / */                 
+       }
+       
+  free(path);
+  return NULL;
+}
+
+GRSTgaclAcl *GRSTxacmlAclLoadforFile(char *pathandfile)
+/* Return ACL that governs the given file or directory (for directories,
+   the ACL file is in the directory itself.) */
+{
+  char        *path;
+  GRSTgaclAcl     *acl;
+
+  path = GRSTxacmlFileFindAclname(pathandfile);
+  
+  if (path != NULL)
+    {
+      acl = GRSTxacmlAclLoadFile(path);
+      free(path);
+      return acl;
+    }
+
+  return NULL;
+}
+
+
+
+/*                                                     *
+ * Functions to save ACL in XACML 1.1 compliant format *
+ * Functions based on method for saving to GACL format *
+ *                                                     */
+
+
+int GRSTxacmlCredPrint(GRSTgaclCred *cred, FILE *fp)
+/*
+   GRSTxacmlCredPrint - print a credential and any name-value pairs is contains in XACML form
+*/
+{
+  char              *q;
+  GRSTgaclNamevalue *p;
+
+  if (cred->firstname != NULL)
+    {
+
+      p = cred->firstname;
+
+      do {
+
+          fputs("\t\t\t\t<Subject>\n", fp);
+          fputs("\t\t\t\t\t<SubjectMatch MatchId=\"urn:oasis:names:tc:xacml:1.0:function:string-equal\">\n", fp);
+          fputs("\t\t\t\t\t\t<AttributeValue DataType=\"http://www.w3.org/2001/XMLSchema#string\">", fp);
+           for (q=p->value; *q != '\0'; ++q)
+              if      (*q == '<')  fputs("&lt;",   fp);
+              else if (*q == '>')  fputs("&gt;",   fp);
+              else if (*q == '&')  fputs("&amp;" , fp);
+              else if (*q == '\'') fputs("&apos;", fp);
+              else if (*q == '"')  fputs("&quot;", fp);
+              else                 fputc(*q, fp);
+
+
+          fputs("</AttributeValue>\n", fp);
+
+          fputs("\t\t\t\t\t\t<SubjectAttributeDesignator\n", fp);
+          fputs("\t\t\t\t\t\t\tAttributeId=", fp);
+          fprintf(fp, "\"%s\"\n", cred->type);
+          fputs("\t\t\t\t\t\t\tDataType=", fp);
+           fprintf(fp, "\"%s\"/>\n", p->name);
+          fputs("\t\t\t\t\t</SubjectMatch>\n", fp);
+          fputs("\t\t\t\t</Subject>\n", fp);
+           p = (GRSTgaclNamevalue *) p->next;
+         } while (p != NULL);
+
+    }
+    else fputs("\t\t\t\t<AnySubject/>\n", fp);
+
+  return 1;
+}
+
+
+int GRSTxacmlEntryPrint(GRSTgaclEntry *entry, FILE *fp, int rule_number)
+{
+  GRSTgaclCred  *cred;
+  GRSTgaclPerm  i;
+
+  if (entry->allowed){
+
+  fprintf(fp, "\t<Rule RuleId=\"Entry%dA\" Effect=\"Permit\">\n", rule_number);
+  fputs("\t\t<Target>\n", fp);
+  fputs("\t\t\t<Subjects>\n", fp);
+
+  for (cred = entry->firstcred; cred != NULL; cred = cred->next)
+                                            GRSTxacmlCredPrint(cred, fp);
+
+  fputs("\t\t\t</Subjects>\n", fp);
+  fputs("\t\t\t<Actions>\n", fp);
+
+      for (i=GRST_PERM_READ; i <= GRST_PERM_ADMIN; ++i)
+       if ((entry->allowed) & i) GRSTxacmlPermPrint(i, fp);
+
+  fputs("\t\t\t</Actions>\n", fp);
+  fputs("\t\t</Target>\n", fp);
+  fputs("\t</Rule>\n", fp);
+  }
+
+  if (entry->denied){
+
+  fprintf(fp, "\t<Rule RuleId=\"Entry%dD\" Effect=\"Deny\">\n", rule_number);
+  fputs("\t\t<Target>\n", fp);
+  fputs("\t\t\t<Subjects>\n", fp);
+
+  for (cred = entry->firstcred; cred != NULL; cred = cred->next)
+                                            GRSTxacmlCredPrint(cred, fp);
+
+  fputs("\t\t\t</Subjects>\n", fp);
+  fputs("\t\t\t<Actions>\n", fp);
+
+      for (i=GRST_PERM_READ; i <= GRST_PERM_ADMIN; ++i)
+       if (entry->denied & i) GRSTxacmlPermPrint(i, fp);
+
+  fputs("\t\t\t</Actions>\n", fp);
+  fputs("\t\t</Target>\n", fp);
+  fputs("\t</Rule>\n", fp);
+  }
+  return 1;
+}
+
+
+int GRSTxacmlPermPrint(GRSTgaclPerm perm, FILE *fp)
+{
+  GRSTgaclPerm i;
+
+  for (i=GRST_PERM_READ; grst_perm_syms[i] != NULL; ++i)
+       if (perm == grst_perm_vals[i])
+         {
+
+          fputs("\t\t\t\t<Action>\n", fp);
+          fputs("\t\t\t\t\t<ActionMatch MatchId=\"urn:oasis:names:tc:xacml:1.0:function:string-equal\">\n", fp);
+          fputs("\t\t\t\t\t\t<AttributeValue DataType=\"http://www.w3.org/2001/XMLSchema#string\">", fp);
+          fprintf(fp, "%s", grst_perm_syms[i]);
+          fputs("</AttributeValue>\n", fp);
+          fputs("\t\t\t\t\t\t<ActionAttributeDesignator\n", fp);
+          fputs("\t\t\t\t\t\t\tAttributeId=\"urn:oasis:names:tc:xacml:1.0:action:action-id\"\n", fp);
+          fputs("\t\t\t\t\t\t\tDataType=\"http://www.w3.org/2001/XMLSchema#string\"/>\n", fp);
+          fputs("\t\t\t\t\t</ActionMatch>\n", fp);
+          fputs("\t\t\t\t</Action>\n",fp);
+
+           return 1;
+         }
+
+  return 0;
+}
+
+int GRSTxacmlAclPrint(GRSTgaclAcl *acl, FILE *fp, char* dir_uri)
+{
+  GRSTgaclEntry *entry;
+  int rule_number=1;
+
+  fputs("<Policy", fp);
+  fputs("\txmlns=\"urn:oasis:names:tc:xacml:1.0:policy\"\n", fp);
+  fputs("\txmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n", fp);
+  fputs("\txsi:schemaLocation=\"urn:oasis:names:tc:xacml:1.0:policy cs-xacml-schema-policy-01.xsd\"\n", fp);
+  fputs("\tPolicyId=\"GridSitePolicy\"\n", fp);
+  fputs("\tRuleCombiningAlgId=\"urn:oasis:names:tc:xacml:1.0:rule-combining-algorithm:deny-overrides\">\n\n", fp);
+
+  fputs("\t<Target>\n\t\t<Resources>\n\t\t\t<Resource>\n", fp);
+  fputs("\t\t\t\t<ResourceMatch MatchId=\"urn:oasis:names:tc:xacml:1.0:function:string-equal\">\n", fp);
+  fputs("\t\t\t\t\t<AttributeValue DataType=\"http://www.w3.org/2001/XMLSchema#string\">", fp);
+  fprintf(fp, "%s", dir_uri);
+  fputs("</AttributeValue>\n", fp);
+  fputs("\t\t\t\t\t<ResourceAttributeDesignator\n", fp);
+  fputs("\t\t\t\t\t\tAttributeId=\"urn:oasis:names:tc:xacml:1.0:resource:resource-id\"\n", fp);
+  fputs("\t\t\t\t\t\tDataType=\"http://www.w3.org/2001/XMLSchema#string\"/>\n", fp);
+
+  fputs("\t\t\t\t</ResourceMatch>\n\t\t\t</Resource>\n\t\t</Resources>\n\t\t<Subjects>\n\t\t\t<AnySubject/>\n\t\t</Subjects>", fp);
+  fputs("\n\t\t<Actions>\n\t\t\t<AnyAction/>\n\t\t</Actions>\n\t</Target>\n\n", fp);
+
+  for (entry = acl->firstentry; entry != NULL; entry = entry->next){
+
+       GRSTxacmlEntryPrint(entry, fp, rule_number);
+       rule_number++;
+  }
+
+  fputs("</Policy>\n", fp);
+
+  return 1;
+}
+
+int GRSTxacmlAclSave(GRSTgaclAcl *acl, char *filename, char* dir_uri)
+{
+  int   ret;
+  FILE *fp;
+
+  fp = fopen(filename, "w");
+  if (fp == NULL) return 0;
+
+  fprintf(fp,"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
+
+  ret = GRSTxacmlAclPrint(acl, fp, dir_uri);
+
+  fclose(fp);
+
+  return ret;
+}
+
+
+
+
diff --git a/org.gridsite.core/src/xacmlexample.c b/org.gridsite.core/src/xacmlexample.c
new file mode 100644 (file)
index 0000000..07baafa
--- /dev/null
@@ -0,0 +1,148 @@
+/*
+   Copyright (c) 2002-3, Andrew McNab, University of Manchester
+   All rights reserved.
+
+   Redistribution and use in source and binary forms, with or
+   without modification, are permitted provided that the following
+   conditions are met:
+
+     o Redistributions of source code must retain the above
+       copyright notice, this list of conditions and the following
+       disclaimer. 
+     o Redistributions in binary form must reproduce the above
+       copyright notice, this list of conditions and the following
+       disclaimer in the documentation and/or other materials
+       provided with the distribution. 
+
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+   CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+   INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+   MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+   DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+   BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+   EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+   TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+   ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+   OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+   OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+   POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/*---------------------------------------------------------------*
+ * For more about GridSite: http://www.gridsite.org/             *
+ *---------------------------------------------------------------*/
+
+/*
+   Example program using XACML
+
+   Build with:
+   
+    gcc -o xacmlexample xacmlexample.c -L. -I. -lgridsite -lxml2 -lz -lm
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <gridsite.h>
+
+int main()
+{
+  GRSTgaclCred  *cred, *usercred;
+  GRSTgaclEntry *entry;
+  GRSTgaclAcl   *acl1, *acl2;
+  GRSTgaclUser  *user;
+  GRSTgaclPerm   perm0, perm1, perm2;
+  FILE          *fp;
+
+  /* must initialise GACL before using XACML functions */
+
+  GRSTgaclInit();
+
+  /* build up an ACL, starting with a credential */
+
+  cred = GRSTgaclCredNew("person");
+
+  GRSTgaclCredAddValue(cred, "dn", "/O=Grid/CN=Mr Grid Person");
+
+  /* create an entry to put it in */
+
+  entry = GRSTgaclEntryNew();
+
+  /* add the credential to it */
+
+  GRSTgaclEntryAddCred(entry, cred);
+
+  /* add another credential */
+
+  cred = GRSTgaclCredNew("dn-list");
+  GRSTgaclCredAddValue(cred, "url", "example-dn-list");
+  GRSTgaclEntryAddCred(entry, cred);
+
+  fp = fopen("example-dn-list", "w");
+  fputs("/O=Grid/CN=Mr Grid Person\n", fp);
+  fclose(fp);
+
+  /* associate some permissions and denials to the credential */
+
+  GRSTgaclEntryAllowPerm( entry, GRST_PERM_READ);
+  GRSTgaclEntryAllowPerm( entry, GRST_PERM_WRITE);
+  GRSTgaclEntryAllowPerm( entry, GRST_PERM_ADMIN);
+  GRSTgaclEntryDenyPerm(  entry, GRST_PERM_ADMIN);
+  GRSTgaclEntryDenyPerm(  entry, GRST_PERM_LIST);
+
+  perm0 = GRST_PERM_READ | GRST_PERM_WRITE;
+
+  printf("test perm should be %d\n", perm0);
+
+  /* create a new ACL and add the entry to it */
+
+  acl1 = GRSTgaclAclNew();
+
+  GRSTgaclAclAddEntry(acl1, entry);
+
+  /* create a GRSTgaclUser to compare with the ACL */
+
+  usercred = GRSTgaclCredNew("person");
+
+  GRSTgaclCredAddValue(usercred, "dn", "/O=Grid/CN=Mr Grid Person");
+
+  user = GRSTgaclUserNew(usercred);
+
+  GRSTgaclUserSetDNlists(user, getcwd(NULL, 0));
+  printf("DN Lists dir %s\n", getcwd(NULL, 0));
+
+//  putenv("GRST_DN_LISTS=.");
+
+  perm1 = GRSTgaclAclTestUser(acl1, user);
+
+  printf("test /O=Grid/CN=Mr Grid Person in acl = %d\n", perm1);
+
+  /* print and save the whole ACL */
+
+  GRSTgaclAclPrint(acl1, stdout);
+
+  GRSTxacmlAclSave(acl1, "example.gacl");
+
+  puts("gridacl.out saved");
+
+  puts("");
+
+  /* load the ACL back off the disk, print and test it */
+
+  acl2 = GRSTxacmlAclLoadFile("example.gacl");
+
+  puts("gridacl.out loaded");
+
+  if (acl2 != NULL) GRSTgaclAclPrint(acl2, stdout); else puts("acl2 is NULL");
+
+  perm2 = GRSTgaclAclTestUser(acl2, user);
+
+  printf("test /O=Grid/CN=Mr Grid Person in acl = %d\n", perm2);
+
+  if (perm1 != perm0) return 1;
+  if (perm2 != perm0) return 2;
+
+  return 0;
+}
+