Decoder for ACL to long text form
This commit is contained in:
parent
aa16a66e33
commit
8f3f36891a
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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 */
|
||||
|
||||
|
@ -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) {
|
||||
|
Loading…
Reference in New Issue
Block a user