New API call iso_node_set_acl_text()

and automatic update of ACL entries by iso_node_set_permissions()
This commit is contained in:
Thomas Schmitt 2009-01-21 13:29:10 +01:00
parent d4ce4a7f88
commit 1150ee32a4
8 changed files with 613 additions and 123 deletions

View File

@ -173,9 +173,11 @@ The Value shall be an arbitrary number of ACL Entries:
they are not aware of updates of this document which would they are not aware of updates of this document which would
assign a meaning to them. assign a meaning to them.
If any of ACL_USER_OBJ, ACL_GROUP_OBJ, ACL_OTHER are missing then the settings The entries ACL_USER_OBJ, ACL_GROUP_OBJ, ACL_OTHER must match the permission
from the PX field shall get into effect. If they exist then they shall override bits of the PX field. This shall obey the peculiar rule that
the PX field. ACL_USER_OBJ must match S_IRWXU, ACL_OTHER must match S_IRWXO,
ACL_MASK - if present - must match S_IRWXG, else ACL_GROUP must match S_IRWXG.
If there is ACL_USER_OBJ or ACL_GROUP_OBJ there must also be ACL_MASK.
A numeric qualifier is a binary number of variable length. The Most Significant A numeric qualifier is a binary number of variable length. The Most Significant
Byte comes first. The number shall be the "POSIX File User ID" resp. Byte comes first. The number shall be the "POSIX File User ID" resp.

View File

