diff --git a/doc/susp_aaip_0_2.txt b/doc/susp_aaip_0_2.txt index 6821704..473e48a 100644 --- a/doc/susp_aaip_0_2.txt +++ b/doc/susp_aaip_0_2.txt @@ -281,8 +281,8 @@ Example: User id number 1001 gets associated with user name "lisa" Specification of the ER System Use Entry Values for AAIP: This ER system entry shall only be present if the ER entry of RRIP is present. -To be compliant with SUSP-1.12, this entry must be present and ES entries have -to mark RRIP and AAIP entries. +To be compliant with SUSP-1.12, this ER entry must be present if AAIP entries +are present, and ES entries have to mark RRIP and AAIP entries. If for some reason compliance with SUSP-1.10 is intended, then this ER entry and the ES entries must not be present, although SUSP-1.10 would allow ER. (See below: Compatibility considerations.) @@ -308,7 +308,7 @@ The corresponding Source Length is 62. Compatibility Considerations This extension is supposed not to disturb any reader system which complies -to this SUSP-1.10 demand: +to SUSP-1.10: "6.2 Requirements for a Receiving System [...] Any System Use Field which the receiving system does not recognize @@ -329,7 +329,7 @@ SUSP-1.10 does not specify ES entires at all and allows to have extension entries without announcing them by a ER entry. So if a second ER entry is not bearable, then the SUSP-1.10 downgrade of of AAIP allows to omit the AAIP ER and the ES entries. But if there is the AAIP ER then there must be ES -at the appropriate paces. +at the appropriate places. ------------------------------------------------------------------------------- diff --git a/libisofs/aaip-os-freebsd.c b/libisofs/aaip-os-freebsd.c index 8a38864..52286e8 100644 --- a/libisofs/aaip-os-freebsd.c +++ b/libisofs/aaip-os-freebsd.c @@ -169,7 +169,7 @@ int aaip_get_attr_list(char *path, size_t *num_attrs, char ***names, 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); + ret= aaip_encode_acl(acl_text, (mode_t) 0, &a_acl_len, &a_acl, flag & 2); if(ret <= 0) goto ex; aaip_get_acl_text("", &acl_text, 1 << 15); /* free */ diff --git a/libisofs/aaip-os-linux.c b/libisofs/aaip-os-linux.c index 5cac1f7..f4acd30 100644 --- a/libisofs/aaip-os-linux.c +++ b/libisofs/aaip-os-linux.c @@ -234,7 +234,7 @@ int aaip_get_attr_list(char *path, size_t *num_attrs, char ***names, 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, + ret= aaip_encode_both_acl(a_acl_text, d_acl_text, (mode_t) 0, &acl_len, &acl, (flag & 2)); if(ret <= 0) goto ex; diff --git a/libisofs/aaip_0_2.c b/libisofs/aaip_0_2.c index 48a6e95..cc8fe19 100644 --- a/libisofs/aaip_0_2.c +++ b/libisofs/aaip_0_2.c @@ -203,7 +203,7 @@ static int aaip_encode_pair(char *name, size_t attr_length, char *attr, /* ----------- Encoder for ACLs ----------- */ -static ssize_t aaip_encode_acl_text(char *acl_text, +static ssize_t aaip_encode_acl_text(char *acl_text, mode_t st_mode, size_t result_size, unsigned char *result, int flag); @@ -211,6 +211,7 @@ static ssize_t aaip_encode_acl_text(char *acl_text, Attribute. According to AAIP 0.2 this value is to be stored together with an empty name. @param acl_text The ACL in long text form + @param st_mode The stat(2) permission bits to be used with flag bit3 @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 @@ -219,17 +220,20 @@ static ssize_t aaip_encode_acl_text(char *acl_text, bit0= count only bit1= use numeric qualifiers rather than names bit2= this is a default ACL, prepend SWITCH_MARK + bit3= check for completeness of list and eventually + fill up with entries deduced from st_mode @return >0 means ok 0 means error */ -int aaip_encode_acl(char *acl_text, +int aaip_encode_acl(char *acl_text, mode_t st_mode, size_t *result_len, unsigned char **result, int flag) { ssize_t bytes; *result= NULL; *result_len= 0; - bytes= aaip_encode_acl_text(acl_text, (size_t) 0, NULL, 1 | (flag & 6)); + bytes= aaip_encode_acl_text(acl_text, st_mode, + (size_t) 0, NULL, 1 | (flag & (2 | 4 | 8))); if(bytes < 0) return(0); if(flag & 1) { @@ -241,7 +245,8 @@ int aaip_encode_acl(char *acl_text, return(-1); (*result)[bytes]= 0; *result_len= bytes; - bytes= aaip_encode_acl_text(acl_text, *result_len, *result, (flag & 6)); + bytes= aaip_encode_acl_text(acl_text, st_mode, *result_len, *result, + (flag & (2 | 4 | 8))); if(bytes != *result_len) { *result_len= 0; return(0); @@ -265,6 +270,21 @@ static double aaip_numeric_id(char *name, int flag) } +static int aaip_make_aaip_perms(int r, int w, int x) +{ + int perms; + + perms= 0; + if(r) + perms|= Aaip_READ; + if(w) + perms|= Aaip_WRITE; + if(x) + perms|= Aaip_EXEC; + return(perms); +} + + /* @param result_size Number of bytes to store result @param result Pointer to the start of the result string. @@ -272,14 +292,17 @@ static double aaip_numeric_id(char *name, int flag) bit0= count only, do not really produce bytes bit1= use numeric qualifiers bit2= this is a default ACL, prepend SWITCH_MARK 1 + bit3= check for completeness of list and eventually + fill up with entries deduced from st_mode @return >=0 number of bytes produced resp. counted <0 means error */ -static ssize_t aaip_encode_acl_text(char *acl_text, +static ssize_t aaip_encode_acl_text(char *acl_text, mode_t st_mode, size_t result_size, unsigned char *result, int flag) { char *rpt, *npt, *cpt; - int qualifier= 0, perms, type, i, qualifier_len= 0, num_recs; + int qualifier= 0, perms, type, i, qualifier_len= 0, num_recs, needed; + unsigned int has_u= 0, has_g= 0, has_o= 0, has_m= 0, is_trivial= 1; uid_t uid, huid; gid_t gid, hgid; ssize_t count= 0; @@ -314,11 +337,13 @@ static ssize_t aaip_encode_acl_text(char *acl_text, continue; qualifier= 0; if(strncmp(rpt, "user:", 5) == 0) { - if(cpt - rpt == 5) + if(cpt - rpt == 5) { type= Aaip_ACL_USER_OBJ; - else { + has_u++; + } else { if(cpt - (rpt + 5) >= sizeof(name)) continue; + is_trivial= 0; strncpy(name, rpt + 5, cpt - (rpt + 5)); name[cpt - (rpt + 5)]= 0; if(flag & 2) { @@ -345,11 +370,13 @@ user_by_name:; qualifier= 1; } } else if(strncmp(rpt, "group:", 6) == 0) { - if(cpt - rpt == 6) + if(cpt - rpt == 6) { type= Aaip_ACL_GROUP_OBJ; - else { + has_g++; + } else { if(cpt - (rpt + 6) >= sizeof(name)) continue; + is_trivial= 0; strncpy(name, rpt + 6, cpt - (rpt + 6)); if(flag & 2) { type= Aaip_ACL_GROUP_N; @@ -377,20 +404,16 @@ group_by_name:; } } else if(strncmp(rpt, "other:", 6) == 0) { type= Aaip_ACL_OTHER; + has_o++; } else if(strncmp(rpt, "mask:", 5) == 0) { type= Aaip_ACL_MASK; + has_m++; } else continue; - if(npt - cpt < 3) + if(npt - cpt < 4) continue; - perms= 0; - if(cpt[1] == 'r') - perms|= Aaip_READ; - if(cpt[2] == 'w') - perms|= Aaip_WRITE; - if(cpt[3] == 'x') - perms|= Aaip_EXEC; + perms= aaip_make_aaip_perms(cpt[1] == 'r', cpt[2] == 'w', cpt[3] == 'x'); if(!(flag & 1)) { if(count >= result_size) @@ -421,12 +444,43 @@ group_by_name:; count+= qualifier_len + num_recs; } } - + if (flag & 8) { + /* add eventually missing mandatory ACL entries */ + needed= (!has_u) + (!has_g) + (!has_o) + !(is_trivial || has_m); + if(flag & 1) + count+= needed; + else { + if(count + needed > result_size) + return(-1); + } + } + if ((flag & 8) && needed > 0 && !(flag & 1)) { + if(!has_u) { + perms= aaip_make_aaip_perms(st_mode & S_IRUSR, st_mode & S_IWUSR, + st_mode * S_IXUSR); + result[count++]= perms | (Aaip_ACL_USER_OBJ << 4); + } + if(!has_g) { + perms= aaip_make_aaip_perms(st_mode & S_IRGRP, st_mode & S_IWGRP, + st_mode * S_IXGRP); + result[count++]= perms | (Aaip_ACL_GROUP_OBJ << 4); + } + if(!has_o) { + perms= aaip_make_aaip_perms(st_mode & S_IROTH, st_mode & S_IWOTH, + st_mode * S_IXOTH); + result[count++]= perms | (Aaip_ACL_OTHER << 4); + } + if(!(is_trivial | has_m)) { + perms= aaip_make_aaip_perms(st_mode & S_IRGRP, st_mode & S_IWGRP, + st_mode * S_IXGRP); + result[count++]= perms | (Aaip_ACL_MASK << 4); + } + } return(count); } -int aaip_encode_both_acl(char *a_acl_text, char *d_acl_text, +int aaip_encode_both_acl(char *a_acl_text, char *d_acl_text, mode_t st_mode, size_t *result_len, unsigned char **result, int flag) { int ret; @@ -434,12 +488,13 @@ int aaip_encode_both_acl(char *a_acl_text, char *d_acl_text, 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); + ret= aaip_encode_acl(a_acl_text, st_mode, &a_acl_len, &a_acl, flag & 11); 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); + ret= aaip_encode_acl(d_acl_text, (mode_t) 0, &d_acl_len, &d_acl, + (flag & 3) | 4); if(ret <= 0) goto ex; } diff --git a/libisofs/aaip_0_2.h b/libisofs/aaip_0_2.h index 2b54ed6..cae20e5 100644 --- a/libisofs/aaip_0_2.h +++ b/libisofs/aaip_0_2.h @@ -43,6 +43,7 @@ size_t aaip_encode(char aa_name[2], size_t num_attrs, char **names, Attribute. According to AAIP 0.2 this value is to be stored together with an empty name. @param acl_text The ACL in long text form + @param st_mode The stat(2) permission bits to be used with flag bit2 @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 @@ -50,10 +51,13 @@ size_t aaip_encode(char aa_name[2], size_t num_attrs, char **names, @param flag Bitfield for control purposes bit0= count only bit1= use numeric qualifiers rather than names + bit2= this is a default ACL, prepend SWITCH_MARK + bit3= check for completeness of list and eventually + fill up with entries deduced from st_mode @return >0 means ok 0 means error */ -int aaip_encode_acl(char *acl_text, +int aaip_encode_acl(char *acl_text, mode_t st_mode, size_t *result_len, unsigned char **result, int flag); @@ -64,6 +68,7 @@ int aaip_encode_acl(char *acl_text, Submit NULL if there is no such ACL to be encoded. @param d_acl_text The "default" ACL in long text form. Submit NULL if there is no such ACL to be encoded. + @param st_mode The stat(2) permission bits to be used with flag bit2 @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 @@ -71,10 +76,12 @@ int aaip_encode_acl(char *acl_text, @param flag Bitfield for control purposes bit0= count only bit1= use numeric qualifiers rather than names + bit3= check for completeness of list and eventually + fill up with entries deduced from st_mode @return >0 means ok 0 means error */ -int aaip_encode_both_acl(char *a_acl_text, char *d_acl_text, +int aaip_encode_both_acl(char *a_acl_text, char *d_acl_text, mode_t st_mode, size_t *result_len, unsigned char **result, int flag); diff --git a/libisofs/node.c b/libisofs/node.c index 2ec3cd2..f94da6a 100644 --- a/libisofs/node.c +++ b/libisofs/node.c @@ -1612,9 +1612,8 @@ int iso_node_set_acl_text(IsoNode *node, char *acl_text, int flag) int ret; mode_t st_mode; - if (flag & 2) { /* want to update ACL by st_mode */ - st_mode = iso_node_get_permissions(node); - } else { + st_mode = iso_node_get_permissions(node); + if (!(flag & 2)) { /* want to update ACL by st_mode */ /* >>> validate and rectify text */; @@ -1677,7 +1676,8 @@ int iso_node_set_acl_text(IsoNode *node, char *acl_text, int flag) } } if (a_text != NULL || d_text != NULL) - ret = aaip_encode_both_acl(a_text, d_text, &acl_len, &acl, 2); + ret = aaip_encode_both_acl(a_text, d_text, st_mode, &acl_len, &acl, + 2 | 8); else ret = 1; if (ret <= 0) { @@ -1716,9 +1716,11 @@ int iso_node_set_acl_text(IsoNode *node, char *acl_text, int flag) goto ex; } if (flag & 1) - ret = aaip_encode_both_acl(NULL, acl_text, &acl_len, &acl, 2); + ret = aaip_encode_both_acl(NULL, acl_text, + st_mode, &acl_len, &acl, 2 | 8); else - ret = aaip_encode_both_acl(acl_text, NULL, &acl_len, &acl, 2); + ret = aaip_encode_both_acl(acl_text, NULL, + st_mode, &acl_len, &acl, 2 | 8); if (ret <= 0) { /* >>> cannot encode */;