1 |
|
|
2 |
/* Copyright (C) 1999 Beau Kuiper |
/* Copyright (C) 1999 Beau Kuiper |
3 |
|
|
4 |
This program is free software; you can redistribute it and/or modify |
This program is free software; you can redistribute it and/or modify |
21 |
ACLLIST *acllist_create(void) |
ACLLIST *acllist_create(void) |
22 |
{ |
{ |
23 |
ACLLIST *newlist = mallocwrapper(sizeof(ACLLIST)); |
ACLLIST *newlist = mallocwrapper(sizeof(ACLLIST)); |
24 |
|
|
25 |
newlist->aclcount = 0; |
newlist->aclcount = 0; |
26 |
newlist->acls = NULL; |
newlist->acls = NULL; |
27 |
|
|
28 |
return(newlist); |
return (newlist); |
29 |
} |
} |
30 |
|
|
31 |
int getaclattr(char *instr) |
int getaclattr(char *instr) |
32 |
{ |
{ |
33 |
int result = 0; |
int result = 0; |
34 |
|
|
35 |
if (strcasecmp(instr, "ALL") == 0) |
if (strcasecmp(instr, "ALL") == 0) |
36 |
return(ACL_ADD | ACL_READ | ACL_LIST | ACL_DELETE |
return (ACL_ADD | ACL_READ | ACL_LIST | ACL_DELETE |
37 |
| ACL_MKDIR | ACL_RMDIR | ACL_WRITE |
| ACL_MKDIR | ACL_RMDIR | ACL_WRITE |
38 |
| ACL_CHMOD | ACL_CHDIR | ACL_REPLACE ); |
| ACL_CHMOD | ACL_CHDIR | ACL_REPLACE); |
39 |
else if (strcasecmp(instr, "NONE") == 0) |
else if (strcasecmp(instr, "NONE") == 0) |
40 |
return(0); |
return (0); |
41 |
|
|
42 |
while(*instr != 0) |
while (*instr != 0) |
43 |
{ |
{ |
44 |
/* make sure character is upper case! */ |
/* |
45 |
|
* make sure character is upper case! |
46 |
|
*/ |
47 |
char aclchar = *instr & (255 - 32); |
char aclchar = *instr & (255 - 32); |
48 |
|
|
49 |
switch (aclchar) |
switch (aclchar) |
50 |
{ |
{ |
51 |
case 'A': { result |= ACL_ADD ; break ; } |
case 'A': |
52 |
case 'R': { result |= ACL_READ ; break ; } |
{ |
53 |
case 'L': { result |= ACL_LIST ; break ; } |
result |= ACL_ADD; |
54 |
case 'X': { result |= ACL_REPLACE ; break ; } |
break; |
55 |
case 'D': { result |= ACL_DELETE ; break ; } |
} |
56 |
case 'M': { result |= ACL_MKDIR ; break ; } |
case 'R': |
57 |
case 'I': { result |= ACL_RMDIR ; break ; } |
{ |
58 |
case 'W': { result |= ACL_WRITE ; break ; } |
result |= ACL_READ; |
59 |
case 'H': { result |= ACL_CHMOD ; break ; } |
break; |
60 |
case 'C': { result |= ACL_CHDIR ; break ; } |
} |
61 |
default : { log_giveentry(MYLOG_INFO, 0, safe_snprintf("Unknown ACL char %c", aclchar)); } |
case 'L': |
62 |
|
{ |
63 |
|
result |= ACL_LIST; |
64 |
|
break; |
65 |
|
} |
66 |
|
case 'X': |
67 |
|
{ |
68 |
|
result |= ACL_REPLACE; |
69 |
|
break; |
70 |
|
} |
71 |
|
case 'D': |
72 |
|
{ |
73 |
|
result |= ACL_DELETE; |
74 |
|
break; |
75 |
|
} |
76 |
|
case 'M': |
77 |
|
{ |
78 |
|
result |= ACL_MKDIR; |
79 |
|
break; |
80 |
|
} |
81 |
|
case 'I': |
82 |
|
{ |
83 |
|
result |= ACL_RMDIR; |
84 |
|
break; |
85 |
|
} |
86 |
|
case 'W': |
87 |
|
{ |
88 |
|
result |= ACL_WRITE; |
89 |
|
break; |
90 |
|
} |
91 |
|
case 'H': |
92 |
|
{ |
93 |
|
result |= ACL_CHMOD; |
94 |
|
break; |
95 |
|
} |
96 |
|
case 'C': |
97 |
|
{ |
98 |
|
result |= ACL_CHDIR; |
99 |
|
break; |
100 |
|
} |
101 |
|
default: |
102 |
|
{ |
103 |
|
log_giveentry(MYLOG_INFO, 0, |
104 |
|
safe_snprintf("Unknown ACL char %c", aclchar)); |
105 |
|
} |
106 |
} |
} |
107 |
instr++; |
instr++; |
108 |
} |
} |
109 |
return(result); |
return (result); |
110 |
} |
} |
111 |
|
|
112 |
/* this assumes ret is at least 10 chars long */ |
/* this assumes ret is at least 10 chars long */ |
113 |
|
|
114 |
char *acllist_makepermstr(ACLLIST *acl, int cnt, char *ret) |
char *acllist_makepermstr(ACLLIST * acl, |
115 |
|
int cnt, |
116 |
|
char *ret) |
117 |
{ |
{ |
118 |
char refchars[10] = { "RALXDMIWHC" }; |
char refchars[10] = { "RALXDMIWHC" }; |
119 |
int count, xcount = 1; |
int count, xcount = 1; |
120 |
|
|
121 |
strcpy(ret, ""); |
strcpy(ret, ""); |
122 |
|
|
123 |
for (count = 0; count < strlen(refchars); count++) |
for (count = 0; count < strlen(refchars); count++) |
124 |
{ |
{ |
125 |
if (acl->acls[cnt].attr & xcount) |
if (acl->acls[cnt].attr & xcount) |
126 |
strncat(ret, refchars + count, 1); |
strncat(ret, refchars + count, 1); |
127 |
xcount *= 2; |
xcount *= 2; |
128 |
} |
} |
129 |
return(ret); |
return (ret); |
130 |
} |
} |
131 |
|
|
132 |
void acllist_add(ACLLIST *acl, char *dir, char *attribs, int is_regexp) |
void acllist_add(ACLLIST * acl, |
133 |
|
char *dir, |
134 |
|
char *attribs, |
135 |
|
int is_regexp) |
136 |
{ |
{ |
137 |
int count; |
int count; |
138 |
int attr = getaclattr(attribs); |
int attr = getaclattr(attribs); |
139 |
|
|
140 |
/* see if this directory already has an ACL. If it does, |
/* |
141 |
combine the ACL attributes if allowed to */ |
* see if this directory already has an ACL. If it does, |
142 |
|
* combine the ACL attributes if allowed to |
143 |
|
*/ |
144 |
|
|
145 |
debuglog("adding acl: %s %s", dir, attribs); |
debuglog("adding acl: %s %s", dir, attribs); |
146 |
for (count = 0; count < acl->aclcount; count++) |
for (count = 0; count < acl->aclcount; count++) |
147 |
{ |
{ |
148 |
if (strcmp(acl->acls[count].dir, dir) == 0) |
if (strcmp(acl->acls[count].dir, dir) == 0) |
149 |
{ |
{ |
150 |
if (!(acl->acls[count].attr & ACL_REPLACE)) |
if (!(acl->acls[count].attr & ACL_REPLACE)) |
151 |
acl->acls[count].attr |= attr; |
acl->acls[count].attr |= attr; |
152 |
return; |
return; |
153 |
} |
} |
154 |
} |
} |
155 |
|
|
156 |
/* if there isn't an ACL yet for this directory, create it here */ |
/* |
157 |
|
* if there isn't an ACL yet for this directory, create it here |
158 |
reallocwrapper(sizeof(ACL) * (acl->aclcount+1), (void **)&(acl->acls)); |
*/ |
159 |
|
|
160 |
|
reallocwrapper(sizeof(ACL) * (acl->aclcount + 1), (void **) &(acl->acls)); |
161 |
|
|
162 |
acl->acls[acl->aclcount].dir = strdupwrapper(dir); |
acl->acls[acl->aclcount].dir = strdupwrapper(dir); |
163 |
acl->acls[acl->aclcount].regexp = is_regexp; |
acl->acls[acl->aclcount].regexp = is_regexp; |
164 |
acl->acls[acl->aclcount].attr = attr; |
acl->acls[acl->aclcount].attr = attr; |
165 |
|
|
166 |
acl->aclcount++; |
acl->aclcount++; |
167 |
} |
} |
168 |
|
|
169 |
/* |
/* |
170 |
void acllist_tokendo(ACLLIST *acl, TOKENSET *tset) |
void acllist_tokendo(ACLLIST *acl, TOKENSET *tset) |
171 |
{ |
{ |
174 |
acl->acls[count].dir = tokenset_apply(tset, acl->acls[count].dir); |
acl->acls[count].dir = tokenset_apply(tset, acl->acls[count].dir); |
175 |
} |
} |
176 |
*/ |
*/ |
177 |
int acllist_check(ACLLIST *acl, char *dir, int attr) |
int acllist_check(ACLLIST * acl, |
178 |
|
char *dir, |
179 |
|
int attr) |
180 |
{ |
{ |
181 |
int result = 0; |
int result = 0; |
182 |
char *mydir = strdupwrapper(dir); |
char *mydir = strdupwrapper(dir); |
183 |
int len = strlen(dir); |
int len = strlen(dir); |
184 |
int count; |
int count; |
185 |
|
|
186 |
debuglog("inacl : %s", dir); |
debuglog("inacl : %s", dir); |
187 |
|
|
188 |
/* go through the list and find and test any regexp acls */ |
/* |
189 |
|
* go through the list and find and test any regexp acls |
190 |
|
*/ |
191 |
|
|
192 |
for (count = 0; count < acl->aclcount; count++) |
for (count = 0; count < acl->aclcount; count++) |
193 |
{ |
{ |
194 |
if ( acl->acls[count].regexp ) |
if (acl->acls[count].regexp) |
195 |
{ |
{ |
196 |
debuglog( "regexp acl %s, %s\n", mydir, acl->acls[count].dir); |
debuglog("regexp acl %s, %s\n", mydir, acl->acls[count].dir); |
197 |
if (my_fnmatch( acl->acls[count].dir, mydir, |
if (my_fnmatch(acl->acls[count].dir, mydir, |
198 |
acl->acls[count].regexp == 2 ? FNM_PATHNAME : 0 ) |
acl->acls[count].regexp == 2 ? FNM_PATHNAME : 0) |
199 |
== 0) |
== 0) |
200 |
{ |
{ |
201 |
result = acl->acls[count].attr; |
result = acl->acls[count].attr; |
202 |
goto gotmatch; |
goto gotmatch; |
203 |
} |
} |
204 |
} |
} |
205 |
} |
} |
206 |
|
|
207 |
/* now do regular dir matches */ |
/* |
208 |
|
* now do regular dir matches |
209 |
while( mydir[0] != 0 ) |
*/ |
210 |
|
|
211 |
|
while (mydir[0] != 0) |
212 |
{ |
{ |
213 |
char *tmp; |
char *tmp; |
214 |
debuglog("acl breakdown : %s", mydir); |
|
215 |
|
debuglog("acl breakdown : %s", mydir); |
216 |
for (count = 0; count < acl->aclcount; count++) |
for (count = 0; count < acl->aclcount; count++) |
217 |
{ |
{ |
218 |
debuglog( "%s, %s\n", mydir, acl->acls[count].dir); |
debuglog("%s, %s\n", mydir, acl->acls[count].dir); |
219 |
if (strcmp( mydir, acl->acls[count].dir ) == 0) |
if (strcmp(mydir, acl->acls[count].dir) == 0) |
220 |
{ |
{ |
221 |
result = acl->acls[count].attr; |
result = acl->acls[count].attr; |
222 |
goto gotmatch; |
goto gotmatch; |
223 |
} |
} |
224 |
} |
} |
225 |
|
|
226 |
if (mydir[len - 1] == '/') |
if (mydir[len - 1] == '/') |
227 |
len--; |
len--; |
228 |
mydir[len] = 0; |
mydir[len] = 0; |
236 |
} |
} |
237 |
|
|
238 |
result = 0; |
result = 0; |
239 |
gotmatch: |
gotmatch: |
240 |
freewrapper(mydir); |
freewrapper(mydir); |
241 |
if ((result & attr) == attr) |
if ((result & attr) == attr) |
242 |
return(TRUE); |
return (TRUE); |
243 |
|
|
244 |
return(FALSE); |
return (FALSE); |
245 |
} |
} |
246 |
|
|
247 |
void acllist_dest(ACLLIST *acl) |
void acllist_dest(ACLLIST * acl) |
248 |
{ |
{ |
249 |
int count; |
int count; |
250 |
|
|
251 |
if (acl->aclcount > 0) |
if (acl->aclcount > 0) |
252 |
{ |
{ |
253 |
for (count = 0; count < acl->aclcount; count++) |
for (count = 0; count < acl->aclcount; count++) |
254 |
freewrapper(acl->acls[count].dir); |
freewrapper(acl->acls[count].dir); |
255 |
|
|
256 |
freewrapper(acl->acls); |
freewrapper(acl->acls); |
257 |
} |
} |
258 |
|
|
259 |
freewrapper(acl); |
freewrapper(acl); |
260 |
} |
} |
261 |
|
|
262 |
int check_acl(FTPSTATE *peer, char *path, int perm) |
int check_acl(FTPSTATE * peer, |
263 |
|
char *path, |
264 |
|
int perm) |
265 |
{ |
{ |
266 |
int ok; |
int ok; |
267 |
|
|
268 |
ok = acllist_check(peer->acldata, dir_getvirtual(peer, path), perm); |
ok = acllist_check(peer->acldata, dir_getvirtual(peer, path), perm); |
269 |
|
|
270 |
errno = 0; |
errno = 0; |
271 |
if (ok) |
if (ok) |
272 |
return(0); |
return (0); |
273 |
else |
else |
274 |
errno = EACCES; |
errno = EACCES; |
275 |
return(-1); |
return (-1); |
276 |
} |
} |