1 1.1 christos <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> 2 1.1 christos <html xmlns="http://www.w3.org/1999/xhtml"> 3 1.1 christos <head> 4 1.1 christos <title>cvs_acls</title> 5 1.1 christos <link rev="made" href="mailto:root@localhost" /> 6 1.1 christos </head> 7 1.1 christos 8 1.1 christos <body style="background-color: white"> 9 1.1 christos 10 1.1 christos <p><a name="__index__"></a></p> 11 1.1 christos <!-- INDEX BEGIN --> 12 1.1 christos 13 1.1 christos <ul> 14 1.1 christos 15 1.1 christos <li><a href="#name">Name</a></li> 16 1.1 christos <li><a href="#synopsis">Synopsis</a></li> 17 1.1 christos <li><a href="#licensing">Licensing</a></li> 18 1.1 christos <li><a href="#description">Description</a></li> 19 1.1 christos <li><a href="#enhancements">Enhancements</a></li> 20 1.1 christos <ul> 21 1.1 christos 22 1.1 christos <li><a href="#fixed_bugs">Fixed Bugs</a></li> 23 1.1 christos <li><a href="#enhancements">Enhancements</a></li> 24 1.1 christos <li><a href="#todos">ToDoS</a></li> 25 1.1 christos </ul> 26 1.1 christos 27 1.1 christos <li><a href="#version_information">Version Information</a></li> 28 1.1 christos <li><a href="#installation">Installation</a></li> 29 1.1 christos <li><a href="#format_of_the_cvsacl_file">Format of the cvsacl file</a></li> 30 1.1 christos <li><a href="#program_logic">Program Logic</a></li> 31 1.1 christos <ul> 32 1.1 christos 33 1.1 christos <li><a href="#pseudocode">Pseudocode</a></li> 34 1.1 christos <li><a href="#sanity_check">Sanity Check</a></li> 35 1.1 christos </ul> 36 1.1 christos 37 1.1 christos </ul> 38 1.1 christos <!-- INDEX END --> 39 1.1 christos 40 1.1 christos <hr /> 41 1.1 christos <p> 42 1.1 christos </p> 43 1.1 christos <h1><a name="name">Name</a></h1> 44 1.1 christos <p>cvs_acls - Access Control List for CVS</p> 45 1.1 christos <p> 46 1.1 christos </p> 47 1.1 christos <hr /> 48 1.1 christos <h1><a name="synopsis">Synopsis</a></h1> 49 1.1 christos <p>In 'commitinfo':</p> 50 1.1 christos <pre> 51 1.1 christos repository/path/to/restrict $CVSROOT/CVSROOT/cvs_acls [-d][-u $USER][-f <logfile>]</pre> 52 1.1 christos <p>where:</p> 53 1.1 christos <pre> 54 1.1 christos -d turns on debug information 55 1.1 christos -u passes the client-side userId to the cvs_acls script 56 1.1 christos -f specifies an alternate filename for the restrict_log file</pre> 57 1.1 christos <p>In 'cvsacl':</p> 58 1.1 christos <pre> 59 1.1 christos {allow.*,deny.*} [|user,user,... [|repos,repos,... [|branch,branch,...]]]</pre> 60 1.1 christos <p>where:</p> 61 1.1 christos <pre> 62 1.1 christos allow|deny - allow: commits are allowed; deny: prohibited 63 1.1 christos user - userId to be allowed or restricted 64 1.1 christos repos - file or directory to be allowed or restricted 65 1.1 christos branch - branch to be allowed or restricted</pre> 66 1.1 christos <p>See below for examples.</p> 67 1.1 christos <p> 68 1.1 christos </p> 69 1.1 christos <hr /> 70 1.1 christos <h1><a name="licensing">Licensing</a></h1> 71 1.1 christos <p>cvs_acls - provides access control list functionality for CVS 72 1.1 christos </p> 73 1.1 christos <pre> 74 1.1 christos 75 1.1 christos Copyright (c) 2004 by Peter Connolly <peter.connolly (a] cnet.com> 76 1.1 christos All rights reserved.</pre> 77 1.1 christos <p>This program is free software; you can redistribute it and/or modify 78 1.1 christos it under the terms of the GNU General Public License as published by 79 1.1 christos the Free Software Foundation; either version 2 of the License, or 80 1.1 christos (at your option) any later version.</p> 81 1.1 christos <p>This program is distributed in the hope that it will be useful, 82 1.1 christos but WITHOUT ANY WARRANTY; without even the implied warranty of 83 1.1 christos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 84 1.1 christos GNU General Public License for more details.</p> 85 1.1 christos <p>You should have received a copy of the GNU General Public License 86 1.1 christos along with this program; if not, write to the Free Software 87 1.1 christos Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA</p> 88 1.1 christos <p> 89 1.1 christos </p> 90 1.1 christos <hr /> 91 1.1 christos <h1><a name="description">Description</a></h1> 92 1.1 christos <p>This script--cvs_acls--is invoked once for each directory within a 93 1.1 christos ``cvs commit''. The set of files being committed for that directory as 94 1.1 christos well as the directory itself, are passed to this script. This script 95 1.1 christos checks its 'cvsacl' file to see if any of the files being committed 96 1.1 christos are on the 'cvsacl' file's restricted list. If any of the files are 97 1.1 christos restricted, then the cvs_acls script passes back an exit code of 1 98 1.1 christos which disallows the commits for that directory.</p> 99 1.1 christos <p>Messages are returned to the committer indicating the <a href="#item_file"><code>file(s)</code></a> that 100 1.1 christos he/she are not allowed to committ. Additionally, a site-specific 101 1.1 christos set of messages (e.g., contact information) can be included in these 102 1.1 christos messages.</p> 103 1.1 christos <p>When a commit is prohibited, log messages are written to a restrict_log 104 1.1 christos file in $CVSROOT/CVSROOT. This default file can be redirected to 105 1.1 christos another destination.</p> 106 1.1 christos <p>The script is triggered from the 'commitinfo' file in $CVSROOT/CVSROOT/.</p> 107 1.1 christos <p> 108 1.1 christos </p> 109 1.1 christos <hr /> 110 1.1 christos <h1><a name="enhancements">Enhancements</a></h1> 111 1.1 christos <p>This section lists the bug fixes and enhancements added to cvs_acls 112 1.1 christos that make up the current cvs_acls.</p> 113 1.1 christos <p> 114 1.1 christos </p> 115 1.1 christos <h2><a name="fixed_bugs">Fixed Bugs</a></h2> 116 1.1 christos <p>This version attempts to get rid the following bugs from the 117 1.1 christos original version of cvs_acls:</p> 118 1.1 christos <ul> 119 1.1 christos <li><strong><a name="item_files">Multiple entries on an 'cvsacl' line will be matched individually, 120 1.1 christos instead of requiring that all commit files *exactly* match all 121 1.1 christos 'cvsacl' entries. Commiting a file not in the 'cvsacl' list would 122 1.1 christos allow *all* files (including a restricted file) to be committed.</a></strong><br /> 123 1.1 christos </li> 124 1.1 christos [IMO, this basically made the original script unuseable for our 125 1.1 christos situation since any arbitrary combination of committed files could 126 1.1 christos avoid matching the 'cvsacl's entries.] 127 1.1 christos <p></p> 128 1.1 christos <li><strong><a name="item_handle_specific_filename_restrictions_2e_cvs_acls_">Handle specific filename restrictions. cvs_acls didn't restrict 129 1.1 christos individual files specified in 'cvsacl'.</a></strong><br /> 130 1.1 christos </li> 131 1.1 christos <li><strong><a name="item_correctly_handle_multiple_2c_specific_filename_res">Correctly handle multiple, specific filename restrictions</a></strong><br /> 132 1.1 christos </li> 133 1.1 christos <li><strong><a name="item_prohibit_mix_of_dirs_and_files_on_a_single__27cvsa">Prohibit mix of dirs and files on a single 'cvsacl' line 134 1.1 christos [To simplify the logic and because this would be normal usage.]</a></strong><br /> 135 1.1 christos </li> 136 1.1 christos <li><strong><a name="item_correctly_handle_a_mixture_of_branch_restrictions_">Correctly handle a mixture of branch restrictions within one work 137 1.1 christos directory</a></strong><br /> 138 1.1 christos </li> 139 1.1 christos <li><strong><a name="item__24cvsroot_existence_is_checked_too_late">$CVSROOT existence is checked too late</a></strong><br /> 140 1.1 christos </li> 141 1.1 christos <li><strong><a name="item_option">Correctly handle the CVSROOT=:local:/... option (useful for 142 1.1 christos interactive testing)</a></strong><br /> 143 1.1 christos </li> 144 1.1 christos <li><strong><a name="item_logic">Replacing shoddy ``$universal_off'' logic 145 1.1 christos (Thanks to Karl-Konig Konigsson for pointing this out.)</a></strong><br /> 146 1.1 christos </li> 147 1.1 christos </ul> 148 1.1 christos <p> 149 1.1 christos </p> 150 1.1 christos <h2><a name="enhancements">Enhancements</a></h2> 151 1.1 christos <ul> 152 1.1 christos <li><strong><a name="item_checks_modules_in_the__27cvsacl_27_file_for_valid_">Checks modules in the 'cvsacl' file for valid files and directories</a></strong><br /> 153 1.1 christos </li> 154 1.1 christos <li><strong><a name="item_accurately_report_restricted_entries_and_their_mat">Accurately report restricted entries and their matching patterns</a></strong><br /> 155 1.1 christos </li> 156 1.1 christos <li><strong><a name="item_simplified_and_commented_overly_complex_perl_regex">Simplified and commented overly complex PERL REGEXPs for readability 157 1.1 christos and maintainability</a></strong><br /> 158 1.1 christos </li> 159 1.1 christos <li><strong><a name="item_skip_the_rest_of_processing_if_a_mismatch_on_porti">Skip the rest of processing if a mismatch on portion of the 'cvsacl' line</a></strong><br /> 160 1.1 christos </li> 161 1.1 christos <li><strong><a name="item_file">Get rid of opaque ``karma'' messages in favor of user-friendly messages 162 1.1 christos that describe which user, <code>file(s)</code> and <code>branch(es)</code> were disallowed.</a></strong><br /> 163 1.1 christos </li> 164 1.1 christos <li><strong><a name="item_add_optional__27restrict_msg_27_file_for_additiona">Add optional 'restrict_msg' file for additional, site-specific 165 1.1 christos restriction messages.</a></strong><br /> 166 1.1 christos </li> 167 1.1 christos <li><strong><a name="item_userid">Take a ``-u'' parameter for $USER from commit_prep so that the script 168 1.1 christos can do restrictions based on the client-side userId rather than the 169 1.1 christos server-side userId (usually 'cvs').</a></strong><br /> 170 1.1 christos </li> 171 1.1 christos (See discussion below on ``Admin Setup'' for more on this point.) 172 1.1 christos <p></p> 173 1.1 christos <li><strong><a name="item_added_a_lot_more_debug_trace">Added a lot more debug trace</a></strong><br /> 174 1.1 christos </li> 175 1.1 christos <li><strong><a name="item_tested_these_restrictions_with_concurrent_use_of_p">Tested these restrictions with concurrent use of pserver and SSH 176 1.1 christos access to model our transition from pserver to ext access.</a></strong><br /> 177 1.1 christos </li> 178 1.1 christos <li><strong><a name="item_added_logging_of_restricted_commit_attempts_2e_res">Added logging of restricted commit attempts. 179 1.1 christos Restricted commits can be sent to a default file: 180 1.1 christos $CVSROOT/CVSROOT/restrictlog or to one passed to the script 181 1.1 christos via the -f command parameter.</a></strong><br /> 182 1.1 christos </li> 183 1.1 christos </ul> 184 1.1 christos <p> 185 1.1 christos </p> 186 1.1 christos <h2><a name="todos">ToDoS</a></h2> 187 1.1 christos <ul> 188 1.1 christos <li><strong><a name="item_need_to_deal_with_pserver_2fssh_transition_with_co">Need to deal with pserver/SSH transition with conflicting umasks?</a></strong><br /> 189 1.1 christos </li> 190 1.1 christos <li><strong><a name="item_use_a_cpan_module_to_handle_command_parameters_2e">Use a CPAN module to handle command parameters.</a></strong><br /> 191 1.1 christos </li> 192 1.1 christos <li><strong><a name="item_use_a_cpan_module_to_clone_data_structures_2e">Use a CPAN module to clone data structures.</a></strong><br /> 193 1.1 christos </li> 194 1.1 christos </ul> 195 1.1 christos <p> 196 1.1 christos </p> 197 1.1 christos <hr /> 198 1.1 christos <h1><a name="version_information">Version Information</a></h1> 199 1.1 christos <p>This is not offered as a fix to the original 'cvs_acls' script since it 200 1.1 christos differs substantially in goals and methods from the original and there 201 1.1 christos are probably a significant number of people out there that still require 202 1.1 christos the original version's functionality.</p> 203 1.1 christos <p>The 'cvsacl' file flags of 'allow' and 'deny' were intentionally 204 1.1 christos changed to 'allow' and 'deny' because there are enough differences 205 1.1 christos between the original script's behavior and this one's that we wanted to 206 1.1 christos make sure that users will rethink their 'cvsacl' file formats before 207 1.1 christos plugging in this newer script.</p> 208 1.1 christos <p>Please note that there has been very limited cross-platform testing of 209 1.1 christos this script!!! (We did not have the time or resources to do exhaustive 210 1.1 christos cross-platform testing.)</p> 211 1.1 christos <p>It was developed and tested under Red Hat Linux 9.0 using PERL 5.8.0. 212 1.1 christos Additionally, it was built and tested under Red Hat Linux 7.3 using 213 1.1 christos PERL 5.6.1.</p> 214 1.1 christos <p>$Id: cvs_acls.html,v 1.1.1.1 2009/04/07 22:10:10 christos Exp $</p> 215 1.1 christos <p>This version is based on the 1.11.13 version of cvs_acls 216 1.1 christos <a href="mailto:peter.connolly (a] cnet.com">peter.connolly (a] cnet.com</a> (Peter Connolly)</p> 217 1.1 christos <pre> 218 1.1 christos Access control lists for CVS. dgg (a] ksr.com (David G. Grubbs) 219 1.1 christos Branch specific controls added by voisine (a] bytemobile.com (Aaron Voisine)</pre> 220 1.1 christos <p> 221 1.1 christos </p> 222 1.1 christos <hr /> 223 1.1 christos <h1><a name="installation">Installation</a></h1> 224 1.1 christos <p>To use this program, do the following four things:</p> 225 1.1 christos <p>0. Install PERL, version 5.6.1 or 5.8.0.</p> 226 1.1 christos <p>1. Admin Setup:</p> 227 1.1 christos <pre> 228 1.1 christos There are two choices here.</pre> 229 1.1 christos <pre> 230 1.1 christos a) The first option is to use the $ENV{"USER"}, server-side userId 231 1.1 christos (from the third column of your pserver 'passwd' file) as the basis for 232 1.1 christos your restrictions. In this case, you will (at a minimum) want to set 233 1.1 christos up a new "cvsadmin" userId and group on the pserver machine. 234 1.1 christos CVS administrators will then set up their 'passwd' file entries to 235 1.1 christos run either as "cvs" (for regular users) or as "cvsadmin" (for power 236 1.1 christos users). Correspondingly, your 'cvsacl' file will only list 'cvs' 237 1.1 christos and 'cvsadmin' as the userIds in the second column.</pre> 238 1.1 christos <pre> 239 1.1 christos Commentary: A potential weakness of this is that the xinetd 240 1.1 christos cvspserver process will need to run as 'root' in order to switch 241 1.1 christos between the 'cvs' and the 'cvsadmin' userIds. Some sysadmins don't 242 1.1 christos like situations like this and may want to chroot the process. 243 1.1 christos Talk to them about this point...</pre> 244 1.1 christos <pre> 245 1.1 christos b) The second option is to use the client-side userId as the basis for 246 1.1 christos your restrictions. In this case, all the xinetd cvspserver processes 247 1.1 christos can run as userId 'cvs' and no 'root' userId is required. If you have 248 1.1 christos a 'passwd' file that lists 'cvs' as the effective run-time userId for 249 1.1 christos all your users, then no changes to this file are needed. Your 'cvsacl' 250 1.1 christos file will use the individual, client-side userIds in its 2nd column.</pre> 251 1.1 christos <pre> 252 1.1 christos As long as the userIds in pserver's 'passwd' file match those userIds 253 1.1 christos that your Linux server know about, this approach is ideal if you are 254 1.1 christos planning to move from pserver to SSH access at some later point in time. 255 1.1 christos Just by switching the CVSROOT var from CVSROOT=:pserver:<userId>... to 256 1.1 christos CVSROOT=:ext:<userId>..., users can switch over to SSH access without 257 1.1 christos any other administrative changes. When all users have switched over to 258 1.1 christos SSH, the inherently insecure xinetd cvspserver process can be disabled. 259 1.1 christos [<a href="http://ximbiot.com/cvs/manual/cvs-1.11.17/cvs_2.html#SEC32">http://ximbiot.com/cvs/manual/cvs-1.11.17/cvs_2.html#SEC32</a>]</pre> 260 1.1 christos <pre> 261 1.1 christos :TODO: The only potential glitch with the SSH approach is the possibility 262 1.1 christos that each user can have differing umasks that might interfere with one 263 1.1 christos another, especially during a transition from pserver to SSH. As noted 264 1.1 christos in the ToDo section, this needs a good strategy and set of tests for that 265 1.1 christos yet...</pre> 266 1.1 christos <p>2. Put two lines, as the *only* non-comment lines, in your commitinfo file:</p> 267 1.1 christos <pre> 268 1.1 christos ALL $CVSROOT/CVSROOT/commit_prep 269 1.1 christos ALL $CVSROOT/CVSROOT/cvs_acls [-d][-u $USER ][-f <logfilename>]</pre> 270 1.1 christos <pre> 271 1.1 christos where "-d" turns on debug trace 272 1.1 christos "-u $USER" passes the client-side userId to cvs_acls 273 1.1 christos "-f <logfilename"> overrides the default filename used to log 274 1.1 christos restricted commit attempts.</pre> 275 1.1 christos <pre> 276 1.1 christos (These are handled in the processArgs() subroutine.)</pre> 277 1.1 christos <p>If you are using client-side userIds to restrict access to your 278 1.1 christos repository, make sure that they are in this order since the commit_prep 279 1.1 christos script is required in order to pass the $USER parameter.</p> 280 1.1 christos <p>A final note about the repository matching pattern. The example above 281 1.1 christos uses ``ALL'' but note that this means that the cvs_acls script will run 282 1.1 christos for each and every commit in your repository. Obviously, in a large 283 1.1 christos repository this adds up to a lot of overhead that may not be necesary. 284 1.1 christos A better strategy is to use a repository pattern that is more specific 285 1.1 christos to the areas that you wish to secure.</p> 286 1.1 christos <p>3. Install this file as $CVSROOT/CVSROOT/cvs_acls and make it executable.</p> 287 1.1 christos <p>4. Create a file named CVSROOT/cvsacl and optionally add it to 288 1.1 christos CVSROOT/checkoutlist and check it in. See the CVS manual's 289 1.1 christos administrative files section about checkoutlist. Typically:</p> 290 1.1 christos <pre> 291 1.1 christos $ cvs checkout CVSROOT 292 1.1 christos $ cd CVSROOT 293 1.1 christos [ create the cvsacl file, include 'commitinfo' line ] 294 1.1 christos [ add cvsacl to checkoutlist ] 295 1.1 christos $ cvs add cvsacl 296 1.1 christos $ cvs commit -m 'Added cvsacl for use with cvs_acls.' cvsacl checkoutlist</pre> 297 1.1 christos <p>Note: The format of the 'cvsacl' file is described in detail immediately 298 1.1 christos below but here is an important set up point:</p> 299 1.1 christos <pre> 300 1.1 christos Make sure to include a line like the following:</pre> 301 1.1 christos <pre> 302 1.1 christos deny||CVSROOT/commitinfo CVSROOT/cvsacl 303 1.1 christos allow|cvsadmin|CVSROOT/commitinfo CVSROOT/cvsacl</pre> 304 1.1 christos <pre> 305 1.1 christos that restricts access to commitinfo and cvsacl since this would be one of 306 1.1 christos the easiest "end runs" around this ACL approach. ('commitinfo' has the 307 1.1 christos line that executes the cvs_acls script and, of course, all the 308 1.1 christos restrictions are in 'cvsacl'.)</pre> 309 1.1 christos <p>5. (Optional) Create a 'restrict_msg' file in the $CVSROOT/CVSROOT directory. 310 1.1 christos Whenever there is a restricted file or dir message, cvs_acls will look 311 1.1 christos for this file and, if it exists, print its contents as part of the 312 1.1 christos commit-denial message. This gives you a chance to print any site-specific 313 1.1 christos information (e.g., who to call, what procedures to look up,...) whenever 314 1.1 christos a commit is denied.</p> 315 1.1 christos <p> 316 1.1 christos </p> 317 1.1 christos <hr /> 318 1.1 christos <h1><a name="format_of_the_cvsacl_file">Format of the cvsacl file</a></h1> 319 1.1 christos <p>The 'cvsacl' file determines whether you may commit files. It contains lines 320 1.1 christos read from top to bottom, keeping track of whether a given user, repository 321 1.1 christos and branch combination is ``allowed'' or ``denied.'' The script will assume 322 1.1 christos ``allowed'' on all repository paths until 'allow' and 'deny' rules change 323 1.1 christos that default.</p> 324 1.1 christos <p>The normal pattern is to specify an 'deny' rule to turn off 325 1.1 christos access to ALL users, then follow it with a matching 'allow' rule that will 326 1.1 christos turn on access for a select set of users. In the case of multiple rules for 327 1.1 christos the same user, repository and branch, the last one takes precedence.</p> 328 1.1 christos <p>Blank lines and lines with only comments are ignored. Any other lines not 329 1.1 christos beginning with ``allow'' or ``deny'' are logged to the restrict_log file.</p> 330 1.1 christos <p>Lines beginning with ``allow'' or ``deny'' are assumed to be '|'-separated 331 1.1 christos triples: (All spaces and tabs are ignored in a line.)</p> 332 1.1 christos <pre> 333 1.1 christos {allow.*,deny.*} [|user,user,... [|repos,repos,... [|branch,branch,...]]]</pre> 334 1.1 christos <pre> 335 1.1 christos 1. String starting with "allow" or "deny". 336 1.1 christos 2. Optional, comma-separated list of usernames. 337 1.1 christos 3. Optional, comma-separated list of repository pathnames. 338 1.1 christos These are pathnames relative to $CVSROOT. They can be directories or 339 1.1 christos filenames. A directory name allows or restricts access to all files and 340 1.1 christos directories below it. One line can have either directories or filenames 341 1.1 christos but not both. 342 1.1 christos 4. Optional, comma-separated list of branch tags. 343 1.1 christos If not specified, all branches are assumed. Use HEAD to reference the 344 1.1 christos main branch.</pre> 345 1.1 christos <p>Example: (Note: No in-line comments.)</p> 346 1.1 christos <pre> 347 1.1 christos # ----- Make whole repository unavailable. 348 1.1 christos deny</pre> 349 1.1 christos <pre> 350 1.1 christos # ----- Except for user "dgg". 351 1.1 christos allow|dgg</pre> 352 1.1 christos <pre> 353 1.1 christos # ----- Except when "fred" or "john" commit to the 354 1.1 christos # module whose repository is "bin/ls" 355 1.1 christos allow|fred, john|bin/ls</pre> 356 1.1 christos <pre> 357 1.1 christos # ----- Except when "ed" commits to the "stable" 358 1.1 christos # branch of the "bin/ls" repository 359 1.1 christos allow|ed|/bin/ls|stable</pre> 360 1.1 christos <p> 361 1.1 christos </p> 362 1.1 christos <hr /> 363 1.1 christos <h1><a name="program_logic">Program Logic</a></h1> 364 1.1 christos <p>CVS passes to @ARGV an absolute directory pathname (the repository 365 1.1 christos appended to your $CVSROOT variable), followed by a list of filenames 366 1.1 christos within that directory that are to be committed.</p> 367 1.1 christos <p>The script walks through the 'cvsacl' file looking for matches on 368 1.1 christos the username, repository and branch.</p> 369 1.1 christos <p>A username match is simply the user's name appearing in the second 370 1.1 christos column of the cvsacl line in a space-or-comma separate list. If 371 1.1 christos blank, then any user will match.</p> 372 1.1 christos <p>A repository match:</p> 373 1.1 christos <ul> 374 1.1 christos <li><strong><a name="item_each_entry_in_the_modules_section_of_the_current__">Each entry in the modules section of the current 'cvsacl' line is 375 1.1 christos examined to see if it is a dir or a file. The line must have 376 1.1 christos either files or dirs, but not both. (To simplify the logic.)</a></strong><br /> 377 1.1 christos </li> 378 1.1 christos <li><strong><a name="item_if_neither_2c_then_assume_the__27cvsacl_27_file_wa">If neither, then assume the 'cvsacl' file was set up in error and 379 1.1 christos skip that 'allow' line.</a></strong><br /> 380 1.1 christos </li> 381 1.1 christos <li><strong><a name="item_if_a_dir_2c_then_each_dir_pattern_is_matched_separ">If a dir, then each dir pattern is matched separately against the 382 1.1 christos beginning of each of the committed files in @ARGV.</a></strong><br /> 383 1.1 christos </li> 384 1.1 christos <li><strong><a name="item_if_a_file_2c_then_each_file_pattern_is_matched_exa">If a file, then each file pattern is matched exactly against each 385 1.1 christos of the files to be committed in @ARGV.</a></strong><br /> 386 1.1 christos </li> 387 1.1 christos <li><strong><a name="item_repository_and_branch_must_both_match_together_2e_">Repository and branch must BOTH match together. This is to cover 388 1.1 christos the use case where a user has multiple branches checked out in 389 1.1 christos a single work directory. Commit files can be from different 390 1.1 christos branches.</a></strong><br /> 391 1.1 christos </li> 392 1.1 christos A branch match is either: 393 1.1 christos <ul> 394 1.1 christos <li><strong><a name="item_when_no_branches_are_listed_in_the_fourth_column_2">When no branches are listed in the fourth column. (``Match any.'')</a></strong><br /> 395 1.1 christos </li> 396 1.1 christos <li><strong><a name="item_all_elements_from_the_fourth_column_are_matched_ag">All elements from the fourth column are matched against each of 397 1.1 christos the tag names for $ARGV[1..$#ARGV] found in the %branches file.</a></strong><br /> 398 1.1 christos </li> 399 1.1 christos </ul> 400 1.1 christos <li><strong><a name="item__27allow_27_match_remove_that_match_from_the_tally">'allow' match remove that match from the tally map.</a></strong><br /> 401 1.1 christos </li> 402 1.1 christos <li><strong><a name="item_restricted">Restricted ('deny') matches are saved in the %repository_matches 403 1.1 christos table.</a></strong><br /> 404 1.1 christos </li> 405 1.1 christos <li><strong><a name="item_if_there_is_a_match_on_user_2c_repository_and_bran">If there is a match on user, repository and branch:</a></strong><br /> 406 1.1 christos </li> 407 1.1 christos <pre> 408 1.1 christos If repository, branch and user match 409 1.1 christos if 'deny' 410 1.1 christos add %repository_matches entries to %restricted_entries 411 1.1 christos else if 'allow' 412 1.1 christos remove %repository_matches entries from %restricted_entries</pre> 413 1.1 christos <li><strong><a name="item_at_the_end_of_all_the__27cvsacl_27_line_checks_2c_">At the end of all the 'cvsacl' line checks, check to see if there 414 1.1 christos are any entries in the %restricted_entries. If so, then deny the 415 1.1 christos commit.</a></strong><br /> 416 1.1 christos </li> 417 1.1 christos </ul> 418 1.1 christos <p> 419 1.1 christos </p> 420 1.1 christos <h2><a name="pseudocode">Pseudocode</a></h2> 421 1.1 christos <pre> 422 1.1 christos read CVS/Entries file and create branch{file}->{branch} hash table 423 1.1 christos + for each 'allow' and 'deny' line in the 'cvsacl' file: 424 1.1 christos | user match? 425 1.1 christos | - Yes: set $user_match = 1; 426 1.1 christos | repository and branch match? 427 1.1 christos | - Yes: add to %repository_matches; 428 1.1 christos | did user, repository match? 429 1.1 christos | - Yes: if 'deny' then 430 1.1 christos | add %repository_matches -> %restricted_entries 431 1.1 christos | if 'allow' then 432 1.1 christos | remove %repository_matches <- %restricted_entries 433 1.1 christos + end for loop 434 1.1 christos any saved restrictions? 435 1.1 christos no: exit, 436 1.1 christos set exit code allowing commits and exit 437 1.1 christos yes: report restrictions, 438 1.1 christos set exit code prohibiting commits and exit</pre> 439 1.1 christos <p> 440 1.1 christos </p> 441 1.1 christos <h2><a name="sanity_check">Sanity Check</a></h2> 442 1.1 christos <pre> 443 1.1 christos 1) file allow trumps a dir deny 444 1.1 christos deny||java/lib 445 1.1 christos allow||java/lib/README 446 1.1 christos 2) dir allow can undo a file deny 447 1.1 christos deny||java/lib/README 448 1.1 christos allow||java/lib 449 1.1 christos 3) file deny trumps a dir allow 450 1.1 christos allow||java/lib 451 1.1 christos deny||java/lib/README 452 1.1 christos 4) dir deny trumps a file allow 453 1.1 christos allow||java/lib/README 454 1.1 christos deny||java/lib 455 1.1 christos ... so last match always takes precedence</pre> 456 1.1 christos 457 1.1 christos </body> 458 1.1 christos 459 1.1 christos </html> 460