Decoder for ACL to long text form

This commit is contained in:
Thomas Schmitt 2008-12-26 12:40:04 +00:00
parent aa16a66e33
commit 8f3f36891a
3 changed files with 306 additions and 15 deletions

View File

@ -208,6 +208,7 @@ static ssize_t aaip_encode_acl_text(char *acl_text,
@param flag Bitfield for control purposes @param flag Bitfield for control purposes
bit0= count only bit0= count only
bit1= use numeric qualifiers rather than names bit1= use numeric qualifiers rather than names
bit2= this is a default ACL, prepend SWITCH_MARK
@return >0 means ok @return >0 means ok
0 means error 0 means error
*/ */
@ -218,7 +219,7 @@ int aaip_encode_acl(char *acl_text,
*result= NULL; *result= NULL;
*result_len= 0; *result_len= 0;
bytes= aaip_encode_acl_text(acl_text, (size_t) 0, NULL, 1 | (flag & 2)); bytes= aaip_encode_acl_text(acl_text, (size_t) 0, NULL, 1 | (flag & 6));
if(bytes < 0) if(bytes < 0)
return(0); return(0);
if(flag & 1) { if(flag & 1) {
@ -230,7 +231,7 @@ int aaip_encode_acl(char *acl_text,
return(-1); return(-1);
(*result)[bytes]= 0; (*result)[bytes]= 0;
*result_len= bytes; *result_len= bytes;
bytes= aaip_encode_acl_text(acl_text, *result_len, *result, (flag & 2)); bytes= aaip_encode_acl_text(acl_text, *result_len, *result, (flag & 6));
if(bytes != *result_len) { if(bytes != *result_len) {
*result_len= 0; *result_len= 0;
return(0); return(0);
@ -255,13 +256,12 @@ static double aaip_numeric_id(char *name, int flag)
/* /*
@param result_len Number of bytes in the resulting value @param result_size Number of bytes to store result
@param result *result will point to the start of the result string. @param result Pointer 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 @param flag Bitfield for control purposes
bit0= count only, do not really produce bytes bit0= count only, do not really produce bytes
bit1= use numeric qualifiers bit1= use numeric qualifiers
bit2= this is a default ACL, prepend SWITCH_MARK 1
@return >=0 number of bytes produced resp. counted @return >=0 number of bytes produced resp. counted
<0 means error <0 means error
*/ */
@ -278,6 +278,16 @@ static ssize_t aaip_encode_acl_text(char *acl_text,
char name[1024]; char name[1024];
double num; double num;
if(flag & 4) {
/* set SWITCH_MARK to indicate a default ACL */;
if(!(flag & 1)) {
if(count >= result_size)
return(-1);
result[count]= (Aaip_SWITCH_MARK << 4) | Aaip_EXEC;
}
count++;
}
for(rpt= acl_text; *rpt != 0; rpt= npt) { for(rpt= acl_text; *rpt != 0; rpt= npt) {
npt= strchr(rpt, '\n'); npt= strchr(rpt, '\n');
if(npt == 0) if(npt == 0)
@ -362,6 +372,8 @@ group_by_name:;
} else } else
continue; continue;
if(npt - cpt < 3)
continue;
perms= 0; perms= 0;
if(cpt[1] == 'r') if(cpt[1] == 'r')
perms|= Aaip_READ; perms|= Aaip_READ;
@ -370,13 +382,18 @@ group_by_name:;
if(cpt[3] == 'x') if(cpt[3] == 'x')
perms|= Aaip_EXEC; perms|= Aaip_EXEC;
if(!(flag & 1)) if(!(flag & 1)) {
if(count >= result_size)
return(-1);
result[count]= perms | ((!!qualifier) << 3) | (type << 4); result[count]= perms | ((!!qualifier) << 3) | (type << 4);
}
count++; count++;
if(qualifier) { if(qualifier) {
num_recs= (qualifier_len / 127) + !!(qualifier_len % 127); num_recs= (qualifier_len / 127) + !!(qualifier_len % 127);
if(!(flag & 1)) { if(!(flag & 1)) {
if(count + 1 > result_size)
return(-1);
for(i= 0; i < num_recs; i++) { for(i= 0; i < num_recs; i++) {
if(i < num_recs - 1) if(i < num_recs - 1)
result[count++]= 255; result[count++]= 255;
@ -385,6 +402,8 @@ group_by_name:;
if(result[count - 1] == 0) if(result[count - 1] == 0)
result[count - 1]= 127; result[count - 1]= 127;
} }
if(count + (result[count - 1] & 127) > result_size)
return(-1);
memcpy(result + count, name + i * 127, result[count - 1] & 127); memcpy(result + count, name + i * 127, result[count - 1] & 127);
count+= result[count - 1] & 127; count+= result[count - 1] & 127;
} }
@ -1134,5 +1153,189 @@ unsigned int aaip_get_pairs_skipped(struct aaip_state *aaip, int flag)
} }
/* >>> Decoder for ACLs */; /* ------ Decoder for ACLs ------ */
static int aaip_write_acl_line(char **result, size_t *result_size,
char *tag_type, char *qualifier,
char *permissions, int flag)
{
size_t needed, tag_len, perm_len, qualifier_len;
tag_len= strlen(tag_type);
qualifier_len= strlen(qualifier);
perm_len= strlen(permissions);
needed= tag_len + qualifier_len + perm_len + 3;
if((flag & 1)) {
(*result_size)+= needed;
return(1);
}
if(needed + 1 > *result_size) /* +1 : want to append a trailing 0 */
return(-1);
memcpy((*result), tag_type, tag_len);
(*result)[tag_len]= ':';
memcpy((*result) + tag_len + 1, qualifier, qualifier_len);
(*result)[tag_len + 1 + qualifier_len]= ':';
memcpy((*result) + tag_len + 1 + qualifier_len + 1, permissions, perm_len);
(*result)[tag_len + 1 + qualifier_len + 1 + perm_len]= '\n';
(*result)[tag_len + 1 + qualifier_len + 1 + perm_len + 1] = 0;
(*result)+= needed;
(*result_size)-= needed;
return(1);
}
static int aaip_read_qualifier(unsigned char *data, size_t num_data,
char *name, size_t name_size, size_t *name_fill,
int flag)
{
int is_done= 0, rec_len= 0;
unsigned char *rpt;
*name_fill= 0;
for(rpt= data; !is_done; rpt+= rec_len) {
rec_len= (*rpt) & 127;
is_done= !((*rpt) & 128);
if(*name_fill + rec_len >= name_size || rpt + 1 + rec_len - data > num_data)
return(-1);
memcpy(name + *name_fill, rpt + 1, rec_len);
rpt+= 1 + rec_len;
(*name_fill)+= rec_len;
name[*name_fill]= 0;
}
return(1);
}
/* Convert an AAIP ACL attribute value into the long text form of ACL.
@param data The raw data to decode
@param num_data Number of data bytes provided
@param consumed Returns the number of consumed data bytes
@param acl_text Will be filled with ACL long text form
@param acl_text_size Maximum number of bytes to be written to acl_text
@param acl_text_fill Will return the number of bytes in acl_text
@param flag Bitfield for control purposes
bit0= count only, do not really produce bytes:
acl_text will not be touched,
acl_text_size will be ignored,
*acl_text_fill will return the counted number
plus 1 for a trailing zero.
bit1= expected is a default ACL (see return value 2)
@return 1 success
2 success, begin of default/access ACL encountered,
submit data + *consumed for access/default ACL
-1 error with reading of qualifier
-2 error with writing of ACL text line
-3 version mismatch
-4 unknown tag type encountered
*/
int aaip_decode_acl(unsigned char *data, size_t num_data, size_t *consumed,
char *acl_text, size_t acl_text_size,
size_t *acl_text_fill, int flag)
{
unsigned char *rpt;
char perm_text[4], *wpt, name[1024];
int type, qualifier= 0, perm, ret, i, cnt;
size_t w_size, name_fill;
uid_t uid;
gid_t gid;
struct passwd *pwd;
struct group *grp;
cnt= flag & 1;
*consumed= 0;
wpt= acl_text;
w_size= acl_text_size;
*acl_text_fill= 0;
for(rpt= data; rpt - data < num_data; ) {
perm= *rpt;
strcpy(perm_text, "---");
if(perm & Aaip_READ)
perm_text[0]= 'r';
if(perm & Aaip_WRITE)
perm_text[1]= 'w';
if(perm & Aaip_EXEC)
perm_text[2]= 'x';
type= (*rpt) >> 4;
if(type == Aaip_FUTURE_VERSION) /* indicate to caller: version mismatch */
return(-3);
qualifier= !!((*rpt) & 8);
if(qualifier) {
ret= aaip_read_qualifier(rpt + 1, num_data - (rpt + 1 - data),
name, sizeof(name), &name_fill, 0);
if(ret <= 0)
return(-1);
}
/* Advance read pointer */
(*consumed)+= 1 + (qualifier ? name_fill + 1 : 0);
rpt+= 1 + (qualifier ? name_fill + 1 : 0);
ret= 1;
if(type == Aaip_TRANSLATE) {
/* rightfully ignored yet */;
continue;
} else if(type == Aaip_ACL_USER_OBJ) {
/* user::rwx */
ret= aaip_write_acl_line(&wpt, &w_size, "user", "", perm_text, cnt);
} else if(type == Aaip_ACL_USER) {
/* user:<username>:rwx */;
ret= aaip_write_acl_line(&wpt, &w_size, "user", name, perm_text, cnt);
} else if(type == Aaip_ACL_GROUP_OBJ) {
/* user::rwx */
ret= aaip_write_acl_line(&wpt, &w_size, "group", "", perm_text, cnt);
} else if(type == Aaip_ACL_GROUP) {
/* group:<groupname>:rwx */;
ret= aaip_write_acl_line(&wpt, &w_size, "group", name, perm_text, cnt);
} else if(type == Aaip_ACL_MASK) {
/* mask::rwx */
ret= aaip_write_acl_line(&wpt, &w_size, "mask", "", perm_text, cnt);
} else if(type == Aaip_ACL_OTHER) {
/* other::rwx */
ret= aaip_write_acl_line(&wpt, &w_size, "other", "", perm_text, cnt);
} else if(type == Aaip_SWITCH_MARK) {
/* Indicate to caller: end of desired ACL type access/default */
if((!(perm & Aaip_EXEC)) ^ (!!(flag & 2)))
return(2);
} else if(type == Aaip_ACL_USER_N) {
/* determine username from uid */
uid= 0;
for(i= 0; i < name_fill; i++)
uid= (uid << 8) | ((unsigned char *) name)[i];
pwd= getpwuid(uid);
if(pwd == NULL)
sprintf(name, "%.f", (double) uid);
else if(strlen(pwd->pw_name) >= sizeof(name))
sprintf(name, "%.f", (double) uid);
else
strcpy(name, pwd->pw_name);
/* user:<username>:rwx */;
ret= aaip_write_acl_line(&wpt, &w_size, "user", name, perm_text, cnt);
} else if(type == Aaip_ACL_GROUP_N) {
/* determine username from gid */;
gid= 0;
for(i= 0; i < name_fill; i++)
gid= (gid << 8) | ((unsigned char *) name)[i];
grp= getgrgid(gid);
if(grp == NULL)
sprintf(name, "%.f", (double) gid);
else if(strlen(grp->gr_name) >= sizeof(name))
sprintf(name, "%.f", (double) gid);
else
strcpy(name, grp->gr_name);
/* user:<username>:rwx */;
ret= aaip_write_acl_line(&wpt, &w_size, "group", name, perm_text, cnt);
} else {
/* indicate to caller: unknown type */
return(-4);
}
if(ret <= 0)
return(-2);
}
if(flag & 1)
*acl_text_fill= w_size + 1;
return(1);
}

View File

@ -37,7 +37,7 @@ unsigned int aaip_encode(char aa_name[2],
size_t *result_len, unsigned char **result, int flag); size_t *result_len, unsigned char **result, int flag);
/* Convert an ACL text as of acl_to_text(3) into the value of an Arbitrary /* Convert an ACL from long text form into the value of an Arbitrary
Attribute. According to AAIP 0.2 this value is to be stored together with Attribute. According to AAIP 0.2 this value is to be stored together with
an empty name. an empty name.
@param acl_text The ACL in long text form @param acl_text The ACL in long text form
@ -199,5 +199,32 @@ int aaip_decode_pair(struct aaip_state *aaip,
*/ */
unsigned int aaip_get_pairs_skipped(struct aaip_state *aaip, int flag); unsigned int aaip_get_pairs_skipped(struct aaip_state *aaip, int flag);
/* Convert an AAIP 0.2 ACL attribute value into the long text form of ACL.
@param data The raw data to decode
@param num_data Number of data bytes provided
@param consumed Returns the number of consumed data bytes
@param acl_text Will be filled with ACL long text form
@param acl_text_size Maximum number of bytes to be written to acl_text
@param acl_text_fill Will return the number of bytes in acl_text
@param flag Bitfield for control purposes
bit0= count only, do not really produce bytes:
acl_text will not be touched,
acl_text_size will be ignored,
*acl_text_fill will return the counted number
bit1= expected is a default ACL (see return value 2)
@return 1 success
2 success, begin of default/access ACL encountered,
submit data + *consumed for access/default ACL
-1 error with reading of qualifier
-2 error with writing of ACL text line
-3 version mismatch
-4 unknown tag type encountered
*/
int aaip_decode_acl(unsigned char *data, size_t num_data, size_t *consumed,
char *acl_text, size_t acl_text_size,
size_t *acl_text_fill, int flag);
#endif /* ! Aaip_h_is_includeD */ #endif /* ! Aaip_h_is_includeD */

View File

@ -57,7 +57,63 @@ static int print_result(unsigned char *result, size_t result_len, int flag)
} }
static int test_acl(char *path, int flag) static int decode_acl(unsigned char *result, size_t result_len,
char *out_path, int flag)
{
int ret;
size_t consumed, text_fill;
char *text= NULL;
acl_t out_acl= NULL;
FILE *fp;
ret= aaip_decode_acl(result, result_len, &consumed, NULL, 0, &text_fill, 1);
if(ret <= 0) {
fprintf(stderr, "aaip_decode_acl(,1) failed: ret= %d\n", ret);
ret= 0; goto ex;
}
text= calloc(text_fill, 1);
ret= aaip_decode_acl(result, result_len, &consumed, text, text_fill,
&text_fill, 0);
if(ret <= 0) {
fprintf(stderr, "aaip_decode_acl(,0) failed: ret= %d\n", ret);
ret= 0; goto ex;
}
printf("--- ret= %d , text=\n%s--- end of text\n\n", ret, text);
if(out_path == NULL)
{ret= 1; goto ex;}
out_acl= acl_from_text(text);
if(out_acl == NULL) {
fprintf(stderr, "acl_from_text failed: %d %s\n",
errno, errno != 0 ? strerror(errno) : "");
ret= 0; goto ex;
}
fp= fopen(out_path, "a");
if(fp == NULL) {
fprintf(stderr, "fopen(\"%s\") failed: %d %s\n",
out_path, errno, errno != 0 ? strerror(errno) : "");
ret= 0; goto ex;
}
fclose(fp);
ret= acl_set_file(out_path, ACL_TYPE_ACCESS, out_acl);
if(ret == -1) {
fprintf(stderr, "acl_set_file(\"%s\") failed: %d %s\n",
out_path, errno, errno != 0 ? strerror(errno) : "");
ret= 0; goto ex;
}
ret= 1;
ex:
if(out_acl != NULL)
acl_free(out_acl);
if(text != NULL)
free(text);
return(ret);
}
static int test_acl(char *in_path, char *out_path, int flag)
{ {
int ret; int ret;
acl_t acl= NULL; acl_t acl= NULL;
@ -65,7 +121,7 @@ static int test_acl(char *path, int flag)
unsigned char *result= NULL; unsigned char *result= NULL;
size_t result_len; size_t result_len;
acl= acl_get_file(path, ACL_TYPE_ACCESS); acl= acl_get_file(in_path, ACL_TYPE_ACCESS);
if(acl == NULL) { if(acl == NULL) {
fprintf(stderr, "acl_get_file failed: %d %s\n", fprintf(stderr, "acl_get_file failed: %d %s\n",
errno, errno != 0 ? strerror(errno) : ""); errno, errno != 0 ? strerror(errno) : "");
@ -78,23 +134,28 @@ static int test_acl(char *path, int flag)
ret= 0; goto ex; ret= 0; goto ex;
} }
printf("--- ACL:\n%s--- end of ACL\n\n", acl_text); printf("--- ACL:\n%s--- end of ACL\n\n", acl_text);
ret= aaip_encode_acl(acl_text, &result_len, &result, 0); ret= aaip_encode_acl(acl_text, &result_len, &result, 0);
if(ret <= 0) { if(ret <= 0) {
fprintf(stderr, "aaip_encode_acl(text) failed: ret= %d\n", ret); fprintf(stderr, "aaip_encode_acl(text) failed: ret= %d\n", ret);
ret= 0; goto ex; ret= 0; goto ex;
} }
print_result(result, result_len, 0); print_result(result, result_len, 0);
ret= decode_acl(result, result_len, out_path, 0);
if(ret <= 0)
goto ex;
free(result); result= NULL; free(result); result= NULL;
ret= aaip_encode_acl(acl_text, &result_len, &result, 2); ret= aaip_encode_acl(acl_text, &result_len, &result, 2);
if(ret <= 0) { if(ret <= 0) {
fprintf(stderr, "aaip_encode_acl(num) failed: ret= %d\n", ret); fprintf(stderr, "aaip_encode_acl(num) failed: ret= %d\n", ret);
ret= 0; goto ex; ret= 0; goto ex;
} }
print_result(result, result_len, 0); print_result(result, result_len, 0);
ret= decode_acl(result, result_len, out_path, 0);
if(ret <= 0)
goto ex;
/* >>> */;
ret= 1; ret= 1;
ex:; ex:;
if(acl_text != NULL) if(acl_text != NULL)
@ -126,7 +187,7 @@ int main(int argc, char **argv)
unsigned int skipped, was_skipped= 0; unsigned int skipped, was_skipped= 0;
test_acl("/u/test/acl", 0); test_acl("/u/test/acl", "/u/test/out_acl", 0);
if(argc < 3 || (argc % 2) == 0) { if(argc < 3 || (argc % 2) == 0) {