2
Copyright (C) 2003-2004 Douglas Thain and the University of Wisconsin
3
Copyright (C) 2005- The University of Notre Dame
4
This software is distributed under the GNU General Public License.
5
See the file COPYING for details.
9
#include "chirp_filesystem.h"
10
#include "chirp_group.h"
11
#include "chirp_protocol.h"
12
#include "chirp_ticket.h"
15
#include "hash_table.h"
17
#include "stringtools.h"
26
#include <sys/types.h>
33
/* Cygwin does not have 64-bit I/O, while Darwin has it by default. */
35
#if CCTOOLS_OPSYS_CYGWIN || CCTOOLS_OPSYS_DARWIN || CCTOOLS_OPSYS_FREEBSD
42
#define fseeko64 fseeko
43
#define ftruncate64 ftruncate
44
#define truncate64 truncate
45
#define statfs64 statfs
46
#define fstatfs64 fstatfs
49
#define unsigned_isspace(c) isspace((unsigned char) c)
51
#if CCTOOLS_OPSYS_DARWIN
55
static int read_only_mode = 0;
56
static const char *default_acl=0;
58
extern const char *chirp_super_user;
60
static int do_stat( const char *filename, struct chirp_stat *buf )
64
result = cfs->stat(filename,buf);
65
} while( result==-1 && errno==EINTR );
75
struct chirp_ticket_rights {
81
static int readquote (const char **buffer, const char **s, size_t *l)
83
while (unsigned_isspace(**buffer)) (*buffer)++;
84
if (**buffer != '"') return 0;
88
while (**buffer != '"' && **buffer != '\0') {
92
if (**buffer != '"') return 0;
97
static void ticket_free (struct chirp_ticket *ct)
102
while (n < ct->nrights) {
103
free(ct->rights[n].directory);
109
static int ticket_write (const char *fname, struct chirp_ticket *ct)
112
CHIRP_FILE *ticketfile = cfs_fopen(fname, "w");
113
if (!ticketfile) return 0;
115
cfs_fprintf(ticketfile,"subject \"%s\"\n",ct->subject);
116
cfs_fprintf(ticketfile,"ticket \"%s\"\n",ct->ticket);
117
cfs_fprintf(ticketfile,"expiration \"%lu\"\n",(unsigned long) ct->expiration);
118
for (n = 0; n < ct->nrights; n++) {
119
cfs_fprintf(ticketfile,"rights \"%s\" \"%s\"\n",ct->rights[n].directory,chirp_acl_flags_to_text(ct->rights[n].acl));
122
cfs_fflush(ticketfile);
123
int result = cfs_ferror(ticketfile);
128
cfs_fclose(ticketfile);
132
static int ticket_read (const char *fname, struct chirp_ticket *ct)
138
CHIRP_FILE *ticketfile = cfs_fopen(fname, "r");
139
if (!ticketfile) return 0;
140
if (!cfs_freadall(ticketfile, &b, &l)) {
141
cfs_fclose(ticketfile);
144
cfs_fclose(ticketfile);
146
/* Ticket format (quoted strings may span multiple lines):
147
* subject "<subject>"
149
* expiration "<UTC seconds since Epoch>"
150
* rights "<directory>" "<acl>"
151
* rights "<directory>" "<acl>"
156
const char *buffer = b;
157
time_t now = time(NULL);
158
now = mktime(gmtime(&now)); /* convert to UTC */
161
ct->expiration = now; /* default expire now... */
162
ct->expired = 1; /* default is expired */
166
while (unsigned_isspace(*buffer)) buffer++;
167
if (strncmp(buffer, "subject", strlen("subject")) == 0) {
168
buffer += strlen("subject");
169
if (!readquote(&buffer, &s, &n)) break;
170
ct->subject = xxrealloc(ct->subject, n+1);
171
memcpy(ct->subject, s, n);
172
ct->subject[n] = '\0';
173
} else if (strncmp(buffer, "ticket", strlen("ticket")) == 0) {
174
buffer += strlen("ticket");
175
if (!readquote(&buffer, &s, &n)) break;
176
ct->ticket = xxrealloc(ct->ticket, n+1);
177
memcpy(ct->ticket, s, n);
178
ct->ticket[n] = '\0';
179
} else if (strncmp(buffer, "expiration", strlen("expiration")) == 0) {
180
buffer += strlen("expiration");
181
if (!readquote(&buffer, &s, &n)) break;
182
char *stime = xxmalloc(n+1);
185
ct->expiration = (time_t) strtoul(stime, NULL, 10);
186
ct->expired = (ct->expiration <= now);
188
} else if (strncmp(buffer, "rights", strlen("rights")) == 0) {
189
buffer += strlen("rights");
190
if (!readquote(&buffer, &s, &n)) break;
191
ct->rights = xxrealloc(ct->rights, sizeof(*ct->rights)*(++ct->nrights)+1);
192
ct->rights[ct->nrights-1].directory = xxmalloc(n+1);
193
memcpy(ct->rights[ct->nrights-1].directory, s, n);
194
ct->rights[ct->nrights-1].directory[n] = '\0';
195
if (!readquote(&buffer, &s, &n)) break;
196
char *acl = xxmalloc(n+1);
199
ct->rights[ct->nrights-1].acl = chirp_acl_text_to_flags(acl);
201
} else if (*buffer == '\0') {
202
if (ct->subject && ct->ticket && ct->nrights > 0) {
210
if (ct->rights == NULL) {
211
assert(ct->nrights == 0);
212
ct->rights = xxrealloc(ct->rights, sizeof(*ct->rights)*(++ct->nrights)+1);
213
ct->rights[ct->nrights-1].directory = xstrdup("/");
214
ct->rights[ct->nrights-1].acl = CHIRP_ACL_ALL;
218
/* fprintf(stderr, "TICKET:\n\tsubject = %s\n\texpiration = %lu %lu %d\n\tticket = %s\n\trights[0] = %s %s\n", ct->subject, now, ct->expiration, ct->expired, ct->ticket, ct->rights[0].directory, chirp_acl_flags_to_text(ct->rights[0].acl)); */
219
return status && !ct->expired;
222
static void chirp_acl_ticket_name ( const char *root, const char *ticket, char *name, char *fname )
224
unsigned char digest[CHIRP_TICKET_DIGEST_LENGTH];
225
md5_context_t context;
227
md5_update(&context, (const unsigned char *) ticket, strlen(ticket));
228
md5_final(digest, &context);
229
strcpy(name, "ticket:");
230
strcat(name, md5_string(digest));
231
sprintf(fname,"%s/%s%s",root,CHIRP_TICKET_PREFIX,name);
234
void chirp_acl_force_readonly()
239
void chirp_acl_default( const char *d )
244
static int is_a_directory( const char *filename )
246
struct chirp_stat info;
248
if(do_stat(filename,&info)==0) {
249
if(S_ISDIR(info.cst_mode)) {
259
static void make_acl_name( const char *filename, int get_parent, char *aclname )
261
char tmp[CHIRP_PATH_MAX];
262
sprintf(tmp,"%s/%s",filename,CHIRP_ACL_BASE_NAME);
263
string_collapse_path(tmp,aclname,1);
267
do_chirp_acl_get returns the acl flags associated with a subject and directory.
268
If the subject has rights there, they are returned and errno is undefined.
269
If the directory exists, but the subject has no rights, returns zero with errno=0.
270
If the rights cannot be obtained, returns zero with errno set appropriately.
273
static int do_chirp_acl_get( const char *root, const char *dirname, const char *subject, int *totalflags )
276
char aclsubject[CHIRP_LINE_MAX];
282
/* if the subject is a ticket, then we need the rights we have for the
283
* directory along with the rights of the subject in that directory
286
if (chirp_ticket_isticketsubject(subject, &digest)) {
287
/* open the ticket file, read the public key */
288
char ticketfilename[CHIRP_PATH_MAX];
289
struct chirp_ticket ct;
290
strcpy(ticketfilename, CHIRP_TICKET_PREFIX);
291
strcat(ticketfilename, subject);
292
if (!ticket_read(ticketfilename, &ct)) return 0;
293
if (!do_chirp_acl_get(root, dirname, ct.subject, totalflags)) {
300
for (i = 0; i < ct.nrights; i++) {
301
char safewhere[CHIRP_PATH_MAX];
302
char where[CHIRP_PATH_MAX];
303
sprintf(safewhere, "%s/%s", root, ct.rights[i].directory);
304
string_collapse_path(safewhere, where, 1);
306
if (strncmp(dirname, where, strlen(where)) == 0) {
307
if (strlen(where) > longest) {
308
longest = strlen(where);
309
mask = ct.rights[i].acl;
315
aclfile = chirp_acl_open(dirname);
317
while(chirp_acl_read(aclfile,aclsubject,&aclflags)) {
318
if(string_match(aclsubject,subject)) {
319
*totalflags |= aclflags;
320
} else if(!strncmp(aclsubject,"group:",6)) {
321
if(chirp_group_lookup(aclsubject,subject)) {
322
*totalflags |= aclflags;
326
chirp_acl_close(aclfile);
333
*totalflags &= CHIRP_ACL_READ|CHIRP_ACL_LIST;
340
int chirp_acl_check_dir( const char *root, const char *dirname, const char *subject, int flags )
344
if (!do_chirp_acl_get(root,dirname,subject,&myflags))
347
/* The superuser can implicitly list and admin */
349
if(chirp_super_user && !strcmp(subject,chirp_super_user)) {
350
myflags |= CHIRP_ACL_LIST|CHIRP_ACL_ADMIN;
353
if( ( flags & myflags ) == flags ) {
361
static int do_chirp_acl_check( const char *root, const char *filename, const char *subject, int flags, int follow_links )
363
char linkname[CHIRP_PATH_MAX];
364
char temp[CHIRP_PATH_MAX];
365
char dirname[CHIRP_PATH_MAX];
368
Symbolic links require special handling.
369
If requested, follow the link and look for rights in that directory.
372
if(follow_links && flags!=CHIRP_ACL_DELETE) {
373
int length = cfs->readlink(filename,linkname,sizeof(linkname));
375
linkname[length] = 0;
377
/* If the link is relative, construct a full path */
379
if(linkname[0]!='/') {
380
sprintf(temp,"%s/../%s",filename,linkname);
381
string_collapse_path(temp,linkname,1);
384
/* Use the linkname now to look up the ACL */
386
debug(D_DEBUG,"symlink %s points to %s",filename,linkname);
392
If the file being checked is an ACL file,
393
then it may be written with the admin flag, but never deleted.
396
if(!strcmp(string_back(filename,CHIRP_ACL_BASE_LENGTH),CHIRP_ACL_BASE_NAME)) {
397
if(flags&CHIRP_ACL_DELETE) {
401
if(flags&CHIRP_ACL_WRITE) {
402
flags &= ~CHIRP_ACL_WRITE;
403
flags |= CHIRP_ACL_ADMIN;
407
/* Now get the name of the directory containing the file */
409
string_collapse_path(filename,temp,1);
410
if(!is_a_directory(temp))
411
string_dirname(temp,dirname);
413
strcpy(dirname,temp);
415
/* Perform the permissions check on that directory. */
417
return chirp_acl_check_dir(root,dirname,subject,flags);
420
int chirp_acl_check( const char *root, const char *filename, const char *subject, int flags )
422
return do_chirp_acl_check(root,filename,subject,flags,1);
425
int chirp_acl_check_link( const char *root, const char *filename, const char *subject, int flags )
427
return do_chirp_acl_check(root,filename,subject,flags,0);
430
int chirp_acl_gettickets (const char *dirname, struct hash_table *ticket)
432
if (!is_a_directory(dirname)) {
440
dir = cfs->opendir(dirname);
444
while ((entry = cfs->readdir(dir))) {
445
char path[CHIRP_PATH_MAX];
446
if (!strcmp(entry, ".")) continue;
447
if (!strcmp(entry, "..")) continue;
448
sprintf(path,"%s/%s", dirname, entry);
450
if (strncmp(entry, CHIRP_TICKET_PREFIX, CHIRP_TICKET_PREFIX_LENGTH) == 0 && chirp_ticket_isticketsubject(entry+CHIRP_TICKET_PREFIX_LENGTH, &digest)) {
451
/* open the ticket file, read the public key */
452
struct chirp_ticket ct;
453
if (!ticket_read(path, &ct)) continue;
454
debug(D_CHIRP, "adding %s to known tickets", digest);
455
hash_table_insert(ticket, digest, xstrdup(ct.ticket));
463
int chirp_acl_ticket_delete( const char *root, const char *subject, const char *ticket_subject )
465
char ticket_file[CHIRP_PATH_MAX];
468
struct chirp_ticket ct;
471
if (!chirp_ticket_isticketsubject(ticket_subject,&digest)) {
475
if (!chirp_acl_whoami(subject, &esubject)) return -1;
477
sprintf(ticket_file,"%s/%s%s",root,CHIRP_TICKET_PREFIX,ticket_subject);
479
if (!ticket_read(ticket_file, &ct)) {
484
if (strcmp(esubject,ct.subject) == 0 || strcmp(chirp_super_user, subject) == 0) {
485
status = cfs->unlink(ticket_file);
495
int chirp_acl_ticket_get (const char *root, const char *subject, const char *ticket_subject, char **ticket_esubject, char **ticket, time_t *ticket_expiration, char ***ticket_rights)
498
if (!chirp_acl_whoami(subject, &esubject)) return -1;
501
if (!chirp_ticket_isticketsubject(ticket_subject,&digest)) {
506
struct chirp_ticket ct;
507
char ticket_file[CHIRP_PATH_MAX];
508
sprintf(ticket_file,"%s/%s%s",root,CHIRP_TICKET_PREFIX,ticket_subject);
509
if (!ticket_read(ticket_file, &ct)) {
514
if (strcmp(ct.subject, subject) == 0 || strcmp(subject, chirp_super_user) == 0) {
515
*ticket_esubject = xstrdup(ct.subject);
516
*ticket = xstrdup(ct.ticket);
520
now = mktime(gmtime(&now)); /* convert to UTC */
521
*ticket_expiration = ct.expiration-now;
524
*ticket_rights = (char **) xxmalloc(sizeof(char *)*2*(ct.nrights+1));
525
for (n = 0; n < ct.nrights; n++) {
526
(*ticket_rights)[n*2+0] = xstrdup(ct.rights[n].directory);
527
(*ticket_rights)[n*2+1] = xstrdup(chirp_acl_flags_to_text(ct.rights[n].acl));
529
(*ticket_rights)[n*2+0] = NULL;
530
(*ticket_rights)[n*2+1] = NULL;
543
int chirp_acl_ticket_list (const char *root, const char *subject, char ***ticket_subjects)
546
*ticket_subjects = NULL;
550
dir = cfs->opendir(root);
551
if (dir == NULL) return -1;
553
while ((entry = cfs->readdir(dir))) {
554
if (strcmp(entry, ".") == 0 || strcmp(entry, "..") == 0) continue;
555
char path[CHIRP_PATH_MAX];
556
sprintf(path,"%s/%s", root, entry);
558
if (strncmp(entry, CHIRP_TICKET_PREFIX, CHIRP_TICKET_PREFIX_LENGTH) == 0 && chirp_ticket_isticketsubject(entry+CHIRP_TICKET_PREFIX_LENGTH, &digest)) {
559
struct chirp_ticket ct;
560
if (!ticket_read(path, &ct)) continue; /* expired? */
561
if (strcmp(subject, ct.subject) == 0 || strcmp(subject, "all") == 0) {
563
*ticket_subjects = (char **) xxrealloc(*ticket_subjects, (n+1)*sizeof(char *));
564
(*ticket_subjects)[n-1] = xstrdup(entry+CHIRP_TICKET_PREFIX_LENGTH);
565
(*ticket_subjects)[n] = NULL;
575
int chirp_acl_gctickets (const char *root)
580
dir = cfs->opendir(root);
584
while ((entry = cfs->readdir(dir))) {
586
if (strncmp(entry, CHIRP_TICKET_PREFIX, CHIRP_TICKET_PREFIX_LENGTH) == 0 && chirp_ticket_isticketsubject(entry+CHIRP_TICKET_PREFIX_LENGTH, &digest)) {
587
/* open the ticket file, read the public key */
588
struct chirp_ticket ct;
589
char path[CHIRP_PATH_MAX];
590
sprintf(path, "%s/%s", root, entry);
591
if (ticket_read(path, &ct)) {
595
debug(D_CHIRP, "ticket %s expired (or corrupt), garbage collecting", digest);
603
int chirp_acl_ticket_create ( const char *root, const char *subject, const char *newsubject, const char *ticket, const char *duration)
605
time_t now; /*, delta; */
606
time_t offset = (time_t) strtoul(duration, NULL, 10);
608
char ticket_name[CHIRP_PATH_MAX];
609
char ticket_file[CHIRP_PATH_MAX];
610
char expiration[128];
613
now = mktime(gmtime(&now)); /* convert to UTC */
614
sprintf(expiration, "%lu", (unsigned long) (now+offset));
616
/* Note about tickets making tickets:
617
* A ticket created by a ticket authenticated user has the same effective
618
* subject (see the ticket_register RPC in chirp_server.c). Also, the
619
* expiration time is less than or equal to the expiration time of the
620
* ticket used to authenticate.
622
if (chirp_ticket_isticketsubject(subject,&digest)) {
623
struct chirp_ticket ct;
624
sprintf(ticket_file,"%s/%s%s",root,CHIRP_TICKET_PREFIX,subject);
625
if (!ticket_read(ticket_file, &ct)) return -1;
626
if (ct.expiration < now+offset) {
627
sprintf(expiration, "%lu", (unsigned long) ct.expiration);
632
if(!is_a_directory(root)) {
637
chirp_acl_ticket_name(root,ticket,ticket_name,ticket_file);
639
CHIRP_FILE *f = cfs_fopen(ticket_file,"w");
644
cfs_fprintf(f,"subject \"%s\"\n",newsubject);
645
cfs_fprintf(f,"expiration \"%s\"\n",expiration);
646
cfs_fprintf(f,"ticket \"%s\"\n",ticket);
647
cfs_fprintf(f,"rights \"/\" \"\"\n");
650
int result = cfs_ferror(f);
659
int chirp_acl_ticket_modify ( const char *root, const char *subject, const char *ticket_subject, const char *path, int flags )
661
char ticket_file[CHIRP_PATH_MAX];
664
struct chirp_ticket ct;
667
if (!chirp_ticket_isticketsubject(ticket_subject,&digest)) {
671
/* Note about tickets making tickets:
672
* We check whether the ticket has the rights associated with the mask in
673
* the next line. So, a ticket can only make a ticket with rights it
676
if (!chirp_acl_check_dir(root,path,subject,flags)) return -1; /* you don't have the rights for the mask */
677
if (!chirp_acl_whoami(subject, &esubject)) return -1;
679
sprintf(ticket_file,"%s/%s%s",root,CHIRP_TICKET_PREFIX,ticket_subject);
681
if (!ticket_read(ticket_file, &ct)) {
686
if (strcmp(esubject,ct.subject) == 0 || strcmp(chirp_super_user, subject) == 0) {
689
for (n = 0; n < ct.nrights; n++) {
690
char safewhere[CHIRP_PATH_MAX];
691
char where[CHIRP_PATH_MAX];
692
sprintf(safewhere, "%s/%s", root, ct.rights[n].directory);
693
string_collapse_path(safewhere, where, 1);
695
if (strcmp(where, path) == 0) {
696
ct.rights[n].acl = flags; /* replace old acl mask */
701
assert(strlen(path) >= strlen(root));
702
ct.rights = xxrealloc(ct.rights, sizeof(*ct.rights)*(++ct.nrights)+1);
703
char directory[CHIRP_PATH_MAX];
704
char collapsed_directory[CHIRP_PATH_MAX];
705
sprintf(directory, "/%s", path+strlen(root));
706
string_collapse_path(directory, collapsed_directory, 1);
707
ct.rights[ct.nrights-1].directory = xstrdup(collapsed_directory);
708
ct.rights[ct.nrights-1].acl = flags;
710
status = ticket_write(ticket_file, &ct);
720
int chirp_acl_whoami( const char *subject, char **esubject )
723
if (chirp_ticket_isticketsubject(subject, &digest)) {
724
/* open the ticket file */
725
struct chirp_ticket ct;
726
char ticketfilename[CHIRP_PATH_MAX];
727
strcpy(ticketfilename, CHIRP_TICKET_PREFIX);
728
strcat(ticketfilename, subject);
729
if (!ticket_read(ticketfilename, &ct)) return 0;
730
*esubject = xstrdup(ct.subject);
734
*esubject = xstrdup(subject);
739
int chirp_acl_set( const char *dirname, const char *subject, int flags, int reset_acl )
741
char aclname[CHIRP_PATH_MAX];
742
char newaclname[CHIRP_PATH_MAX];
743
char aclsubject[CHIRP_LINE_MAX];
745
CHIRP_FILE *aclfile, *newaclfile;
747
int replaced_acl_entry=0;
749
if(!is_a_directory(dirname)) {
754
sprintf(aclname,"%s/%s",dirname,CHIRP_ACL_BASE_NAME);
755
sprintf(newaclname,"%s/%s.%d",dirname,CHIRP_ACL_BASE_NAME,(int)getpid());
758
aclfile = cfs_fopen("/dev/null","r");
760
aclfile = cfs_fopen(aclname,"r");
762
/* If the acl never existed, then we can simply create it. */
763
if(!aclfile && errno==ENOENT) {
765
aclfile = cfs_fopen(default_acl,"r");
767
aclfile = cfs_fopen("/dev/null","r"); /* use local... */
777
replaced_acl_entry = 0;
779
newaclfile = cfs_fopen(newaclname,"w");
786
while(chirp_acl_read(aclfile,aclsubject,&aclflags)) {
787
if(!strcmp(subject,aclsubject)) {
789
replaced_acl_entry = 1;
792
cfs_fprintf(newaclfile,"%s %s\n",aclsubject,chirp_acl_flags_to_text(aclflags));
797
if(!replaced_acl_entry) {
798
cfs_fprintf(newaclfile,"%s %s\n",subject,chirp_acl_flags_to_text(flags));
801
/* Need to force a write in order to get response from ferror */
803
cfs_fflush(newaclfile);
804
result = cfs_ferror(newaclfile);
805
cfs_fclose(newaclfile);
811
result = cfs->rename(newaclname,aclname);
813
cfs->unlink(newaclname);
822
CHIRP_FILE *chirp_acl_open( const char *dirname )
824
char aclname[CHIRP_PATH_MAX];
827
if(!is_a_directory(dirname)) {
828
if (errno == ENOENT && default_acl) {
829
file = cfs_fopen(default_acl, "r");
832
else if (errno == ENOTDIR) /* component directory missing */
837
make_acl_name(dirname,0,aclname);
838
file = cfs_fopen(aclname,"r");
839
if(!file && default_acl) file = cfs_fopen(default_acl, "r");
844
int chirp_acl_read( CHIRP_FILE *aclfile, char *subject, int *flags )
846
char acl[CHIRP_LINE_MAX];
847
char tmp[CHIRP_LINE_MAX];
849
while(cfs_fgets(acl,sizeof(acl),aclfile)) {
850
if(sscanf(acl,"%[^ ] %[rwldpvax()]",subject,tmp)==2) {
851
*flags = chirp_acl_text_to_flags(tmp);
861
void chirp_acl_close( CHIRP_FILE *aclfile )
867
const char * chirp_acl_flags_to_text( int flags )
869
static char text[20];
873
if(flags&CHIRP_ACL_READ) strcat(text,"r");
874
if(flags&CHIRP_ACL_WRITE) strcat(text,"w");
875
if(flags&CHIRP_ACL_LIST) strcat(text,"l");
876
if(flags&CHIRP_ACL_DELETE) strcat(text,"d");
877
if(flags&CHIRP_ACL_PUT) strcat(text,"p");
878
if(flags&CHIRP_ACL_ADMIN) strcat(text,"a");
879
if(flags&CHIRP_ACL_EXECUTE) strcat(text,"x");
880
if(flags&CHIRP_ACL_RESERVE) {
883
if(flags&CHIRP_ACL_RESERVE_READ) strcat(text,"r");
884
if(flags&CHIRP_ACL_RESERVE_WRITE) strcat(text,"w");
885
if(flags&CHIRP_ACL_RESERVE_LIST) strcat(text,"l");
886
if(flags&CHIRP_ACL_RESERVE_DELETE) strcat(text,"d");
887
if(flags&CHIRP_ACL_RESERVE_PUT) strcat(text,"p");
888
if(flags&CHIRP_ACL_RESERVE_RESERVE) strcat(text,"v");
889
if(flags&CHIRP_ACL_RESERVE_ADMIN) strcat(text,"a");
890
if(flags&CHIRP_ACL_RESERVE_EXECUTE) strcat(text,"x");
901
int chirp_acl_text_to_flags( const char *t )
906
if( *t=='r' ) flags|=CHIRP_ACL_READ;
907
if( *t=='w' ) flags|=CHIRP_ACL_WRITE;
908
if( *t=='l' ) flags|=CHIRP_ACL_LIST;
909
if( *t=='d' ) flags|=CHIRP_ACL_DELETE;
910
if( *t=='p' ) flags|=CHIRP_ACL_PUT;
911
if( *t=='a' ) flags|=CHIRP_ACL_ADMIN;
912
if( *t=='x' ) flags|=CHIRP_ACL_EXECUTE;
914
flags |= CHIRP_ACL_RESERVE;
917
while(*t && *t != ')'){
918
if( *t=='r' ) flags|=CHIRP_ACL_RESERVE_READ;
919
if( *t=='w' ) flags|=CHIRP_ACL_RESERVE_WRITE;
920
if( *t=='l' ) flags|=CHIRP_ACL_RESERVE_LIST;
921
if( *t=='d' ) flags|=CHIRP_ACL_RESERVE_DELETE;
922
if( *t=='p' ) flags|=CHIRP_ACL_RESERVE_PUT;
923
if( *t=='v' ) flags|=CHIRP_ACL_RESERVE_RESERVE;
924
if( *t=='a' ) flags|=CHIRP_ACL_RESERVE_ADMIN;
925
if( *t=='x' ) flags|=CHIRP_ACL_RESERVE_EXECUTE;
936
int chirp_acl_from_access_flags( int flags )
939
if(flags&R_OK) acl|=CHIRP_ACL_READ;
940
if(flags&W_OK) acl|=CHIRP_ACL_WRITE;
941
if(flags&X_OK) acl|=CHIRP_ACL_EXECUTE;
942
if(flags&F_OK) acl|=CHIRP_ACL_READ;
943
if(acl==0) acl|=CHIRP_ACL_READ;
947
int chirp_acl_from_open_flags( int flags )
950
if(flags&O_WRONLY) acl|=CHIRP_ACL_WRITE;
951
if(flags&O_RDWR) acl|=CHIRP_ACL_READ|CHIRP_ACL_WRITE;
952
if(flags&O_CREAT) acl|=CHIRP_ACL_WRITE;
953
if(flags&O_TRUNC) acl|=CHIRP_ACL_WRITE;
954
if(flags&O_APPEND) acl|=CHIRP_ACL_WRITE;
955
if(acl==0) acl|=CHIRP_ACL_READ;
959
int chirp_acl_init_root( const char *path )
961
char aclpath[CHIRP_PATH_MAX];
962
char username[USERNAME_MAX];
965
file = chirp_acl_open(path);
967
chirp_acl_close(file);
971
username_get(username);
973
sprintf(aclpath,"%s/%s",path,CHIRP_ACL_BASE_NAME);
974
file = cfs_fopen(aclpath,"w");
976
cfs_fprintf(file,"unix:%s %s\n",username,chirp_acl_flags_to_text(CHIRP_ACL_READ|CHIRP_ACL_WRITE|CHIRP_ACL_DELETE|CHIRP_ACL_LIST|CHIRP_ACL_ADMIN));
984
int chirp_acl_init_copy( const char *path )
986
char oldpath[CHIRP_LINE_MAX];
987
char newpath[CHIRP_LINE_MAX];
988
char subject[CHIRP_LINE_MAX];
994
sprintf(oldpath,"%s/..",path);
995
sprintf(newpath,"%s/%s",path,CHIRP_ACL_BASE_NAME);
997
oldfile = chirp_acl_open(oldpath);
999
newfile = cfs_fopen(newpath,"w");
1001
while(chirp_acl_read(oldfile,subject,&flags)) {
1002
cfs_fprintf(newfile,"%s %s\n",subject,chirp_acl_flags_to_text(flags));
1004
cfs_fclose(newfile);
1007
chirp_acl_close(oldfile);
1013
int chirp_acl_init_reserve( const char *root, const char *path, const char *subject )
1015
char dirname[CHIRP_PATH_MAX];
1016
char aclpath[CHIRP_PATH_MAX];
1021
string_dirname(path,dirname);
1023
if (!do_chirp_acl_get(root,dirname,subject,&aclflags))
1026
if(aclflags&CHIRP_ACL_RESERVE_READ)
1027
newflags|=CHIRP_ACL_READ;
1028
if(aclflags&CHIRP_ACL_RESERVE_WRITE)
1029
newflags|=CHIRP_ACL_WRITE;
1030
if(aclflags&CHIRP_ACL_RESERVE_LIST)
1031
newflags|=CHIRP_ACL_LIST;
1032
if(aclflags&CHIRP_ACL_RESERVE_DELETE)
1033
newflags|=CHIRP_ACL_DELETE;
1034
if(aclflags&CHIRP_ACL_RESERVE_PUT)
1035
newflags|=CHIRP_ACL_PUT;
1036
if(aclflags&CHIRP_ACL_RESERVE_RESERVE)
1037
newflags|=CHIRP_ACL_RESERVE;
1038
if(aclflags&CHIRP_ACL_RESERVE_ADMIN)
1039
newflags|=CHIRP_ACL_ADMIN;
1040
if(aclflags&CHIRP_ACL_RESERVE_EXECUTE)
1041
newflags|=CHIRP_ACL_EXECUTE;
1045
If no sub-rights are associated with the v right,
1046
then give all of the ordinary subrights.
1049
if(newflags==0) newflags = CHIRP_ACL_READ|CHIRP_ACL_WRITE|CHIRP_ACL_LIST|CHIRP_ACL_DELETE|CHIRP_ACL_ADMIN;
1051
sprintf(aclpath,"%s/%s",path,CHIRP_ACL_BASE_NAME);
1052
file = cfs_fopen(aclpath,"w");
1054
cfs_fprintf(file,"%s %s\n",subject,chirp_acl_flags_to_text(newflags));
1062
static int delete_dir (const char *path)
1068
dir = cfs->opendir(path);
1070
if (errno == ENOTDIR)
1071
return cfs->unlink(path) == 0;
1073
return errno == ENOENT;
1075
while ((entry = cfs->readdir(dir))) {
1076
char subdir[PATH_MAX];
1077
if (!strcmp(entry, ".")) continue;
1078
if (!strcmp(entry, "..")) continue;
1079
sprintf(subdir,"%s/%s",path,entry);
1080
if(!delete_dir(subdir)) {
1085
return cfs->rmdir(path) == 0 ? result : 0;
1089
Because each directory now contains an ACL,
1090
a simple rmdir will not work on a (perceived) empty directory.
1091
This function checks to see if the directory is empty,
1092
save for the ACL file, and deletes it if so.
1093
Otherwise, it determines an errno and returns with failure.
1096
int chirp_acl_rmdir( const char *path )
1101
dir = cfs->opendir(path);
1103
while((d=cfs->readdir(dir))) {
1104
if(!strcmp(d,".")) continue;
1105
if(!strcmp(d,"..")) continue;
1106
if(!strcmp(d,CHIRP_ACL_BASE_NAME)) continue;