Handling ACL entries which match the POSIX permissions

This commit is contained in:
Thomas Schmitt 2009-01-18 18:39:06 +01:00
parent ece6eca9a5
commit 723d23321a
8 changed files with 232 additions and 10 deletions

View File

@ -330,4 +330,9 @@ SUSP 1.12 ftp://ftp.ymi.com/pub/rockridge/susp112.ps
RRIP 1.12 ftp://ftp.ymi.com/pub/rockridge/rrip112.ps
(especially field SL)
-------------------------------------------------------------------------------
Pending considerations:
- shall "AA" be fixely defined as signature ?

View File

@ -14,6 +14,7 @@
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <sys/stat.h>
#include <sys/acl.h>
@ -27,6 +28,9 @@
with bit15 of flag.
@param flag Bitfield for control purposes
bit0= obtain default ACL rather than access ACL
bit4= do not return entries which match the st_mode
permissions. If no other ACL entries exist:
set *text = NULL and return 2
bit15= free text and return 1
@return > 0 ok
-1 failure of system ACL service (see errno)
@ -34,6 +38,8 @@
int aaip_get_acl_text(char *path, char **text, int flag)
{
acl_t acl= NULL;
struct stat stbuf;
int ret;
if(flag & (1 << 15)) {
if(*text != NULL)
@ -55,6 +61,16 @@ int aaip_get_acl_text(char *path, char **text, int flag)
acl_free(acl);
if(*text == NULL)
return(-1);
if(flag & 16) {
ret= stat(path, &stbuf);
if(ret != -1)
aaip_cleanout_st_mode(*text, stbuf.st_mode, 0);
if((*text)[0] == 0 || strcmp(*text, "\n") == 0) {
acl_free(text);
*text= NULL;
return(2);
}
}
return(1);
}
@ -74,6 +90,8 @@ int aaip_get_acl_text(char *path, char **text, int flag)
bit0= obtain ACL (access and eventually default)
bit1= use numeric ACL qualifiers rather than names
bit2= do not encode attributes other than ACL
bit3= -reserved-
bit4= do not return st_mode permissions in ACL.
bit15= free memory of names, value_lengths, values
@return >0 ok
<=0 error
@ -118,9 +136,11 @@ int aaip_get_attr_list(char *path, size_t *num_attrs, char ***names,
if(flag & 1) { /* Obtain ACL */
/* access-ACL */
ret= aaip_get_acl_text(path, &acl_text, 0);
ret= aaip_get_acl_text(path, &acl_text, flag & 16);
if(ret <= 0)
goto ex;
if(ret == 2)
{ret= 1; goto ex;} /* empty ACL / only st_mode info was found in ACL */
ret= aaip_encode_acl(acl_text, &a_acl_len, &a_acl, flag & 2);
if(ret <= 0)
goto ex;

View File

@ -14,6 +14,7 @@
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <sys/stat.h>
#include <sys/acl.h>
#include <attr/xattr.h>
@ -30,6 +31,9 @@
with bit15 of flag.
@param flag Bitfield for control purposes
bit0= obtain default ACL rather than access ACL
bit4= do not return entries which match the st_mode
permissions. If no other ACL entries exist:
set *text = NULL and return 2
bit15= free text and return 1
@return > 0 ok
-1 failure of system ACL service (see errno)
@ -37,6 +41,8 @@
int aaip_get_acl_text(char *path, char **text, int flag)
{
acl_t acl= NULL;
struct stat stbuf;
int ret;
if(flag & (1 << 15)) {
if(*text != NULL)
@ -52,6 +58,16 @@ int aaip_get_acl_text(char *path, char **text, int flag)
acl_free(acl);
if(*text == NULL)
return(-1);
if(flag & 16) {
ret= stat(path, &stbuf);
if(ret != -1)
aaip_cleanout_st_mode(*text, stbuf.st_mode, 0);
if((*text)[0] == 0 || strcmp(*text, "\n") == 0) {
acl_free(text);
*text= NULL;
return(2);
}
}
return(1);
}
@ -69,6 +85,7 @@ int aaip_get_acl_text(char *path, char **text, int flag)
bit2= do not obtain attributes other than ACL
bit3= do not ignore eventual local ACL attribute
(e.g. system.posix_acl_access)
bit4= do not return st_mode permissions in ACL.
bit15= free memory of names, value_lengths, values
@return >0 ok
<=0 error
@ -158,9 +175,11 @@ int aaip_get_attr_list(char *path, size_t *num_attrs, char ***names,
if(flag & 1) { /* Obtain ACL */
/* access-ACL */
ret= aaip_get_acl_text(path, &acl_text, 0);
ret= aaip_get_acl_text(path, &acl_text, flag & 16);
if(ret <= 0)
goto ex;
if(ret == 2)
{ret= 1; goto ex;} /* empty ACL / only st_mode info was found in ACL */
ret= aaip_encode_acl(acl_text, &a_acl_len, &a_acl, flag & 2);
if(ret <= 0)
goto ex;

View File

@ -17,6 +17,7 @@
#include <stdio.h>
#include <pwd.h>
#include <grp.h>
#include <sys/stat.h>
/* <<<
*/
@ -425,6 +426,121 @@ group_by_name:;
}
/* Remove the entries user::??? , group::??? , other::??? , other:???
from an ACL in long text form if they match the bits in st_mode.
@param flag bit0= do not remove entries, only determine return value
*/
int aaip_cleanout_st_mode(char *acl_text, mode_t st_mode, int flag)
{
char *rpt, *wpt, *npt, *cpt;
mode_t m;
int overriders= 0;
for(npt= wpt= rpt= acl_text; *npt != 0; rpt= npt + 1) {
npt= strchr(rpt, '\n');
if(npt == NULL)
npt= rpt + strlen(rpt);
if(strncmp(rpt, "user::", 6) == 0 && npt - rpt == 9) {
cpt= rpt + 6;
m= 0;
if(cpt[0] == 'r')
m|= S_IRUSR;
if(cpt[1] == 'w')
m|= S_IWUSR;
if(cpt[2] == 'x')
m|= S_IXUSR;
if((st_mode & S_IRWXU) == (m & S_IRWXU)) {
overriders|= 32;
continue;
}
overriders|= 4;
}
if(strncmp(rpt, "group::", 7) == 0 && npt - rpt == 10) {
cpt= rpt + 7;
m= 0;
if(cpt[0] == 'r')
m|= S_IRGRP;
if(cpt[1] == 'w')
m|= S_IWGRP;
if(cpt[2] == 'x')
m|= S_IXGRP;
if((st_mode & S_IRWXG) == (m & S_IRWXG)) {
overriders|= 16;
continue;
}
overriders|= 2;
}
if(strncmp(rpt, "other::", 7) == 0 && npt - rpt == 10) {
cpt= rpt + 7;
others_st_mode:;
m= 0;
if(cpt[0] == 'r')
m|= S_IROTH;
if(cpt[1] == 'w')
m|= S_IWOTH;
if(cpt[2] == 'x')
m|= S_IXOTH;
if((st_mode & S_IRWXO) == (m & S_IRWXO)) {
overriders|= 8;
continue;
}
overriders|= 1;
}
if(strncmp(rpt, "other:", 6) == 0 && npt - rpt == 9) {
cpt= rpt + 7;
goto others_st_mode;
}
if(wpt == rpt) {
wpt= npt + 1;
continue;
}
if(!(flag & 1))
memmove(wpt, rpt, 1 + npt - rpt);
wpt+= 1 + npt - rpt;
}
if(!(flag & 1)) {
if(wpt == acl_text)
*wpt= 0;
else if(*(wpt - 1) != 0)
*wpt= 0;
}
return(overriders);
}
/* Important: acl_text must provide 32 bytes more than its current length !
*/
int aaip_add_acl_st_mode(char *acl_text, mode_t st_mode, int flag)
{
char *wpt;
int overriders= 0;
overriders = aaip_cleanout_st_mode(acl_text, st_mode, 1);
if(!(overriders & (4 | 32))) {
wpt= acl_text + strlen(acl_text);
sprintf(wpt, "user::%c%c%c\n",
st_mode & S_IRUSR ? 'r' : '-',
st_mode & S_IWUSR ? 'w' : '-',
st_mode & S_IXUSR ? 'x' : '-');
}
if(!(overriders & (2 | 16))) {
wpt= acl_text + strlen(acl_text);
sprintf(wpt, "group::%c%c%c\n",
st_mode & S_IRGRP ? 'r' : '-',
st_mode & S_IWGRP ? 'w' : '-',
st_mode & S_IXGRP ? 'x' : '-');
}
if(!(overriders & (1 | 8))) {
wpt= acl_text + strlen(acl_text);
sprintf(wpt, "other::%c%c%c\n",
st_mode & S_IROTH ? 'r' : '-',
st_mode & S_IWOTH ? 'w' : '-',
st_mode & S_IXOTH ? 'x' : '-');
}
return(1);
}
/* --------------------------------- Decoder ---------------------------- */
/* --- private --- */

View File

@ -58,6 +58,44 @@ int aaip_encode_acl(char *acl_text,
size_t *result_len, unsigned char **result, int flag);
/* Remove the entries of type "user::" , "group::" , "other::" , "other:"
from an ACL in long text form if they match the bits in st_mode.
@param acl_text The text to be shortened
@param st_mode The component of struct stat which shall take the
removed information. The caller should submit the st_mode
variable which holds permissions as indicated by ECMA-119
and RRIP data.
@param flag bit0= do not remove entries, only determine return value
@return <0 failure
>=0 tells in six bits which tag types are present.
The first three tell which types deviate from the
corresponding st_mode settings:
bit0= "other::" overrides S_IRWXO
bit1= "group::" overrides S_IRWXG
bit2= "user::" overrides S_IRWXU
The second three tell which types comply with st_mode:
bit3= "other::" matches S_IRWXO
bit4= "group::" matches S_IRWXG
bit5= "user::" matches S_IRWXU
Given the nature of ACLs all 64 combinations are
possible although some show inner contradictions.
*/
int aaip_cleanout_st_mode(char *acl_text, mode_t st_mode, int flag);
/* Append entries of type "user::" , "group::" , "other::" representing the
permission bits in st_mode if those tag types are not present in the ACL
text.
@param acl_text The text to be made longer. It must offer 33 bytes more
storage space than its length when it is submitted.
@param st_mode The component of struct stat which shall provide the
permission information.
@param flag Unused yet. Submit 0.
@return <0 failure
*/
int aaip_add_acl_st_mode(char *acl_text, mode_t st_mode, int flag);
/* ------ OS interface ------ */
/* Obtain the ACL of the given file in long text form.
@ -67,9 +105,13 @@ int aaip_encode_acl(char *acl_text,
with bit15 of flag.
@param flag Bitfield for control purposes
bit0= obtain default ACL rather than access ACL
bit4= do not return entries which match the st_mode
permissions. If no other ACL entries exist:
set *text = NULL and return 2
bit15= free text and return 1
@return > 0 ok
-1 failure of system ACL service (see errno)
@return 1 ok
2 only st_mode permissions exist and bit 4 is set
-1 failure of system ACL service (see errno)
*/
int aaip_get_acl_text(char *path, char **text, int flag);
@ -89,6 +131,7 @@ int aaip_get_acl_text(char *path, char **text, int flag);
bit2= do not obtain attributes other than ACLs
bit3= do not ignore eventual ACL attribute
(e.g. system.posix_acl_access)
bit4= do not return st_mode permissions in ACL.
bit15= free memory of names, value_lengths, values
@return >0 ok
<=0 error

View File

@ -489,11 +489,13 @@ int lfs_get_aa_string(IsoFileSource *src, unsigned char **aa_string, int flag)
*aa_string = NULL;
/* Obtain EAs and ACLs ("access" and "default"). ACLs encoded according
to AAIP ACL representation.
to AAIP ACL representation. Clean out st_mode ACL entries.
*/
path = iso_file_source_get_path(src);
/* >>> make adjustable: bit4 = ignoring of st_mode ACL entries */
ret = aaip_get_attr_list(path, &num_attrs, &names,
&value_lengths, &values, 1 | 2);
&value_lengths, &values, 1 | 2 | 16);
if (ret <= 0) {
ret = ISO_FILE_ERROR;
goto ex;

View File

@ -4141,9 +4141,12 @@ int aaip_xinfo_func(void *data, int flag);
* bit0= obtain "default" ACL rather than "access" ACL
* (Linux directories can have a "default" ACL which influences
* the permissions of newly created files.)
* bit4= if no ACL available: return *text == NULL
else: produce ACL from PROSIX permissions
* bit15= free memory and return 1
* @return
* 1 on success,
* 2 ACL produced from POSIX permissions
* 1 ACL was read from node
* 0 if the desire ACL type is not available
* < 0 on error
*

View File

@ -1421,7 +1421,8 @@ int iso_node_get_acl_text(IsoNode *node, char **text, int flag)
size_t v_len;
char **names = NULL, **values = NULL;
unsigned char *v_data;
int ret;
int ret, from_posix= 0;
mode_t st_mode;
if (flag & (1 << 15)) {
if (*text != NULL)
@ -1468,7 +1469,7 @@ int iso_node_get_acl_text(IsoNode *node, char **text, int flag)
ret = 0;
goto ex;
}
*text = calloc(text_fill, 1);
*text = calloc(text_fill + 32, 1); /* 32 for aaip_update_acl_st_mode */
if (*text == NULL) {
ret = ISO_OUT_OF_MEM;
goto ex;
@ -1479,8 +1480,21 @@ int iso_node_get_acl_text(IsoNode *node, char **text, int flag)
goto bad_decode;
break;
}
if (*text == NULL && !(flag & 16)) {
from_posix = 1;
*text = calloc(32, 1); /* 32 for aaip_update_acl_st_mode */
}
if (*text != NULL) {
st_mode = iso_node_get_permissions(node);
aaip_add_acl_st_mode(*text, st_mode, 0);
text_fill = strlen(*text);
}
ret = (*text != NULL);
if (text == NULL)
ret = 0;
else
ret = 1 + from_posix;
ex:;
iso_node_get_attrs(node, &num_attrs, &names,
&value_lengths, &values, 1 << 15); /* free memory */