grst_xacml.c

Go to the documentation of this file.
00001 /*
00002    Andrew McNab and Shiv Kaushal, University of Manchester.
00003    Copyright (c) 2002-3. 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.gridpp.ac.uk/gridsite/ *
00033  *------------------------------------------------------------------------*/
00034 
00035 #include <stdio.h>
00036 #include <stdlib.h>
00037 #include <sys/types.h>
00038 #include <sys/stat.h>
00039 #include <unistd.h>
00040 #include <string.h>
00041 #include <strings.h>
00042 #include <dirent.h>
00043 #include <ctype.h>
00044 
00045 #ifndef _GNU_SOURCE
00046 #define _GNU_SOURCE
00047 #endif
00048 #include <fnmatch.h>
00049 
00050 #include <libxml/xmlmemory.h>
00051 #include <libxml/tree.h>
00052 #include <libxml/parser.h>
00053 
00054 #include "gridsite.h"
00055 
00056 //#define XACML_DEBUG
00057 
00058 #ifdef XACML_DEBUG
00059   #define XACML_DEBUG_FILE "/tmp/grstxacmldebug.out"
00060 #endif
00061 
00062 
00063 /*                                                                      *
00064  * Global variables, shared by all GACL functions by private to libgacl *
00065  *                                                                      */
00066 
00067 extern char     *grst_perm_syms[];
00068 extern GRSTgaclPerm grst_perm_vals[];
00069 
00070 
00071 FILE* debugfile;
00072 
00073 GRSTgaclAcl *GRSTgaclAclParse(xmlDocPtr, xmlNodePtr, GRSTgaclAcl *);
00074 GRSTgaclAcl *GRSTxacmlAclParse(xmlDocPtr, xmlNodePtr, GRSTgaclAcl *);
00075 int          GRSTxacmlPermPrint(GRSTgaclPerm perm, FILE *fp);
00076 
00077 /*                                                     *
00078  * Functions to read in XACML 1.1 compliant format ACL *
00079  * Functions based on method for opening GACL format   *
00080  *                                                     */
00081 
00082 // need to check these for libxml memory leaks? - what needs to be freed?
00083 
00084 
00085 static GRSTgaclCred *GRSTxacmlCredParse(xmlNodePtr cur)
00086 /*
00087     GRSTxacmlCredParse - parse a credential stored in the libxml structure cur,
00088     returning it as a pointer or NULL on error.
00089 */
00090 {
00091   xmlNodePtr  attr_val;
00092   xmlNodePtr  attr_des;
00093   GRSTgaclCred   *cred;
00094 
00095   // cur points to <Subject> or <AnySubjects/>, loop done outside this function.
00096 
00097   if ( (xmlStrcmp(cur->name, (const xmlChar *) "AnySubject") == 0)) cred = GRSTgaclCredNew("any-user");
00098 
00099   else{
00100 
00101   attr_val=cur->xmlChildrenNode->xmlChildrenNode;
00102   attr_des=attr_val->next;
00103 
00104   cred = GRSTgaclCredNew((char *) xmlNodeGetContent(attr_des->properties->children));
00105 
00106   cred->next      = NULL;
00107 
00108   //Assumed that there is only one name/value pair per credential
00109   GRSTgaclCredAddValue(cred, (char *) xmlNodeGetContent(attr_des->properties->next->children),
00110                              (char *) xmlNodeGetContent(attr_val));
00111   }
00112 
00113   return cred;
00114 }
00115 
00116 static GRSTgaclEntry *GRSTxacmlEntryParse(xmlNodePtr cur)
00117 /*
00118     GRSTxacmlEntryParse - parse an entry stored in the libxml structure cur,
00119     returning it as a pointer or NULL on error. Also checks to see if the following
00120     <Rule> tag refers to the same <Target> by checking the <RuleId> of both
00121 */
00122 {
00123   int        i, check=0;
00124   xmlNodePtr cur2;
00125   xmlNodePtr rule_root=cur;
00126   GRSTgaclEntry *entry;
00127   GRSTgaclCred  *cred;
00128 
00129 
00130   // Next line not needed as function only called if <Rule> tag found
00131   // if (xmlStrcmp(cur->name, (const xmlChar *) "Rule") != 0) return NULL;
00132   // cur and rule_root point to the <Rule> tag
00133 
00134   cur = cur->xmlChildrenNode->xmlChildrenNode;
00135   // cur should now be pointing at <Subjects> tag
00136 #ifdef XACML_DEBUG
00137   fprintf (debugfile, "Starting to Parse Entry\n");
00138 #endif
00139   entry = GRSTgaclEntryNew();
00140 
00141   while (cur!=NULL){
00142 
00143     if (xmlStrcmp(cur->name, (const xmlChar *) "Subjects") == 0){
00144 #ifdef XACML_DEBUG
00145       fprintf (debugfile, "Starting to Parse Credentials\n");
00146 #endif
00147       if (check==0){
00148         // cur still pointing at <Subjects> tag make cur2 point to <Subject> and loop over them.
00149         cur2=cur->xmlChildrenNode;
00150         while (cur2!=NULL){
00151           if ( ((cred = GRSTxacmlCredParse(cur2)) != NULL) && (!GRSTgaclEntryAddCred(entry, cred))){
00152             GRSTgaclCredFree(cred);
00153             GRSTgaclEntryFree(entry);
00154             return NULL;
00155           }
00156           cur2=cur2->next;
00157         }
00158       }
00159     }
00160 
00161     else if (xmlStrcmp(cur->name, (const xmlChar *) "Actions") == 0){
00162 #ifdef XACML_DEBUG
00163       fprintf (debugfile, "Starting to Parse Permissions\n");
00164 #endif
00165       if (xmlStrcmp(xmlNodeGetContent(rule_root->properties->next->children), (const xmlChar *) "Permit") == 0 ){
00166 #ifdef XACML_DEBUG
00167         fprintf (debugfile, "\tPermit-ed actions: ");
00168 #endif
00169         for (cur2 = cur->xmlChildrenNode; cur2 != NULL; cur2=cur2->next) //cur2-><Action>
00170           for (i=0; grst_perm_syms[i] != NULL; ++i)
00171             if (xmlStrcmp(xmlNodeGetContent(cur2->xmlChildrenNode->xmlChildrenNode), (const xmlChar *) grst_perm_syms[i]) == 0)
00172             {
00173 #ifdef XACML_DEBUG
00174               fprintf (debugfile, "%s ", grst_perm_syms[i]);
00175 #endif
00176               GRSTgaclEntryAllowPerm(entry, grst_perm_vals[i]);
00177             }
00178       }
00179 
00180       if (xmlStrcmp(xmlNodeGetContent(rule_root->properties->next->children), (const xmlChar *) "Deny") == 0 ) {
00181 #ifdef XACML_DEBUG
00182         fprintf (debugfile, "\tDeny-ed actions: ");
00183 #endif
00184         for (cur2 = cur->xmlChildrenNode; cur2 != NULL; cur2=cur2->next) //cur2-><Action>
00185           for (i=0; grst_perm_syms[i] != NULL; ++i)
00186             if (xmlStrcmp(xmlNodeGetContent(cur2->xmlChildrenNode->xmlChildrenNode), (const xmlChar *) grst_perm_syms[i]) == 0)
00187             {
00188               
00189 #ifdef XACML_DEBUG
00190               fprintf (debugfile, "%s ", grst_perm_syms[i]);
00191 #endif
00192               GRSTgaclEntryDenyPerm(entry, grst_perm_vals[i]);
00193             }
00194       }
00195 
00196     }
00197     else{ // I cannot parse this - give up rather than get it wrong
00198 #ifdef XACML_DEBUG
00199       fprintf (debugfile, "OOOPSIE\n");
00200 #endif
00201       GRSTgaclEntryFree(entry);
00202       return NULL;
00203     }
00204 
00205     cur=cur->next;
00206 
00207     // Check if next Rule should be included when end of current rule reached
00208     // If RuleId are from the same entry (eg Entry1A and Entry1D)
00209     // make cur point to the next Rule's <Subjects> tag
00210     if (cur==NULL)
00211       if (check==0)
00212         if (rule_root->next!=NULL)
00213           if ( strncmp((const char*)xmlNodeGetContent(rule_root->properties->children), // RuleId of this Rule
00214                        (const char*)xmlNodeGetContent(rule_root->next->properties->children), // RuleId of next Rule
00215                  6) == 0){
00216 #ifdef XACML_DEBUG
00217             fprintf (debugfile, "End of perms and creds, next is %s \n", xmlNodeGetContent(rule_root->next->properties->children));
00218 #endif
00219             rule_root=rule_root->next;
00220             cur=rule_root->xmlChildrenNode->xmlChildrenNode;
00221 #ifdef XACML_DEBUG
00222             fprintf (debugfile, "skipped to <%s> tag of next Rule\n", cur->name);
00223 #endif
00224             check++;
00225           }
00226   }
00227 
00228   return entry;
00229 }
00230 
00231 GRSTgaclAcl *GRSTxacmlAclLoadFile(char *filename)
00232 {
00233   xmlDocPtr   doc;
00234   xmlNodePtr  cur;
00235   GRSTgaclAcl    *acl=NULL;
00236 
00237   doc = xmlParseFile(filename);
00238   if (doc == NULL) return NULL;
00239 
00240   cur = xmlDocGetRootElement(doc);
00241   if (cur == NULL) return NULL;
00242 
00243   if (!xmlStrcmp(cur->name, (const xmlChar *) "Policy")) { acl=GRSTxacmlAclParse(doc, cur, acl);}
00244   else if (!xmlStrcmp(cur->name, (const xmlChar *) "gacl")) {acl=GRSTgaclAclParse(doc, cur, acl);}
00245   else /* ACL format not recognised */
00246     {
00247       xmlFreeDoc(doc);
00248       free(cur);
00249       return NULL;
00250     }
00251 
00252   xmlFreeDoc(doc);
00253   return acl;
00254 }
00255 
00256 GRSTgaclAcl *GRSTxacmlAclParse(xmlDocPtr doc, xmlNodePtr cur, GRSTgaclAcl *acl)
00257 {
00258   GRSTgaclEntry  *entry;
00259 
00260   #ifdef XACML_DEBUG
00261   debugfile=fopen(XACML_DEBUG_FILE, "w");
00262   fprintf (debugfile, "ACL loaded..\n");
00263   fprintf (debugfile, "Parsing XACML\n");
00264   #endif
00265 
00266   // Have an XACML policy file.
00267   // Skip <Target> tag and set cur to first <Rule> tag
00268   cur = cur->xmlChildrenNode->next;
00269 
00270   acl = GRSTgaclAclNew();
00271 
00272   while (cur != NULL){
00273 
00274     if ( !xmlStrcmp(cur->name, (const xmlChar *)"Rule") )
00275     { // IF statement not needed?
00276       #ifdef XACML_DEBUG
00277       fprintf (debugfile, "Rule %s found\n", xmlNodeGetContent(cur->properties->children) );
00278       fprintf (debugfile, "Parsing Entry for this rule\n");
00279       #endif
00280       entry = GRSTxacmlEntryParse(cur);
00281 
00282       if (entry == NULL)
00283       {
00284         GRSTgaclAclFree(acl);
00285         return NULL;
00286       }
00287       else GRSTgaclAclAddEntry(acl, entry);
00288 
00289       #ifdef XACML_DEBUG
00290       fprintf (debugfile, "Entry read in\n\n");
00291       #endif
00292     }
00293 
00294     // If the current and next Rules are part of the same entry then advance two Rules
00295     // If not then advance 1
00296     if (cur->next != NULL)
00297     {
00298       if ( strncmp((const char*)xmlNodeGetContent(cur->properties->children),       // RuleId of this Rule
00299                    (const char*)xmlNodeGetContent(cur->next->properties->children), // RuleId of next Rule
00300                    6) == 0)
00301       {
00302         #ifdef XACML_DEBUG
00303         fprintf (debugfile, "skipping next rule %s, should have been caught previously\n\n", xmlNodeGetContent(cur->next->properties->children) );
00304         #endif
00305         cur=cur->next;
00306       } // Check first 6 characters i.e. Entry1**/
00307     }
00308 
00309     cur=cur->next;
00310 
00311   }
00312 
00313   #ifdef XACML_DEBUG
00314   fprintf (debugfile, "Finished loading ACL - Fanfare!\n");
00315   fclose(debugfile);
00316   #endif
00317 
00318   return acl;
00319 }
00320 
00321 
00322 int GRSTxacmlFileIsAcl(char *pathandfile)
00323 /* Return 1 if filename in *pathandfile starts GRST_ACL_FILE
00324    Return 0 otherwise. */
00325 {
00326   char *filename;
00327 
00328   filename = rindex(pathandfile, '/');
00329   if (filename == NULL) filename = pathandfile;
00330   else                  filename++;
00331 
00332   return (strncmp((const char*)filename, GRST_ACL_FILE, sizeof(GRST_ACL_FILE) - 1) == 0);
00333 }
00334 
00335 char *GRSTxacmlFileFindAclname(char *pathandfile)
00336 /* Return malloc()ed ACL filename that governs the given file or directory
00337    (for directories, the ACL file is in the directory itself), or NULL if none
00338    can be found. */
00339 {
00340   char        *path, *p;
00341   struct stat  statbuf;
00342 
00343   path = malloc(strlen(pathandfile) + sizeof(GRST_ACL_FILE) + 1);
00344   strcpy(path, pathandfile);
00345 
00346   if (stat(path, &statbuf) == 0)
00347     {
00348       if (!S_ISDIR(statbuf.st_mode)) /* can strip this / off straightaway */
00349         {
00350           p = rindex(path, '/');
00351           if (p != NULL) *p = '\0';
00352         }
00353     }
00354 
00355   while (path[0] != '\0')
00356        {
00357          strcat(path, "/");
00358          strcat(path, GRST_ACL_FILE);
00359 
00360          if (stat(path, &statbuf) == 0) return path;
00361 
00362          p = rindex(path, '/');
00363          *p = '\0';     /* strip off the / we added for ACL */
00364 
00365          p = rindex(path, '/');
00366          if (p == NULL) break; /* must start without / and we there now ??? */
00367 
00368          *p = '\0';     /* strip off another layer of / */                 
00369        }
00370        
00371   free(path);
00372   return NULL;
00373 }
00374 
00375 GRSTgaclAcl *GRSTxacmlAclLoadforFile(char *pathandfile)
00376 /* Return ACL that governs the given file or directory (for directories,
00377    the ACL file is in the directory itself.) */
00378 {
00379   char        *path;
00380   GRSTgaclAcl     *acl;
00381 
00382   path = GRSTxacmlFileFindAclname(pathandfile);
00383   
00384   if (path != NULL)
00385     {
00386       acl = GRSTxacmlAclLoadFile(path);
00387       free(path);
00388       return acl;
00389     }
00390 
00391   return NULL;
00392 }
00393 
00394 
00395 
00396 /*                                                     *
00397  * Functions to save ACL in XACML 1.1 compliant format *
00398  * Functions based on method for saving to GACL format *
00399  *                                                     */
00400 
00401 
00402 int GRSTxacmlCredPrint(GRSTgaclCred *cred, FILE *fp)
00403 /*
00404    GRSTxacmlCredPrint - print a credential and any name-value pairs is contains in XACML form
00405 */
00406 {
00407   char *q;
00408 
00409   if (cred->auri != NULL)
00410     {
00411            fputs("\t\t\t\t<Subject>\n", fp);
00412            fputs("\t\t\t\t\t<SubjectMatch MatchId=\"urn:oasis:names:tc:xacml:1.0:function:string-equal\">\n", fp);
00413            fputs("\t\t\t\t\t\t<AttributeValue DataType=\"http://www.w3.org/2001/XMLSchema#string\">", fp);
00414            for (q=cred->auri; *q != '\0'; ++q)
00415               if      (*q == '<')  fputs("&lt;",   fp);
00416               else if (*q == '>')  fputs("&gt;",   fp);
00417               else if (*q == '&')  fputs("&amp;" , fp);
00418               else if (*q == '\'') fputs("&apos;", fp);
00419               else if (*q == '"')  fputs("&quot;", fp);
00420               else                 fputc(*q, fp);
00421 
00422 
00423            fputs("</AttributeValue>\n", fp);
00424 
00425            fputs("\t\t\t\t\t\t<SubjectAttributeDesignator\n", fp);
00426            fputs("\t\t\t\t\t\t\tAttributeId=", fp);
00427            fprintf(fp, "\"cred\"\n");
00428            fputs("\t\t\t\t\t\t\tDataType=", fp);
00429            fprintf(fp, "\"auri\"/>\n");
00430            fputs("\t\t\t\t\t</SubjectMatch>\n", fp);
00431            fputs("\t\t\t\t</Subject>\n", fp);
00432     }
00433     else fputs("\t\t\t\t<AnySubject/>\n", fp);
00434 
00435   return 1;
00436 }
00437 
00438 
00439 int GRSTxacmlEntryPrint(GRSTgaclEntry *entry, FILE *fp, int rule_number)
00440 {
00441   GRSTgaclCred  *cred;
00442   GRSTgaclPerm  i;
00443 
00444   if (entry->allowed){
00445 
00446   fprintf(fp, "\t<Rule RuleId=\"Entry%dA\" Effect=\"Permit\">\n", rule_number);
00447   fputs("\t\t<Target>\n", fp);
00448   fputs("\t\t\t<Subjects>\n", fp);
00449 
00450   for (cred = entry->firstcred; cred != NULL; cred = cred->next)
00451                                             GRSTxacmlCredPrint(cred, fp);
00452 
00453   fputs("\t\t\t</Subjects>\n", fp);
00454   fputs("\t\t\t<Actions>\n", fp);
00455 
00456       for (i=GRST_PERM_READ; i <= GRST_PERM_ADMIN; ++i)
00457        if ((entry->allowed) & i) GRSTxacmlPermPrint(i, fp);
00458 
00459   fputs("\t\t\t</Actions>\n", fp);
00460   fputs("\t\t</Target>\n", fp);
00461   fputs("\t</Rule>\n", fp);
00462   }
00463 
00464   if (entry->denied){
00465 
00466   fprintf(fp, "\t<Rule RuleId=\"Entry%dD\" Effect=\"Deny\">\n", rule_number);
00467   fputs("\t\t<Target>\n", fp);
00468   fputs("\t\t\t<Subjects>\n", fp);
00469 
00470   for (cred = entry->firstcred; cred != NULL; cred = cred->next)
00471                                             GRSTxacmlCredPrint(cred, fp);
00472 
00473   fputs("\t\t\t</Subjects>\n", fp);
00474   fputs("\t\t\t<Actions>\n", fp);
00475 
00476       for (i=GRST_PERM_READ; i <= GRST_PERM_ADMIN; ++i)
00477        if (entry->denied & i) GRSTxacmlPermPrint(i, fp);
00478 
00479   fputs("\t\t\t</Actions>\n", fp);
00480   fputs("\t\t</Target>\n", fp);
00481   fputs("\t</Rule>\n", fp);
00482   }
00483   return 1;
00484 }
00485 
00486 
00487 int GRSTxacmlPermPrint(GRSTgaclPerm perm, FILE *fp)
00488 {
00489   GRSTgaclPerm i;
00490 
00491   for (i=GRST_PERM_READ; grst_perm_syms[i] != NULL; ++i)
00492        if (perm == grst_perm_vals[i])
00493          {
00494 
00495            fputs("\t\t\t\t<Action>\n", fp);
00496            fputs("\t\t\t\t\t<ActionMatch MatchId=\"urn:oasis:names:tc:xacml:1.0:function:string-equal\">\n", fp);
00497            fputs("\t\t\t\t\t\t<AttributeValue DataType=\"http://www.w3.org/2001/XMLSchema#string\">", fp);
00498            fprintf(fp, "%s", grst_perm_syms[i]);
00499            fputs("</AttributeValue>\n", fp);
00500            fputs("\t\t\t\t\t\t<ActionAttributeDesignator\n", fp);
00501            fputs("\t\t\t\t\t\t\tAttributeId=\"urn:oasis:names:tc:xacml:1.0:action:action-id\"\n", fp);
00502            fputs("\t\t\t\t\t\t\tDataType=\"http://www.w3.org/2001/XMLSchema#string\"/>\n", fp);
00503            fputs("\t\t\t\t\t</ActionMatch>\n", fp);
00504            fputs("\t\t\t\t</Action>\n",fp);
00505 
00506            return 1;
00507          }
00508 
00509   return 0;
00510 }
00511 
00512 int GRSTxacmlAclPrint(GRSTgaclAcl *acl, FILE *fp, char* dir_uri)
00513 {
00514   GRSTgaclEntry *entry;
00515   int rule_number=1;
00516 
00517   fputs("<Policy", fp);
00518   fputs("\txmlns=\"urn:oasis:names:tc:xacml:1.0:policy\"\n", fp);
00519   fputs("\txmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n", fp);
00520   fputs("\txsi:schemaLocation=\"urn:oasis:names:tc:xacml:1.0:policy cs-xacml-schema-policy-01.xsd\"\n", fp);
00521   fputs("\tPolicyId=\"GridSitePolicy\"\n", fp);
00522   fputs("\tRuleCombiningAlgId=\"urn:oasis:names:tc:xacml:1.0:rule-combining-algorithm:deny-overrides\">\n\n", fp);
00523 
00524   fputs("\t<Target>\n\t\t<Resources>\n\t\t\t<Resource>\n", fp);
00525   fputs("\t\t\t\t<ResourceMatch MatchId=\"urn:oasis:names:tc:xacml:1.0:function:string-equal\">\n", fp);
00526   fputs("\t\t\t\t\t<AttributeValue DataType=\"http://www.w3.org/2001/XMLSchema#string\">", fp);
00527   fprintf(fp, "%s", dir_uri);
00528   fputs("</AttributeValue>\n", fp);
00529   fputs("\t\t\t\t\t<ResourceAttributeDesignator\n", fp);
00530   fputs("\t\t\t\t\t\tAttributeId=\"urn:oasis:names:tc:xacml:1.0:resource:resource-id\"\n", fp);
00531   fputs("\t\t\t\t\t\tDataType=\"http://www.w3.org/2001/XMLSchema#string\"/>\n", fp);
00532 
00533   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);
00534   fputs("\n\t\t<Actions>\n\t\t\t<AnyAction/>\n\t\t</Actions>\n\t</Target>\n\n", fp);
00535 
00536   for (entry = acl->firstentry; entry != NULL; entry = entry->next){
00537 
00538         GRSTxacmlEntryPrint(entry, fp, rule_number);
00539         rule_number++;
00540   }
00541 
00542   fputs("</Policy>\n", fp);
00543 
00544   return 1;
00545 }
00546 
00547 int GRSTxacmlAclSave(GRSTgaclAcl *acl, char *filename, char* dir_uri)
00548 {
00549   int   ret;
00550   FILE *fp;
00551 
00552   fp = fopen(filename, "w");
00553   if (fp == NULL) return 0;
00554 
00555   fprintf(fp,"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
00556 
00557   ret = GRSTxacmlAclPrint(acl, fp, dir_uri);
00558 
00559   fclose(fp);
00560 
00561   return ret;
00562 }
00563 
00564 
00565 
00566 

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