@ -63,7 +63,7 @@ int aaip_get_acl_text(char *path, char **text, int flag)
if(flag & 16) { if(flag & 16) {
ret= stat(path, &stbuf); ret= stat(path, &stbuf);
if(ret != -1) { if(ret != -1) {
ret = aaip_cleanout_st_mode(*text, stbuf.st_mode, 2); ret = aaip_cleanout_st_mode(*text, &(stbuf.st_mode), 2);
if(!(ret & (7 | 64))) if(!(ret & (7 | 64)))
(*text)[0]= 0; (*text)[0]= 0;
} }

View File

@ -61,7 +61,7 @@ int aaip_get_acl_text(char *path, char **text, int flag)
if(flag & 16) { if(flag & 16) {
ret= stat(path, &stbuf); ret= stat(path, &stbuf);
if(ret != -1) { if(ret != -1) {
ret = aaip_cleanout_st_mode(*text, stbuf.st_mode, 2); ret = aaip_cleanout_st_mode(*text, &(stbuf.st_mode), 2);
if(!(ret & (7 | 64))) if(!(ret & (7 | 64)))
(*text)[0]= 0; (*text)[0]= 0;
} }
@ -99,9 +99,18 @@ int aaip_get_attr_list(char *path, size_t *num_attrs, char ***names,
int ret, retry= 0; int ret, retry= 0;
char *list= NULL; char *list= NULL;
ssize_t list_size= 0, i, num_names= 0, value_ret; ssize_t list_size= 0, i, num_names= 0, value_ret;
size_t a_acl_len= 0, d_acl_len= 0, acl_len= 0; size_t acl_len= 0;
unsigned char *a_acl= NULL, *d_acl= NULL, *acl= NULL; unsigned char *acl= NULL;
#define Aaip_os_linux_use_both_acL yes
#ifdef Aaip_os_linux_use_both_acL
char *a_acl_text= NULL, *d_acl_text= NULL;
#else
char *acl_text= NULL; char *acl_text= NULL;
size_t a_acl_len= 0, d_acl_len= 0;
unsigned char *a_acl= NULL, *d_acl= NULL;
#endif
if(flag & (1 << 15)) { /* Free memory */ if(flag & (1 << 15)) { /* Free memory */
if(*names != NULL) if(*names != NULL)
@ -177,6 +186,21 @@ int aaip_get_attr_list(char *path, size_t *num_attrs, char ***names,
} }
if(flag & 1) { /* Obtain ACL */ if(flag & 1) { /* Obtain ACL */
#ifdef Aaip_os_linux_use_both_acL
/* access-ACL */
aaip_get_acl_text(path, &a_acl_text, flag & 16);
aaip_get_acl_text(path, &d_acl_text, 1);
if(a_acl_text == NULL && d_acl_text == NULL)
{ret= 1; goto ex;}
ret= aaip_encode_both_acl(a_acl_text, d_acl_text,
&acl_len, &acl, (flag & 2));
if(ret <= 0)
goto ex;
#else /* Aaip_os_linux_use_both_acL */
/* access-ACL */ /* access-ACL */
ret= aaip_get_acl_text(path, &acl_text, flag & 16); ret= aaip_get_acl_text(path, &acl_text, flag & 16);
if(ret <= 0) if(ret <= 0)
@ -209,24 +233,40 @@ int aaip_get_attr_list(char *path, size_t *num_attrs, char ***names,
acl_len= a_acl_len; acl_len= a_acl_len;
} }
#endif /* ! Aaip_os_linux_use_both_acL */
/* Set as attribute with empty name */; /* Set as attribute with empty name */;
(*names)[*num_attrs]= strdup(""); (*names)[*num_attrs]= strdup("");
if((*names)[*num_attrs] == NULL) if((*names)[*num_attrs] == NULL)
{ret= -1; goto ex;} {ret= -1; goto ex;}
(*values)[*num_attrs]= (char *) acl; (*values)[*num_attrs]= (char *) acl;
acl= NULL;
(*value_lengths)[*num_attrs]= acl_len; (*value_lengths)[*num_attrs]= acl_len;
(*num_attrs)++; (*num_attrs)++;
} }
ret= 1; ret= 1;
ex:; ex:;
#ifdef Aaip_os_linux_use_both_acL
if(a_acl_text != NULL)
aaip_get_acl_text("", &a_acl_text, 1 << 15); /* free */
if(d_acl_text != NULL)
aaip_get_acl_text("", &d_acl_text, 1 << 15); /* free */
#else /* Aaip_os_linux_use_both_acL */
if(a_acl != NULL) if(a_acl != NULL)
free(a_acl); free(a_acl);
if(d_acl != NULL) if(d_acl != NULL)
free(d_acl); free(d_acl);
if(acl != NULL)
free(acl);
if(acl_text != NULL) if(acl_text != NULL)
aaip_get_acl_text("", &acl_text, 1 << 15); /* free */ aaip_get_acl_text("", &acl_text, 1 << 15); /* free */
#endif /* ! Aaip_os_linux_use_both_acL */
if(ret <= 0 || (flag & (1 << 15))) { if(ret <= 0 || (flag & (1 << 15))) {
if(list != NULL) if(list != NULL)
free(list); free(list);

View File

@ -65,10 +65,10 @@ static int aaip_encode_pair(char *name, size_t attr_length, char *attr,
@return >0 is the number of SUSP fields generated, @return >0 is the number of SUSP fields generated,
0 means error 0 means error
*/ */
unsigned int aaip_encode(char aa_name[2], size_t aaip_encode(char aa_name[2],
unsigned int num_attrs, char **names, size_t num_attrs, char **names,
size_t *value_lengths, char **values, size_t *value_lengths, char **values,
size_t *result_len, unsigned char **result, int flag) size_t *result_len, unsigned char **result, int flag)
{ {
size_t mem_size= 0, comp_size; size_t mem_size= 0, comp_size;
unsigned int number_of_fields, i, num_recs, total_recs= 0, ret; unsigned int number_of_fields, i, num_recs, total_recs= 0, ret;
@ -426,50 +426,174 @@ group_by_name:;
} }
/* Remove the entries user::??? , group::??? , other::??? , other:??? int aaip_encode_both_acl(char *a_acl_text, char *d_acl_text,
from an ACL in long text form if they match the bits in st_mode. size_t *result_len, unsigned char **result, int flag)
@param flag bit0= do not remove entries, only determine return value {
bit1= like bit0 but return immediately if non-st_mode int ret;
ACL entry is found size_t a_acl_len= 0, d_acl_len= 0, acl_len= 0;
unsigned char *a_acl= NULL, *d_acl= NULL, *acl= NULL;
if(a_acl_text != NULL) {
ret= aaip_encode_acl(a_acl_text, &a_acl_len, &a_acl, flag & 3);
if(ret <= 0)
goto ex;
}
if(d_acl_text != NULL) {
ret= aaip_encode_acl(d_acl_text, &d_acl_len, &d_acl, (flag & 3) | 4);
if(ret <= 0)
goto ex;
}
if(a_acl == NULL) {
acl= d_acl;
d_acl= NULL;
acl_len= d_acl_len;
} else if (d_acl == NULL) {
acl= a_acl;
a_acl= NULL;
acl_len= a_acl_len;
} else {
acl= calloc(a_acl_len + d_acl_len + 1, 1);
if(acl == NULL)
{ret = -1; goto ex;}
memcpy(acl, a_acl, a_acl_len);
memcpy(acl + a_acl_len, d_acl, d_acl_len);
acl_len= a_acl_len + d_acl_len;
}
*result= acl;
*result_len= acl_len;
ret= 1;
ex:;
if(a_acl != NULL)
free(a_acl);
if(d_acl != NULL)
free(d_acl);
return(ret);
}
/* Linux man 5 acl says:
The permissions defined by ACLs are a superset of the permissions speci-
fied by the file permission bits. The permissions defined for the file
owner correspond to the permissions of the ACL_USER_OBJ entry. The per-
missions defined for the file group correspond to the permissions of the
ACL_GROUP_OBJ entry, if the ACL has no ACL_MASK entry. If the ACL has an
ACL_MASK entry, then the permissions defined for the file group corre-
spond to the permissions of the ACL_MASK entry. The permissions defined
for the other class correspond to the permissions of the ACL_OTHER_OBJ
entry.
Modification of the file permission bits results in the modification of
the permissions in the associated ACL entries. Modification of the per-
missions in the ACL entries results in the modification of the file per-
mission bits.
*/ */
int aaip_cleanout_st_mode(char *acl_text, mode_t st_mode, int flag) /* Analyze occurence of ACL tag types in long text form. If not disabled by
parameter flag remove the entries of type "user::" , "group::" , "other::" ,
or "other:" from an ACL in long text form if they match the bits in st_mode
as described by man 2 stat and man 5 acl.
@param acl_text The text to be analyzed and eventually shortened.
@param st_mode The component of struct stat which tells POSIX permission
bits and eventually shall take equivalent bits as read
from the ACL. The caller should submit a pointer
to the st_mode variable which holds permissions as
indicated by stat(2) resp. ECMA-119 and RRIP data.
@param flag bit0= do not remove entries, only determine return value
bit1= like bit0 but return immediately if a non-st_mode
ACL entry is found
bit2= update *st_mode by acl_text
("user::" -> S_IRWXU, "mask::"|"group::" -> S_IRWXG,
"other::" -> S_IRWXO)
bit3= update acl_text by *st_mode (same mapping as bit 2
but with reversed transfer direction)
@return <0 failure
>=0 tells in its bits which tag types were found.
The first three tell which types deviate from the
corresponding st_mode settings:
bit0= "other::" overrides S_IRWXO
bit1= "group::" overrides S_IRWXG (no "mask::" found)
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 (no "mask::" found)
bit5= "user::" matches S_IRWXU
Given the nature of ACLs nearly all combinations are
possible although some would come from invalid ACLs.
bit6= other ACL tag types are present. Particularly:
bit7= "user:...:" is present
bit8= "group:...:" is present
bit9= "mask::" is present
*/
int aaip_cleanout_st_mode(char *acl_text, mode_t *in_st_mode, int flag)
{ {
char *rpt, *wpt, *npt, *cpt; char *rpt, *wpt, *npt, *cpt;
mode_t m; mode_t m, list_mode, st_mode;
int overriders= 0; int tag_types= 0, has_mask= 0, do_cleanout = 0;
list_mode= st_mode= *in_st_mode;
do_cleanout = !(flag & 15);
has_mask= strncmp(acl_text, "mask:", 5) == 0 ||
strstr(acl_text, "\nmask:") != NULL;
if(has_mask && (flag & 2))
return(64 | 512);
for(npt= wpt= rpt= acl_text; *npt != 0; rpt= npt + 1) { for(npt= wpt= rpt= acl_text; *npt != 0; rpt= npt + 1) {
npt= strchr(rpt, '\n'); npt= strchr(rpt, '\n');
if(npt == NULL) if(npt == NULL)
npt= rpt + strlen(rpt); npt= rpt + strlen(rpt);
if(strncmp(rpt, "user::", 6) == 0 && npt - rpt == 9) { if(strncmp(rpt, "user:", 5) == 0) {
cpt= rpt + 6; if(rpt[5] == ':' && npt - rpt == 9) {
m= 0; cpt= rpt + 6;
if(cpt[0] == 'r') m= 0;
m|= S_IRUSR; if(cpt[0] == 'r')
if(cpt[1] == 'w') m|= S_IRUSR;
m|= S_IWUSR; if(cpt[1] == 'w')
if(cpt[2] == 'x') m|= S_IWUSR;
m|= S_IXUSR; if(cpt[2] == 'x')
if((st_mode & S_IRWXU) == (m & S_IRWXU)) { m|= S_IXUSR;
overriders|= 32; list_mode= (list_mode & ~S_IRWXU) | m;
if((st_mode & S_IRWXU) == (m & S_IRWXU)) {
tag_types|= 32;
continue; continue;
}
if(flag & 8) {
cpt[0]= st_mode & S_IRUSR ? 'r' : '-';
cpt[1]= st_mode & S_IWUSR ? 'w' : '-';
cpt[2]= st_mode & S_IXUSR ? 'x' : '-';
}
tag_types|= 4;
} else {
tag_types|= 64 | 128;
} }
overriders|= 4; } else if(strncmp(rpt, "group:", 6) == 0) {
} else if(strncmp(rpt, "group::", 7) == 0 && npt - rpt == 10) { if(rpt[6] == ':' && npt - rpt == 10 && !has_mask) {
cpt= rpt + 7; /* oddly: mask overrides group in st_mode */
m= 0; cpt= rpt + 7;
if(cpt[0] == 'r') m= 0;
m|= S_IRGRP; if(cpt[0] == 'r')
if(cpt[1] == 'w') m|= S_IRGRP;
m|= S_IWGRP; if(cpt[1] == 'w')
if(cpt[2] == 'x') m|= S_IWGRP;
m|= S_IXGRP; if(cpt[2] == 'x')
if((st_mode & S_IRWXG) == (m & S_IRWXG)) { m|= S_IXGRP;
overriders|= 16; list_mode= (list_mode & ~S_IRWXG) | m;
if((st_mode & S_IRWXG) == (m & S_IRWXG)) {
tag_types|= 16;
continue; continue;
}
if(flag & 8) {
cpt[0]= st_mode & S_IRGRP ? 'r' : '-';
cpt[1]= st_mode & S_IWGRP ? 'w' : '-';
cpt[2]= st_mode & S_IXGRP ? 'x' : '-';
}
tag_types|= 2;
} else {
if(rpt[6] == ':' && npt - rpt == 10)
tag_types|= 1024;
else
tag_types|= 64 | 256;
} }
overriders|= 2;
} else if(strncmp(rpt, "other::", 7) == 0 && npt - rpt == 10) { } else if(strncmp(rpt, "other::", 7) == 0 && npt - rpt == 10) {
cpt= rpt + 7; cpt= rpt + 7;
others_st_mode:; others_st_mode:;
@ -480,66 +604,103 @@ others_st_mode:;
m|= S_IWOTH; m|= S_IWOTH;
if(cpt[2] == 'x') if(cpt[2] == 'x')
m|= S_IXOTH; m|= S_IXOTH;
list_mode= (list_mode & ~S_IRWXO) | m;
if((st_mode & S_IRWXO) == (m & S_IRWXO)) { if((st_mode & S_IRWXO) == (m & S_IRWXO)) {
overriders|= 8; tag_types|= 8;
continue; continue;
} }
overriders|= 1; if(flag & 8) {
cpt[0]= st_mode & S_IROTH ? 'r' : '-';
cpt[1]= st_mode & S_IWOTH ? 'w' : '-';
cpt[2]= st_mode & S_IXOTH ? 'x' : '-';
}
tag_types|= 1;
} else if(strncmp(rpt, "other:", 6) == 0 && npt - rpt == 9) { } else if(strncmp(rpt, "other:", 6) == 0 && npt - rpt == 9) {
cpt= rpt + 7; cpt= rpt + 7;
goto others_st_mode; goto others_st_mode;
} else if(strncmp(rpt, "mask::", 6) == 0 && npt - rpt == 9) {
/* oddly: mask overrides group in st_mode */
cpt= rpt + 6;
mask_st_mode:;
m= 0;
if(cpt[0] == 'r')
m|= S_IRGRP;
if(cpt[1] == 'w')
m|= S_IWGRP;
if(cpt[2] == 'x')
m|= S_IXGRP;
list_mode= (list_mode & ~S_IRWXG) | m;
tag_types|= 64 | 512;
if(flag & 8) {
cpt[0]= st_mode & S_IRGRP ? 'r' : '-';
cpt[1]= st_mode & S_IWGRP ? 'w' : '-';
cpt[2]= st_mode & S_IXGRP ? 'x' : '-';
}
} else if(strncmp(rpt, "mask:", 5) == 0 && npt - rpt == 8) {
cpt= rpt + 5;
goto mask_st_mode;
} else if(*rpt != 0) { } else if(*rpt != 0) {
overriders|= 64; tag_types|= 64;
} }
if (flag & 2) if (flag & 2)
return overriders; goto ex;
if(wpt == rpt) { if(wpt == rpt) {
wpt= npt + 1; wpt= npt + 1;
continue; continue;
} }
if(!(flag & 3)) if(do_cleanout)
memmove(wpt, rpt, 1 + npt - rpt); memmove(wpt, rpt, 1 + npt - rpt);
wpt+= 1 + npt - rpt; wpt+= 1 + npt - rpt;
} }
if(!(flag & 3)) { if(do_cleanout) {
if(wpt == acl_text) if(wpt == acl_text)
*wpt= 0; *wpt= 0;
else if(*(wpt - 1) != 0) else if(*(wpt - 1) != 0)
*wpt= 0; *wpt= 0;
} }
return(overriders); ex:;
if(flag & 4)
*in_st_mode= list_mode;
return(tag_types);
} }
/* Important: acl_text must provide 32 bytes more than its current length ! /* Important: acl_text must provide 42 bytes more than its current length !
*/ */
int aaip_add_acl_st_mode(char *acl_text, mode_t st_mode, int flag) int aaip_add_acl_st_mode(char *acl_text, mode_t st_mode, int flag)
{ {
char *wpt; char *wpt;
int overriders= 0; int tag_types= 0;
overriders = aaip_cleanout_st_mode(acl_text, st_mode, 1); tag_types = aaip_cleanout_st_mode(acl_text, &st_mode, 1);
if(!(overriders & (4 | 32))) { if(!(tag_types & (4 | 32))) {
wpt= acl_text + strlen(acl_text); wpt= acl_text + strlen(acl_text);
sprintf(wpt, "user::%c%c%c\n", sprintf(wpt, "user::%c%c%c\n",
st_mode & S_IRUSR ? 'r' : '-', st_mode & S_IRUSR ? 'r' : '-',
st_mode & S_IWUSR ? 'w' : '-', st_mode & S_IWUSR ? 'w' : '-',
st_mode & S_IXUSR ? 'x' : '-'); st_mode & S_IXUSR ? 'x' : '-');
} }
if(!(overriders & (2 | 16))) { if(!(tag_types & (2 | 16 | 1024))) {
wpt= acl_text + strlen(acl_text); wpt= acl_text + strlen(acl_text);
sprintf(wpt, "group::%c%c%c\n", sprintf(wpt, "group::%c%c%c\n",
st_mode & S_IRGRP ? 'r' : '-', st_mode & S_IRGRP ? 'r' : '-',
st_mode & S_IWGRP ? 'w' : '-', st_mode & S_IWGRP ? 'w' : '-',
st_mode & S_IXGRP ? 'x' : '-'); st_mode & S_IXGRP ? 'x' : '-');
} }
if(!(overriders & (1 | 8))) { if(!(tag_types & (1 | 8))) {
wpt= acl_text + strlen(acl_text); wpt= acl_text + strlen(acl_text);
sprintf(wpt, "other::%c%c%c\n", sprintf(wpt, "other::%c%c%c\n",
st_mode & S_IROTH ? 'r' : '-', st_mode & S_IROTH ? 'r' : '-',
st_mode & S_IWOTH ? 'w' : '-', st_mode & S_IWOTH ? 'w' : '-',
st_mode & S_IXOTH ? 'x' : '-'); st_mode & S_IXOTH ? 'x' : '-');
} }
if((tag_types & (128 | 256)) && !(tag_types & 512)) {
wpt= acl_text + strlen(acl_text);
sprintf(wpt, "mask::%c%c%c\n",
st_mode & S_IRGRP ? 'r' : '-',
st_mode & S_IWGRP ? 'w' : '-',
st_mode & S_IXGRP ? 'x' : '-');
}
return(1); return(1);
} }

View File

@ -32,10 +32,9 @@
@return >0 is the number of SUSP fields generated, @return >0 is the number of SUSP fields generated,
0 means error 0 means error
*/ */
unsigned int aaip_encode(char aa_name[2], size_t aaip_encode(char aa_name[2], size_t num_attrs, char **names,
unsigned int num_attrs, char **names, size_t *value_lengths, char **values,
size_t *value_lengths, char **values, size_t *result_len, unsigned char **result, int flag);
size_t *result_len, unsigned char **result, int flag);
/* ------ ACL representation ------ */ /* ------ ACL representation ------ */
@ -58,38 +57,73 @@ int aaip_encode_acl(char *acl_text,
size_t *result_len, unsigned char **result, int flag); size_t *result_len, unsigned char **result, int flag);
/* Remove the entries of type "user::" , "group::" , "other::" , "other:" /* Convert an "access" and "default" ACL from long text form into the value
from an ACL in long text form if they match the bits in st_mode. of an Arbitrary Attribute. According to AAIP 0.2 this value is to be stored
@param acl_text The text to be shortened together with an empty name.
@param st_mode The component of struct stat which shall take the @param a_acl_text The "access" ACL in long text form.
removed information. The caller should submit the st_mode Submit NULL if there is no such ACL to be encoded.
variable which holds permissions as indicated by ECMA-119 @param d_acl_text The "default" ACL in long text form.
and RRIP data. Submit NULL if there is no such ACL to be encoded.
@param result_len Number of bytes in the resulting value
@param result *result will point to the start of the result string.
This is malloc() memory which needs to be freed when
no longer needed
@param flag Bitfield for control purposes
bit0= count only
bit1= use numeric qualifiers rather than names
@return >0 means ok
0 means error
*/
int aaip_encode_both_acl(char *a_acl_text, char *d_acl_text,
size_t *result_len, unsigned char **result, int flag);
/* Analyze occurence of ACL tag types in long text form. If not disabled by
parameter flag remove the entries of type "user::" , "group::" , "other::" ,
or "other:" from an ACL in long text form if they match the bits in st_mode
as described by man 2 stat and man 5 acl.
@param acl_text The text to be analyzed and eventually shortened.
@param st_mode The component of struct stat which tells POSIX permission
bits and eventually shall take equivalent bits as read
from the ACL. The caller should submit a pointer
to the st_mode variable which holds permissions as
indicated by stat(2) resp. ECMA-119 and RRIP data.
@param flag bit0= do not remove entries, only determine return value @param flag bit0= do not remove entries, only determine return value
bit1= like bit0 but return immediately if a non-st_mode bit1= like bit0 but return immediately if a non-st_mode
ACL entry is found ACL entry is found
bit2= update *st_mode by acl_text
("user::" -> S_IRWXU, "mask::"|"group::" -> S_IRWXG,
"other::" -> S_IRWXO)
bit3= update acl_text by *st_mode (same mapping as bit 2
but with reversed transfer direction)
@return <0 failure @return <0 failure
>=0 tells in its bits which tag types are present. >=0 tells in its bits which tag types were found.
The first three tell which types deviate from the The first three tell which types deviate from the
corresponding st_mode settings: corresponding st_mode settings:
bit0= "other::" overrides S_IRWXO bit0= "other::" overrides S_IRWXO
bit1= "group::" overrides S_IRWXG bit1= "group::" overrides S_IRWXG (no "mask::" found)
bit2= "user::" overrides S_IRWXU bit2= "user::" overrides S_IRWXU
The second three tell which types comply with st_mode: The second three tell which types comply with st_mode:
bit3= "other::" matches S_IRWXO bit3= "other::" matches S_IRWXO
bit4= "group::" matches S_IRWXG bit4= "group::" matches S_IRWXG (no "mask::" found)
bit5= "user::" matches S_IRWXU bit5= "user::" matches S_IRWXU
Given the nature of ACLs all 64 combinations are Given the nature of ACLs nearly all combinations are
possible although some show inner contradictions. possible although some would come from invalid ACLs.
bit6= other ACL tag types are present bit6= other ACL tag types are present. Particularly:
bit7= "user:...:" is present
bit8= "group:...:" is present
bit9= "mask::" is present
bit10= "group::" found and "mask::" exists
*/ */
int aaip_cleanout_st_mode(char *acl_text, mode_t st_mode, int flag); int aaip_cleanout_st_mode(char *acl_text, mode_t *st_mode, int flag);
/* Append entries of type "user::" , "group::" , "other::" representing the /* Append entries of type "user::" , "group::" , "other::" representing the
permission bits in st_mode if those tag types are not present in the ACL permission bits in st_mode if those tag types are not present in the ACL
text. text. Append "mask::" if missing although "user:...:" or "group:...:"
@param acl_text The text to be made longer. It must offer 33 bytes more is present. Eventually set it to S_IRWXG bits of st_mode.
@param acl_text The text to be made longer. It must offer 43 bytes more
storage space than its length when it is submitted. storage space than its length when it is submitted.
@param st_mode The component of struct stat which shall provide the @param st_mode The component of struct stat which shall provide the
permission information. permission information.

View File

@ -481,9 +481,8 @@ void lfs_free(IsoFileSource *src)
static static
int lfs_get_aa_string(IsoFileSource *src, unsigned char **aa_string, int flag) int lfs_get_aa_string(IsoFileSource *src, unsigned char **aa_string, int flag)
{ {
unsigned int uret;
int ret; int ret;
size_t num_attrs = 0, *value_lengths = NULL, result_len; size_t num_attrs = 0, *value_lengths = NULL, result_len, sret;
char *path = NULL, **names = NULL, **values = NULL; char *path = NULL, **names = NULL, **values = NULL;
unsigned char *result = NULL; unsigned char *result = NULL;
@ -500,9 +499,9 @@ int lfs_get_aa_string(IsoFileSource *src, unsigned char **aa_string, int flag)
ret = ISO_FILE_ERROR; ret = ISO_FILE_ERROR;
goto ex; goto ex;
} }
uret = aaip_encode("AA", (unsigned int) num_attrs, names, sret = aaip_encode("AA", num_attrs, names,
value_lengths, values, &result_len, &result, 0); value_lengths, values, &result_len, &result, 0);
if (uret == 0) { if (sret == 0) {
ret = ISO_OUT_OF_MEM; ret = ISO_OUT_OF_MEM;
goto ex; goto ex;
} }

View File

@ -4126,6 +4126,7 @@ int aaip_xinfo_func(void *data, int flag);
#endif /* Libisofs_with_aaiP */ #endif /* Libisofs_with_aaiP */
/* ts A90116 */
/** /**
* Get an eventual ACL which is associated with the node. * Get an eventual ACL which is associated with the node.
* The result will be in "long" text form as of man acl resp. acl_to_text(). * The result will be in "long" text form as of man acl resp. acl_to_text().
@ -4142,7 +4143,7 @@ int aaip_xinfo_func(void *data, int flag);
* (Linux directories can have a "default" ACL which influences * (Linux directories can have a "default" ACL which influences
* the permissions of newly created files.) * the permissions of newly created files.)
* bit4= if no ACL is available: return *text == NULL * bit4= if no ACL is available: return *text == NULL
else: produce ACL from POSIX permissions * else: produce ACL from POSIX permissions
* bit15= free memory and return 1 * bit15= free memory and return 1
* @return * @return
* 2 ACL produced from POSIX permissions * 2 ACL produced from POSIX permissions
@ -4155,15 +4156,47 @@ int aaip_xinfo_func(void *data, int flag);
int iso_node_get_acl_text(IsoNode *node, char **text, int flag); int iso_node_get_acl_text(IsoNode *node, char **text, int flag);
/* ts A90119 */
/**
* Set the ACL of the given node to the list in parameter text or delete it.
*
* @param node
* The node that is to be manipulated.
* @param text
* The ACL text to be set into effect. NULL will delete an eventually
* existing ACL of the node.
* @param flag
* Bitfield for control purposes
* bit0= set "default" ACL rather than "access" ACL
* (Linux directories can have a "default" ACL which influences
* the permissions of newly created files.)
* bit1= ignore text but rather update eventual "access" ACL to the POSIX
* permissions of node. If no ACL exists, then do nothing and
* return success.
* @return
* > 0 success
* <=0 failure
*/
int iso_node_set_acl_text(IsoNode *node, char *text, int flag);
/* ts A90118 */
/* Set the ACL of the given file in the local filesystem to a given list /* Set the ACL of the given file in the local filesystem to a given list
in long text form. * in long text form.
@param disk_path Path to the file *
@param text The input text (0 terminated, ACL long text form) * @param disk_path
@param flag Bitfield for control purposes * Path to the file
bit0= set default ACL rather than access ACL * @param text
@return >0 ok * The input text (0 terminated, ACL long text form)
0 no ACL manipulation adapter available * @param flag
-1 failure of system ACL service (see errno) * Bitfield for control purposes
* bit0= set default ACL rather than access ACL
* @return
* > 0 ok
* 0 no ACL manipulation adapter available
* -1 failure of system ACL service (see errno)
*
* @since 0.6.14
*/ */
int iso_local_set_acl_text(char *disk_path, char *text, int flag); int iso_local_set_acl_text(char *disk_path, char *text, int flag);

View File

@ -290,26 +290,12 @@ void iso_node_set_permissions(IsoNode *node, mode_t mode)
node->mode = (node->mode & S_IFMT) | (mode & ~S_IFMT); node->mode = (node->mode & S_IFMT) | (mode & ~S_IFMT);
#ifdef Libisofs_with_aaiP #ifdef Libisofs_with_aaiP
/* ts A90119 */
/* Linux man 5 acl says: /* If the node has ACL info : update ACL */;
The permissions defined by ACLs are a superset of the permissions speci- iso_node_set_acl_text(node, "", 2);
fied by the file permission bits. The permissions defined for the file
owner correspond to the permissions of the ACL_USER_OBJ entry. The per-
missions defined for the file group correspond to the permissions of the
ACL_GROUP_OBJ entry, if the ACL has no ACL_MASK entry. If the ACL has an
ACL_MASK entry, then the permissions defined for the file group corre-
spond to the permissions of the ACL_MASK entry. The permissions defined
for the other class correspond to the permissions of the ACL_OTHER_OBJ
entry.
Modification of the file permission bits results in the modification of /* >>> actually iso_node_set_permissions() would need a return value now */
the permissions in the associated ACL entries. Modification of the per-
missions in the ACL entries results in the modification of the file per-
mission bits.
*/
/* >>> if the node has ACL info : */
/* >>> update ACL */;
#endif #endif
@ -1439,6 +1425,60 @@ int iso_node_get_attrs(IsoNode *node, size_t *num_attrs,
} }
/* ts A90121 */
int iso_node_set_attrs(IsoNode *node, size_t num_attrs, char **names,
size_t *value_lengths, char **values, int flag)
{
int ret;
size_t sret, result_len;
unsigned char *result;
sret = aaip_encode("AA", num_attrs, names, value_lengths, values,
&result_len, &result, 0);
if (sret == 0)
return ISO_OUT_OF_MEM;
ret = iso_node_remove_xinfo(node, aaip_xinfo_func);
if (ret < 0)
return ret;
ret = iso_node_add_xinfo(node, aaip_xinfo_func, result);
if (ret < 0)
return ret;
if (ret == 0) {
/* >>> something is messed up with xinfo */;
return ISO_ERROR;
}
return 1;
}
static
int iso_decode_acl(unsigned char *v_data, size_t v_len, size_t *consumed,
char **text, size_t *text_fill, int flag)
{
int ret;
ret = aaip_decode_acl(v_data, v_len,
consumed, NULL, (size_t) 0, text_fill, 1);
if (ret <= 0)
return 0;
if (text_fill == 0)
return 0;
*text = calloc(*text_fill + 42, 1); /* 42 for aaip_update_acl_st_mode */
if (*text == NULL)
return ISO_OUT_OF_MEM;
ret = aaip_decode_acl(v_data, v_len,
consumed, *text, *text_fill, text_fill, 0);
if (ret <= 0) {
free(*text);
return 0;
}
return ret;
}
/* ts A90116 */ /* ts A90116 */
int iso_node_get_acl_text(IsoNode *node, char **text, int flag) int iso_node_get_acl_text(IsoNode *node, char **text, int flag)
{ {
@ -1486,29 +1526,17 @@ int iso_node_get_acl_text(IsoNode *node, char **text, int flag)
v_len -= consumed; v_len -= consumed;
} }
ret = aaip_decode_acl(v_data, v_len, ret = iso_decode_acl(v_data, v_len, &consumed, text, &text_fill, 0);
&consumed, NULL, (size_t) 0, &text_fill, 1); if (ret == 0)
if (ret <= 0)
goto bad_decode; goto bad_decode;
if (text_fill == 0) { if (ret < 0)
ret = 0;
goto ex; goto ex;
}
*text = calloc(text_fill + 32, 1); /* 32 for aaip_update_acl_st_mode */
if (*text == NULL) {
ret = ISO_OUT_OF_MEM;
goto ex;
}
ret = aaip_decode_acl(v_data, v_len,
&consumed, *text, text_fill, &text_fill, 0);
if (ret <= 0)
goto bad_decode;
break; break;
} }
if (*text == NULL && !(flag & 16)) { if (*text == NULL && !(flag & 16)) {
from_posix = 1; from_posix = 1;
*text = calloc(32, 1); /* 32 for aaip_update_acl_st_mode */ *text = calloc(42, 1); /* 42 for aaip_update_acl_st_mode */
} }
if (*text != NULL) { if (*text != NULL) {
st_mode = iso_node_get_permissions(node); st_mode = iso_node_get_permissions(node);
@ -1543,6 +1571,199 @@ bad_decode:;
} }
/* ts A90119 */
int iso_node_set_acl_text(IsoNode *node, char *acl_text, int flag)
{
size_t num_attrs = 0, *value_lengths = NULL, i, consumed;
size_t a_text_fill = 0, d_text_fill = 0;
size_t v_len, acl_len= 0;
char **names = NULL, **values = NULL, *a_text = NULL, *d_text = NULL;
char **new_names, **new_values;
size_t *new_value_lengths;
char **tpt;
unsigned char *v_data, *acl= NULL;
int ret;
mode_t st_mode;
#ifdef Libisofs_with_aaiP
if (flag & 2) { /* want to update ACL by st_mode */
st_mode = iso_node_get_permissions(node);
} else {
/* >>> validate and rectify text */;
}
ret = iso_node_get_attrs(node, &num_attrs, &names,
&value_lengths, &values, 0);
if (ret < 0)
return ret;
for(i = 0; i < num_attrs; i++) {
if (names[i][0]) /* searching the empty name */
continue;
v_data = (unsigned char *) values[i];
v_len = value_lengths[i];
/* "access" ACL */;
ret = iso_decode_acl(v_data, v_len, &consumed, &a_text, &a_text_fill,
0);
if (ret == 0)
goto bad_decode;
if (ret < 0)
goto ex;
if (ret == 2) {
/* "default" ACL */;
v_data += consumed;
v_len -= consumed;
ret = iso_decode_acl(v_data, v_len, &consumed, &d_text,
&d_text_fill, 0);
if (ret == 0)
goto bad_decode;
if (ret < 0)
goto ex;
}
if (flag & 2) {
/* Update "access" ACL by st_mode */
if (a_text == NULL) {
ret = 1;
goto ex;
}
ret = aaip_cleanout_st_mode(a_text, &st_mode, 8);
if (ret < 0)
goto bad_decode;
} else {
if (flag & 1)
tpt = &d_text;
else
tpt = &a_text;
if (*tpt != NULL) {
free(*tpt);
*tpt = NULL;
}
if (acl_text != 0) {
*tpt = calloc(strlen(acl_text) + 1, 1);
if (*tpt == NULL) {
ret = ISO_OUT_OF_MEM;
goto ex;
}
memcpy(*tpt, acl_text, strlen(acl_text));
}
}
if (a_text != NULL || d_text != NULL)
ret = aaip_encode_both_acl(a_text, d_text, &acl_len, &acl, 0);
else
ret = 1;
if (ret <= 0) {
ret = ISO_OUT_OF_MEM;
goto ex;
}
/* replace variable value */;
if (values[i] != NULL)
free(values[i]);
values[i] = (char *) acl;
acl = NULL;
value_lengths[i] = acl_len;
/* Encode attributes and attach to node */
ret = iso_node_set_attrs(node, num_attrs, names, value_lengths, values,
0);
goto ex;
}
/* There is no ACL yet */
if ((flag & 2) || acl_text == NULL) {
/* thus no need to update ACL by st_mode or to delete ACL */
ret = 1;
goto ex;
}
if (flag & 1)
ret = aaip_encode_both_acl(NULL, acl_text, &acl_len, &acl, 0);
else
ret = aaip_encode_both_acl(acl_text, NULL, &acl_len, &acl, 0);
if (ret <= 0) {
/* >>> cannot encode */;
ret = ISO_ERROR;
goto ex;
}
/* Enlarge attribute list */
new_names = realloc(names, (num_attrs + 1) * sizeof(char *));
if (new_names == NULL) {
ret = ISO_OUT_OF_MEM;
goto ex;
}
names = new_names;
new_values = realloc(values, (num_attrs + 1) * sizeof(char *));
if (new_values == NULL) {
ret = ISO_OUT_OF_MEM;
goto ex;
}
values = new_values;
new_value_lengths = realloc(value_lengths,
(num_attrs + 1) * sizeof(size_t));
if (new_value_lengths == NULL) {
ret = ISO_OUT_OF_MEM;
goto ex;
}
value_lengths = new_value_lengths;
/* Set new ACL attribute */
names[num_attrs] = strdup("");
if (names[num_attrs] == NULL) {
ret = ISO_OUT_OF_MEM;
goto ex;
}
values[num_attrs] = (char *) acl;
acl = NULL;
value_lengths[num_attrs] = acl_len;
num_attrs++;
/* Encode attributes and attach to node */
ret = iso_node_set_attrs(node, num_attrs, names, value_lengths, values, 0);
if (ret < 0)
goto ex;
ret = 1;
ex:;
iso_node_get_attrs(node, &num_attrs, &names,
&value_lengths, &values, 1 << 15); /* free memory */
if (a_text != NULL)
free(a_text);
if (d_text != NULL)
free(d_text);
if(acl != NULL)
free(acl);
return ret;
bad_decode:;
/* >>> something is wrong with the attribute value */;
/* >>> invent better error code */
ret = ISO_ERROR;
goto ex;
#else /* Libisofs_with_aaiP */
if (text != NULL) {
/* >>> No ACL enabled in program code */;
return(0);
}
return (1);
#endif /* ! Libisofs_with_aaiP */
}
/* ts A90118 */
int iso_local_set_acl_text(char *disk_path, char *text, int flag) int iso_local_set_acl_text(char *disk_path, char *text, int flag)
{ {