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
bit0= count only
bit1= use numeric qualifiers rather than names
bit2= this is a default ACL, prepend SWITCH_MARK
@return >0 means ok
0 means error
*/
@ -218,7 +219,7 @@ int aaip_encode_acl(char *acl_text,
*result= NULL;
*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)
return(0);
if(flag & 1) {
@ -230,7 +231,7 @@ 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 & 2));
bytes= aaip_encode_acl_text(acl_text, *result_len, *result, (flag & 6));
if(bytes != *result_len) {
*result_len= 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 *result will point to the start of the result string.
This is malloc() memory which needs to be freed when
no longer needed
@param result_size Number of bytes to store result
@param result Pointer to the start of the result string.
@param flag Bitfield for control purposes
bit0= count only, do not really produce bytes
bit1= use numeric qualifiers
bit2= this is a default ACL, prepend SWITCH_MARK 1
@return >=0 number of bytes produced resp. counted
<0 means error
*/
@ -278,6 +278,16 @@ static ssize_t aaip_encode_acl_text(char *acl_text,
char name[1024];
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) {
npt= strchr(rpt, '\n');
if(npt == 0)
@ -362,6 +372,8 @@ group_by_name:;
} else
continue;
if(npt - cpt < 3)
continue;
perms= 0;
if(cpt[1] == 'r')
perms|= Aaip_READ;
@ -370,13 +382,18 @@ group_by_name:;
if(cpt[3] == 'x')
perms|= Aaip_EXEC;
if(!(flag & 1))
if(!(flag & 1)) {
if(count >= result_size)
return(-1);
result[count]= perms | ((!!qualifier) << 3) | (type << 4);
}
count++;
if(qualifier) {
num_recs= (qualifier_len / 127) + !!(qualifier_len % 127);
if(!(flag & 1)) {
if(count + 1 > result_size)
return(-1);
for(i= 0; i < num_recs; i++) {
if(i < num_recs - 1)
result[count++]= 255;
@ -385,6 +402,8 @@ group_by_name:;
if(result[count - 1] == 0)
result[count - 1]= 127;
}
if(count + (result[count - 1] & 127) > result_size)
return(-1);
memcpy(result + count, name + i * 127, 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);
/* 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
an empty name.
@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);
/* 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 */

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;
acl_t acl= NULL;
@ -65,7 +121,7 @@ static int test_acl(char *path, int flag)
unsigned char *result= NULL;
size_t result_len;
acl= acl_get_file(path, ACL_TYPE_ACCESS);
acl= acl_get_file(in_path, ACL_TYPE_ACCESS);
if(acl == NULL) {
fprintf(stderr, "acl_get_file failed: %d %s\n",
errno, errno != 0 ? strerror(errno) : "");
@ -78,22 +134,27 @@ static int test_acl(char *path, int flag)
ret= 0; goto ex;
}
printf("--- ACL:\n%s--- end of ACL\n\n", acl_text);
ret= aaip_encode_acl(acl_text, &result_len, &result, 0);
if(ret <= 0) {
fprintf(stderr, "aaip_encode_acl(text) failed: ret= %d\n", ret);
ret= 0; goto ex;
}
print_result(result, result_len, 0);
ret= decode_acl(result, result_len, out_path, 0);
if(ret <= 0)
goto ex;
free(result); result= NULL;
ret= aaip_encode_acl(acl_text, &result_len, &result, 2);
if(ret <= 0) {
fprintf(stderr, "aaip_encode_acl(num) failed: ret= %d\n", ret);
ret= 0; goto ex;
}
print_result(result, result_len, 0);
/* >>> */;
ret= decode_acl(result, result_len, out_path, 0);
if(ret <= 0)
goto ex;
ret= 1;
ex:;
@ -126,7 +187,7 @@ int main(int argc, char **argv)
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) {