(root)/
acl-2.3.1/
libacl/
acl_check.c
       1  /*
       2    File: acl_check.c
       3  
       4    Copyright (C) 1999, 2000
       5    Andreas Gruenbacher, <andreas.gruenbacher@gmail.com>
       6  
       7    This program is free software; you can redistribute it and/or
       8    modify it under the terms of the GNU Lesser General Public
       9    License as published by the Free Software Foundation; either
      10    version 2.1 of the License, or (at your option) any later version.
      11  
      12    This program is distributed in the hope that it will be useful,
      13    but WITHOUT ANY WARRANTY; without even the implied warranty of
      14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      15    Lesser General Public License for more details.
      16  
      17    You should have received a copy of the GNU Lesser General Public
      18    License along with this library; if not, write to the Free Software
      19    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
      20  */
      21  
      22  #include "config.h"
      23  #include <stdio.h>
      24  #include <errno.h>
      25  #include "libacl.h"
      26  
      27  
      28  #define FAIL_CHECK(error) \
      29  	do { return error; } while (0)
      30  
      31  /*
      32    Check if an ACL is valid.
      33  
      34    The e_id fields of ACL entries that don't use them are ignored.
      35  
      36    last
      37    	contains the index of the last valid entry found
      38  	after acl_check returns.
      39    returns
      40    	0 on success, -1 on error, or an ACL_*_ERROR value for invalid ACLs.
      41  */
      42  
      43  int
      44  acl_check(acl_t acl, int *last)
      45  {
      46  	acl_obj *acl_obj_p = ext2int(acl, acl);
      47  	id_t qual = 0;
      48  	int state = ACL_USER_OBJ;
      49  	acl_entry_obj *entry_obj_p;
      50  	int needs_mask = 0;
      51  
      52  	if (!acl_obj_p)
      53  		return -1;
      54  	if (last)
      55  		*last = 0;
      56  	FOREACH_ACL_ENTRY(entry_obj_p, acl_obj_p) {
      57  		/* Check permissions for ~(ACL_READ|ACL_WRITE|ACL_EXECUTE) */
      58  		switch (entry_obj_p->etag) {
      59  			case ACL_USER_OBJ:
      60  				if (state == ACL_USER_OBJ) {
      61  					qual = 0;
      62  					state = ACL_USER;
      63  					break;
      64  				}
      65  				FAIL_CHECK(ACL_MULTI_ERROR);
      66  
      67  			case ACL_USER:
      68  				if (state != ACL_USER)
      69  					FAIL_CHECK(ACL_MISS_ERROR);
      70  				if (qualifier_obj_id(entry_obj_p->eid) < qual ||
      71  				    qualifier_obj_id(entry_obj_p->eid) ==
      72  				    ACL_UNDEFINED_ID)
      73  					FAIL_CHECK(ACL_DUPLICATE_ERROR);
      74  				qual = qualifier_obj_id(entry_obj_p->eid)+1;
      75  				needs_mask = 1;
      76  				break;
      77  
      78  			case ACL_GROUP_OBJ:
      79  				if (state == ACL_USER) {
      80  					qual = 0;
      81  					state = ACL_GROUP;
      82  					break;
      83  				}
      84  				if (state >= ACL_GROUP)
      85  					FAIL_CHECK(ACL_MULTI_ERROR);
      86  				FAIL_CHECK(ACL_MISS_ERROR);
      87  
      88  			case ACL_GROUP:
      89  				if (state != ACL_GROUP)
      90  					FAIL_CHECK(ACL_MISS_ERROR);
      91  				if (qualifier_obj_id(entry_obj_p->eid) < qual ||
      92  				    qualifier_obj_id(entry_obj_p->eid) ==
      93  				    ACL_UNDEFINED_ID)
      94  					FAIL_CHECK(ACL_DUPLICATE_ERROR);
      95  				qual = qualifier_obj_id(entry_obj_p->eid)+1;
      96  				needs_mask = 1;
      97  				break;
      98  
      99  			case ACL_MASK:
     100  				if (state == ACL_GROUP) {
     101  					state = ACL_OTHER;
     102  					break;
     103  				}
     104  				if (state >= ACL_OTHER)
     105  					FAIL_CHECK(ACL_MULTI_ERROR);
     106  				FAIL_CHECK(ACL_MISS_ERROR);
     107  
     108  			case ACL_OTHER:
     109  				if (state == ACL_OTHER ||
     110  				    (state == ACL_GROUP && !needs_mask)) {
     111  					state = 0;
     112  					break;
     113  				}
     114  				FAIL_CHECK(ACL_MISS_ERROR);
     115  
     116  			default:
     117  				FAIL_CHECK(ACL_ENTRY_ERROR);
     118  		}
     119  		if (last)
     120  			(*last)++;
     121  	}
     122  
     123  	if (state != 0)
     124  		FAIL_CHECK(ACL_MISS_ERROR);
     125  	return 0;
     126  }
     127  #undef FAIL_CHECK
     128