[1] | 1 | # scripts.mit.edu openafs patch |
---|
| 2 | # Copyright (C) 2006 Jeff Arnold <jbarnold@mit.edu> |
---|
[259] | 3 | # with modifications by Joe Presbrey <presbrey@mit.edu> |
---|
[628] | 4 | # and Anders Kaseorg <andersk@mit.edu> |
---|
[1134] | 5 | # and Edward Z. Yang <ezyang@mit.edu> |
---|
[1913] | 6 | # and Benjamin Kaduk <kaduk@mit.edu> |
---|
| 7 | # and Alexander Chernyakhovsky <achernya@mit.edu> |
---|
[1] | 8 | # |
---|
[622] | 9 | # This file is available under both the MIT license and the GPL. |
---|
| 10 | # |
---|
| 11 | |
---|
| 12 | # Permission is hereby granted, free of charge, to any person obtaining a copy |
---|
| 13 | # of this software and associated documentation files (the "Software"), to deal |
---|
| 14 | # in the Software without restriction, including without limitation the rights |
---|
| 15 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
---|
| 16 | # copies of the Software, and to permit persons to whom the Software is |
---|
| 17 | # furnished to do so, subject to the following conditions: |
---|
| 18 | # |
---|
| 19 | # The above copyright notice and this permission notice shall be included in |
---|
| 20 | # all copies or substantial portions of the Software. |
---|
| 21 | # |
---|
| 22 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
---|
| 23 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
---|
| 24 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
---|
| 25 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
---|
| 26 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
---|
| 27 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
---|
| 28 | # THE SOFTWARE. |
---|
| 29 | # |
---|
| 30 | |
---|
[1] | 31 | # This program is free software; you can redistribute it and/or |
---|
| 32 | # modify it under the terms of the GNU General Public License |
---|
| 33 | # as published by the Free Software Foundation; either version 2 |
---|
| 34 | # of the License, or (at your option) any later version. |
---|
| 35 | # |
---|
| 36 | # This program is distributed in the hope that it will be useful, |
---|
| 37 | # but WITHOUT ANY WARRANTY; without even the implied warranty of |
---|
| 38 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
---|
| 39 | # GNU General Public License for more details. |
---|
| 40 | # |
---|
| 41 | # You should have received a copy of the GNU General Public License |
---|
| 42 | # along with this program; if not, write to the Free Software |
---|
| 43 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA |
---|
| 44 | # |
---|
| 45 | # See /COPYRIGHT in this repository for more information. |
---|
| 46 | # |
---|
[1913] | 47 | diff --git a/src/afs/LINUX/osi_vnodeops.c b/src/afs/LINUX/osi_vnodeops.c |
---|
| 48 | index 7c7705e..0d0e94f 100644 |
---|
| 49 | --- a/src/afs/LINUX/osi_vnodeops.c |
---|
| 50 | +++ b/src/afs/LINUX/osi_vnodeops.c |
---|
| 51 | @@ -904,6 +904,28 @@ afs_linux_dentry_revalidate(struct dentry *dp, int flags) |
---|
[1134] | 52 | /* should we always update the attributes at this point? */ |
---|
| 53 | /* unlikely--the vcache entry hasn't changed */ |
---|
| 54 | |
---|
| 55 | + /* [scripts] This code makes hardlinks work correctly. |
---|
[1913] | 56 | + * |
---|
| 57 | + * We want Apache to be able to read a file with hardlinks |
---|
| 58 | + * named .htaccess and foo to be able to read it via .htaccess |
---|
| 59 | + * and not via foo, regardless of which name was looked up |
---|
| 60 | + * (remember, inodes do not have filenames associated with them.) |
---|
| 61 | + * |
---|
| 62 | + * It is important that we modify the existing cache entry even |
---|
| 63 | + * if it is otherwise totally valid and would not be reloaded. |
---|
| 64 | + * Otherwise, it won't recover from repeatedly reading the same |
---|
| 65 | + * inode via multiple hardlinks or different names. Specifically, |
---|
| 66 | + * Apache will be able to read both names if it was first looked |
---|
| 67 | + * up (by anyone!) via .htaccess, and neither if it was first |
---|
| 68 | + * looked up via foo. |
---|
| 69 | + * |
---|
| 70 | + * With regards to performance, the strncmp() is bounded by |
---|
| 71 | + * three characters, so it takes O(3) operations. If this code |
---|
| 72 | + * is extended to all static-cat extensions, we'll want to do |
---|
| 73 | + * some clever hashing using gperf here. |
---|
| 74 | + */ |
---|
[1134] | 75 | + vcp->apache_access = strncmp(dp->d_name.name, ".ht", 3) == 0; |
---|
| 76 | + |
---|
[1913] | 77 | dput(parent); |
---|
[1134] | 78 | } else { |
---|
| 79 | #ifdef notyet |
---|
[1913] | 80 | diff --git a/src/afs/VNOPS/afs_vnop_access.c b/src/afs/VNOPS/afs_vnop_access.c |
---|
| 81 | index eabcfeb..6390850 100644 |
---|
| 82 | --- a/src/afs/VNOPS/afs_vnop_access.c |
---|
| 83 | +++ b/src/afs/VNOPS/afs_vnop_access.c |
---|
| 84 | @@ -130,6 +130,15 @@ afs_AccessOK(struct vcache *avc, afs_int32 arights, struct vrequest *areq, |
---|
| 85 | dirBits = PRSFS_LOOKUP | PRSFS_READ; |
---|
| 86 | return (arights == (dirBits & arights)); |
---|
| 87 | } |
---|
| 88 | + if ( areq->uid == globalpag && |
---|
| 89 | + !(areq->realuid == avc->f.fid.Fid.Volume) && |
---|
| 90 | + !((avc->f.anyAccess | arights) == avc->f.anyAccess) && |
---|
| 91 | + !(((arights & ~(PRSFS_LOOKUP|PRSFS_READ)) == 0) && areq->realuid == HTTPD_UID) && |
---|
| 92 | + !(((arights & ~(PRSFS_LOOKUP|PRSFS_READ)) == 0) && areq->realuid == POSTFIX_UID) && |
---|
| 93 | + !(areq->realuid == 0 && PRSFS_USR3 == afs_GetAccessBits(avc, PRSFS_USR3, areq)) && |
---|
| 94 | + !((areq->realuid == 0 || areq->realuid == SIGNUP_UID) && PRSFS_USR4 == afs_GetAccessBits(avc, PRSFS_USR4, areq)) ) { |
---|
| 95 | + return 0; |
---|
| 96 | + } |
---|
| 97 | return (arights == afs_GetAccessBits(avc, arights, areq)); |
---|
| 98 | } else { |
---|
| 99 | /* some rights come from dir and some from file. Specifically, you |
---|
| 100 | @@ -183,6 +192,19 @@ afs_AccessOK(struct vcache *avc, afs_int32 arights, struct vrequest *areq, |
---|
| 101 | fileBits |= PRSFS_READ; |
---|
| 102 | } |
---|
| 103 | } |
---|
| 104 | + |
---|
| 105 | + if ( areq->uid == globalpag && |
---|
| 106 | + !(areq->realuid == avc->f.fid.Fid.Volume) && |
---|
| 107 | + !((avc->f.anyAccess | arights) == avc->f.anyAccess) && |
---|
| 108 | + !(arights == PRSFS_LOOKUP && areq->realuid == HTTPD_UID) && |
---|
| 109 | + !(arights == PRSFS_LOOKUP && areq->realuid == POSTFIX_UID) && |
---|
| 110 | + !(arights == PRSFS_READ && areq->realuid == HTTPD_UID && |
---|
| 111 | + (avc->f.m.Mode == 0100777 || avc->apache_access)) && |
---|
| 112 | + !(areq->realuid == 0 && PRSFS_USR3 == afs_GetAccessBits(avc, PRSFS_USR3, areq)) && |
---|
| 113 | + !((areq->realuid == 0 || areq->realuid == SIGNUP_UID) && PRSFS_USR4 == afs_GetAccessBits(avc, PRSFS_USR4, areq)) ) { |
---|
| 114 | + return 0; |
---|
| 115 | + } |
---|
| 116 | + |
---|
| 117 | return ((fileBits & arights) == arights); /* true if all rights bits are on */ |
---|
[1134] | 118 | } |
---|
[1913] | 119 | } |
---|
| 120 | diff --git a/src/afs/VNOPS/afs_vnop_attrs.c b/src/afs/VNOPS/afs_vnop_attrs.c |
---|
| 121 | index b3931e5..71ef05c 100644 |
---|
| 122 | --- a/src/afs/VNOPS/afs_vnop_attrs.c |
---|
| 123 | +++ b/src/afs/VNOPS/afs_vnop_attrs.c |
---|
| 124 | @@ -88,8 +88,8 @@ afs_CopyOutAttrs(struct vcache *avc, struct vattr *attrs) |
---|
| 125 | } |
---|
| 126 | } |
---|
| 127 | #endif /* AFS_DARWIN_ENV */ |
---|
| 128 | - attrs->va_uid = fakedir ? 0 : avc->f.m.Owner; |
---|
| 129 | - attrs->va_gid = fakedir ? 0 : avc->f.m.Group; /* yeah! */ |
---|
| 130 | + attrs->va_uid = fakedir ? 0 : avc->f.fid.Fid.Volume; |
---|
| 131 | + attrs->va_gid = (avc->f.m.Owner == DAEMON_SCRIPTS_PTSID ? avc->f.m.Group : avc->f.m.Owner); |
---|
| 132 | #if defined(AFS_SUN56_ENV) |
---|
| 133 | attrs->va_fsid = avc->v.v_vfsp->vfs_fsid.val[0]; |
---|
| 134 | #elif defined(AFS_DARWIN80_ENV) |
---|
| 135 | diff --git a/src/afs/VNOPS/afs_vnop_lookup.c b/src/afs/VNOPS/afs_vnop_lookup.c |
---|
| 136 | index 8e7af1c..7e984e9 100644 |
---|
| 137 | --- a/src/afs/VNOPS/afs_vnop_lookup.c |
---|
| 138 | +++ b/src/afs/VNOPS/afs_vnop_lookup.c |
---|
| 139 | @@ -1877,6 +1877,12 @@ afs_lookup(OSI_VC_DECL(adp), char *aname, struct vcache **avcp, afs_ucred_t *acr |
---|
| 140 | } |
---|
[1134] | 141 | |
---|
| 142 | done: |
---|
| 143 | + if (tvc) { |
---|
[1913] | 144 | + /* [scripts] check Apache's ability to read this file, so that |
---|
| 145 | + * we can figure this out on an access() call */ |
---|
| 146 | + tvc->apache_access = strncmp(aname, ".ht", 3) == 0; |
---|
[1134] | 147 | + } |
---|
| 148 | + |
---|
| 149 | /* put the network buffer back, if need be */ |
---|
| 150 | if (tname != aname && tname) |
---|
| 151 | osi_FreeLargeSpace(tname); |
---|
[1913] | 152 | diff --git a/src/afs/afs.h b/src/afs/afs.h |
---|
| 153 | index fcc4c70..0d53af6 100644 |
---|
| 154 | --- a/src/afs/afs.h |
---|
| 155 | +++ b/src/afs/afs.h |
---|
| 156 | @@ -233,8 +233,16 @@ struct afs_slotlist { |
---|
| 157 | struct afs_slotlist *next; |
---|
| 158 | }; |
---|
[628] | 159 | |
---|
[1] | 160 | +#define AFSAGENT_UID (101) |
---|
[258] | 161 | +#define SIGNUP_UID (102) |
---|
[1] | 162 | +#define HTTPD_UID (48) |
---|
[83] | 163 | +#define POSTFIX_UID (89) |
---|
[1] | 164 | +#define DAEMON_SCRIPTS_PTSID (33554596) |
---|
[628] | 165 | +extern afs_int32 globalpag; |
---|
| 166 | + |
---|
[1] | 167 | struct vrequest { |
---|
| 168 | afs_int32 uid; /* user id making the request */ |
---|
| 169 | + afs_int32 realuid; |
---|
| 170 | afs_int32 busyCount; /* how many busies we've seen so far */ |
---|
| 171 | afs_int32 flags; /* things like O_SYNC, O_NONBLOCK go here */ |
---|
[1070] | 172 | char initd; /* if non-zero, Error fields meaningful */ |
---|
[1930] | 173 | @@ -887,6 +895,7 @@ struct vcache { |
---|
[1134] | 174 | #ifdef AFS_SUN5_ENV |
---|
[1930] | 175 | struct afs_q multiPage; /* list of multiPage_range structs */ |
---|
[1134] | 176 | #endif |
---|
[1259] | 177 | + int apache_access; /* whether or not Apache has access to a file */ |
---|
[1134] | 178 | }; |
---|
| 179 | |
---|
| 180 | #define DONT_CHECK_MODE_BITS 0 |
---|
[1913] | 181 | diff --git a/src/afs/afs_analyze.c b/src/afs/afs_analyze.c |
---|
| 182 | index 1834e6d..673a8e6 100644 |
---|
| 183 | --- a/src/afs/afs_analyze.c |
---|
| 184 | +++ b/src/afs/afs_analyze.c |
---|
| 185 | @@ -368,7 +368,7 @@ afs_Analyze(struct afs_conn *aconn, afs_int32 acode, |
---|
| 186 | (afid ? afid->Fid.Volume : 0)); |
---|
| 187 | } |
---|
| 188 | |
---|
| 189 | - if (areq->busyCount > 100) { |
---|
| 190 | + if (1) { |
---|
| 191 | if (aerrP) |
---|
| 192 | (aerrP->err_Volume)++; |
---|
| 193 | areq->volumeError = VOLBUSY; |
---|
| 194 | diff --git a/src/afs/afs_osi_pag.c b/src/afs/afs_osi_pag.c |
---|
| 195 | index c888605..ff5cf2d 100644 |
---|
| 196 | --- a/src/afs/afs_osi_pag.c |
---|
| 197 | +++ b/src/afs/afs_osi_pag.c |
---|
| 198 | @@ -49,6 +49,8 @@ afs_uint32 pagCounter = 0; |
---|
[628] | 199 | #endif |
---|
[1] | 200 | /* Local variables */ |
---|
| 201 | |
---|
[55] | 202 | +afs_int32 globalpag = 0; |
---|
[1] | 203 | + |
---|
| 204 | /* |
---|
| 205 | * Pags are implemented as follows: the set of groups whose long |
---|
| 206 | * representation is '41XXXXXX' hex are used to represent the pags. |
---|
[1913] | 207 | @@ -484,6 +486,15 @@ afs_InitReq(struct vrequest *av, afs_ucred_t *acred) |
---|
| 208 | av->uid = afs_cr_uid(acred); /* default when no pag is set */ |
---|
[1] | 209 | #endif |
---|
| 210 | } |
---|
| 211 | + |
---|
[1913] | 212 | + av->realuid = afs_cr_uid(acred); |
---|
| 213 | + if(!globalpag && av->realuid == AFSAGENT_UID) { |
---|
[1] | 214 | + globalpag = av->uid; |
---|
| 215 | + } |
---|
[1913] | 216 | + else if (globalpag && av->uid == av->realuid) { |
---|
[1] | 217 | + av->uid = globalpag; |
---|
| 218 | + } |
---|
| 219 | + |
---|
| 220 | return 0; |
---|
| 221 | } |
---|
[1693] | 222 | |
---|
[1913] | 223 | diff --git a/src/afs/afs_pioctl.c b/src/afs/afs_pioctl.c |
---|
| 224 | index f282510..00f1360 100644 |
---|
| 225 | --- a/src/afs/afs_pioctl.c |
---|
| 226 | +++ b/src/afs/afs_pioctl.c |
---|
[1962] | 227 | @@ -1406,6 +1406,10 @@ DECL_PIOCTL(PSetAcl) |
---|
| 228 | struct rx_connection *rxconn; |
---|
[1] | 229 | XSTATS_DECLS; |
---|
| 230 | |
---|
[628] | 231 | + if (areq->uid == globalpag && areq->realuid != AFSAGENT_UID) { |
---|
[1962] | 232 | + return EACCES; |
---|
[1] | 233 | + } |
---|
| 234 | + |
---|
| 235 | AFS_STATCNT(PSetAcl); |
---|
| 236 | if (!avc) |
---|
| 237 | return EINVAL; |
---|
[1913] | 238 | @@ -1790,6 +1794,10 @@ DECL_PIOCTL(PSetTokens) |
---|
[1] | 239 | struct vrequest treq; |
---|
| 240 | afs_int32 flag, set_parent_pag = 0; |
---|
| 241 | |
---|
[628] | 242 | + if (areq->uid == globalpag && areq->realuid != AFSAGENT_UID) { |
---|
[1509] | 243 | + return EACCES; |
---|
[1] | 244 | + } |
---|
| 245 | + |
---|
| 246 | AFS_STATCNT(PSetTokens); |
---|
| 247 | if (!afs_resourceinit_flag) { |
---|
| 248 | return EIO; |
---|
[1913] | 249 | @@ -2231,6 +2239,11 @@ DECL_PIOCTL(PGetTokens) |
---|
[936] | 250 | int newStyle; |
---|
[1913] | 251 | int code = E2BIG; |
---|
[936] | 252 | |
---|
| 253 | + if (areq->uid == globalpag && areq->realuid != AFSAGENT_UID && |
---|
[1913] | 254 | + areq->realuid != 0 && areq->realuid != SIGNUP_UID) { |
---|
[1509] | 255 | + return EDOM; |
---|
[1913] | 256 | + } |
---|
[936] | 257 | + |
---|
| 258 | AFS_STATCNT(PGetTokens); |
---|
[1070] | 259 | if (!afs_resourceinit_flag) /* afs daemons haven't started yet */ |
---|
| 260 | return EIO; /* Inappropriate ioctl for device */ |
---|
[1913] | 261 | @@ -2341,6 +2354,10 @@ DECL_PIOCTL(PUnlog) |
---|
| 262 | afs_int32 i; |
---|
| 263 | struct unixuser *tu; |
---|
[1] | 264 | |
---|
[628] | 265 | + if (areq->uid == globalpag && areq->realuid != AFSAGENT_UID) { |
---|
[1509] | 266 | + return EACCES; |
---|
[1] | 267 | + } |
---|
| 268 | + |
---|
| 269 | AFS_STATCNT(PUnlog); |
---|
| 270 | if (!afs_resourceinit_flag) /* afs daemons haven't started yet */ |
---|
| 271 | return EIO; /* Inappropriate ioctl for device */ |
---|