From 37f4eaa9bbd87f8d1ec3fb459aa76d9ad6afd262 Mon Sep 17 00:00:00 2001 From: Thomas Schmitt Date: Thu, 25 Dec 2008 14:01:36 +0000 Subject: [PATCH] Encoder for ACL long text form --- test/aaip_0_2.c | 222 ++++++++++++++++++++++++++++++++++++++++++- test/aaip_0_2.h | 17 +++- test/aaip_0_2_test.c | 101 ++++++++++++++++---- 3 files changed, 320 insertions(+), 20 deletions(-) diff --git a/test/aaip_0_2.c b/test/aaip_0_2.c index 7b66a9d3..64c02592 100644 --- a/test/aaip_0_2.c +++ b/test/aaip_0_2.c @@ -17,12 +17,29 @@ #include #include #include +#include +#include /* <<< */ #define Aaip_encode_debuG 1 #include "aaip_0_2.h" +#define Aaip_EXEC 1 +#define Aaip_WRITE 2 +#define Aaip_READ 4 + +#define Aaip_TRANSLATE 0 +#define Aaip_ACL_USER_OBJ 1 +#define Aaip_ACL_USER 2 +#define Aaip_ACL_GROUP_OBJ 3 +#define Aaip_ACL_GROUP 4 +#define Aaip_ACL_MASK 5 +#define Aaip_ACL_OTHER 6 +#define Aaip_SWITCH_MARK 8 +#define Aaip_ACL_USER_N 10 +#define Aaip_ACL_GROUP_N 12 +#define Aaip_FUTURE_VERSION 15 /* --------------------------------- Encoder ---------------------------- */ @@ -174,7 +191,210 @@ static int aaip_encode_pair(char *name, size_t attr_length, char *attr, } -/* >>> Encoder for ACLs */; +/* ----------- Encoder for ACLs ----------- */ + +static ssize_t aaip_encode_acl_text(char *acl_text, + size_t result_size, unsigned char *result, int flag); + + +/* Convert an ACL text as of acl_to_text(3) 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 + @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_acl(char *acl_text, + 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 & 2)); + if(bytes < 0) + return(0); + if(flag & 1) { + *result_len= bytes; + return(1); + } + *result= calloc(bytes + 1, 1); + if(*result == NULL) + return(-1); + (*result)[bytes]= 0; + *result_len= bytes; + bytes= aaip_encode_acl_text(acl_text, *result_len, *result, (flag & 2)); + if(bytes != *result_len) { + *result_len= 0; + return(0); + } + return(1); +} + + +static double aaip_numeric_id(char *name, int flag) +{ + double num; + char *cpt; + + for(cpt= name; *cpt != 0; cpt++) + if(*cpt < '0' || *cpt >'9') + break; + if(*cpt != 0) + return(-1); + sscanf(name, "%lf", &num); + return(num); +} + + +/* + @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, do not really produce bytes + bit1= use numeric qualifiers + @return >=0 number of bytes produced resp. counted + <0 means error +*/ +static ssize_t aaip_encode_acl_text(char *acl_text, + size_t result_size, unsigned char *result, int flag) +{ + char *rpt, *npt, *cpt; + int qualifier= 0, perms, type, i, qualifier_len, num_recs; + uid_t uid, huid; + gid_t gid, hgid; + ssize_t count= 0; + struct passwd *pwd; + struct group *grp; + char name[1024]; + double num; + + for(rpt= acl_text; *rpt != 0; rpt= npt) { + npt= strchr(rpt, '\n'); + if(npt == 0) + npt= rpt + strlen(rpt); + else + npt++; + if(*rpt == '#') + continue; + cpt= strchr(rpt, ':'); + if(cpt == NULL) + continue; + cpt= strchr(cpt + 1, ':'); + if(cpt == NULL) + continue; + qualifier= 0; + if(strncmp(rpt, "user:", 5) == 0) { + if(cpt - rpt == 5) + type= Aaip_ACL_USER_OBJ; + else { + if(cpt - (rpt + 5) >= sizeof(name)) + continue; + strncpy(name, rpt + 5, cpt - (rpt + 5)); + name[cpt - (rpt + 5)]= 0; + if(flag & 2) { + type= Aaip_ACL_USER_N; + pwd= getpwnam(name); + if(pwd == NULL) { + num= aaip_numeric_id(name, 0); + if(num <= 0) + goto user_by_name; + uid= huid= num; + } else + uid= huid= pwd->pw_uid; + /* Convert uid into Qualifier Record */ + for(i= 0; huid != 0; i++) + huid= huid >> 8; + qualifier_len= i; + for(i= 0; i < qualifier_len ; i++) + name[i]= uid >> (8 * (qualifier_len - i - 1)); + } else { +user_by_name:; + type= Aaip_ACL_USER; + qualifier_len= strlen(name); + } + qualifier= 1; + } + } else if(strncmp(rpt, "group:", 6) == 0) { + if(cpt - rpt == 6) + type= Aaip_ACL_GROUP_OBJ; + else { + if(cpt - (rpt + 6) >= sizeof(name)) + continue; + strncpy(name, rpt + 6, cpt - (rpt + 6)); + if(flag & 2) { + type= Aaip_ACL_GROUP_N; + grp= getgrnam(name); + if(grp == NULL) { + num= aaip_numeric_id(name, 0); + if(num <= 0) + goto group_by_name; + gid= hgid= num; + } else + gid= hgid= grp->gr_gid; + /* Convert gid into Qualifier Record */ + for(i= 0; hgid != 0; i++) + hgid= hgid >> 8; + qualifier_len= i; + for(i= 0; i < qualifier_len ; i++) + name[i]= gid >> (8 * (qualifier_len - i - 1)); + + } else { +group_by_name:; + type= Aaip_ACL_GROUP; + qualifier_len= strlen(name); + } + qualifier= 1; + } + } else if(strncmp(rpt, "other:", 6) == 0) { + type= Aaip_ACL_OTHER; + } else if(strncmp(rpt, "mask:", 5) == 0) { + type= Aaip_ACL_MASK; + } else + continue; + + perms= 0; + if(cpt[1] == 'r') + perms|= Aaip_READ; + if(cpt[2] == 'w') + perms|= Aaip_WRITE; + if(cpt[3] == 'x') + perms|= Aaip_EXEC; + + if(!(flag & 1)) + result[count]= perms | ((!!qualifier) << 3) | (type << 4); + count++; + + if(qualifier) { + num_recs= (qualifier_len / 127) + !!(qualifier_len % 127); + if(!(flag & 1)) { + for(i= 0; i < num_recs; i++) { + if(i < num_recs - 1) + result[count++]= 255; + else { + result[count++]= (qualifier_len % 127); + if(result[count - 1] == 0) + result[count - 1]= 127; + } + memcpy(result + count, name + i * 127, result[count - 1] & 127); + count+= result[count - 1] & 127; + } + } else + count+= qualifier_len + num_recs; + } + } + + return(count); +} /* --------------------------------- Decoder ---------------------------- */ diff --git a/test/aaip_0_2.h b/test/aaip_0_2.h index 5eee54a5..d89d18be 100644 --- a/test/aaip_0_2.h +++ b/test/aaip_0_2.h @@ -37,7 +37,22 @@ unsigned int aaip_encode(char aa_name[2], size_t *result_len, unsigned char **result, int flag); -/* >>> Encoder for ACLs */; +/* Convert an ACL text as of acl_to_text(3) 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 + @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_acl(char *acl_text, + size_t *result_len, unsigned char **result, int flag); /* --------------------------------- Decoder ---------------------------- */ diff --git a/test/aaip_0_2_test.c b/test/aaip_0_2_test.c index b89e08d4..94284b3a 100644 --- a/test/aaip_0_2_test.c +++ b/test/aaip_0_2_test.c @@ -8,7 +8,7 @@ test/aaip_0_2_test.c - Main program for test binary - Compile: cc -g -Wall -o test/aaip test/aaip_0_2.c test/aaip_0_2_test.c + Compile: cc -g -Wall -o test/aaip test/aaip_0_2.c test/aaip_0_2_test.c -lacl Usage: ./aaip name value Long parameters ./aaip -name"x100" -value"x100" @@ -23,12 +23,89 @@ #include #include #include +#include + +#include #include "aaip_0_2.h" #define Aaip_test_name_sizE 1024 #define Aaip_test_value_sizE 1024 + +static int print_result(unsigned char *result, size_t result_len, int flag) +{ + int i; + + printf( + " - - - - - - 0 - - 1 - - 2 - - 3 - - 4 - - 5 - - 6 - - 7 - - 8 - - 9\n"); + printf("\n"); + printf("%4u : ", 0); + for(i= 0; i < result_len; i++) { + if(result[i] >= 32 && result[i] <= 126) + printf("'%c' ", result[i]); + else + printf("%3u ", (unsigned int) ((unsigned char *) result)[i]); + if((i % 10) == 9) + printf("\n%4u : ", (unsigned int) (i + 1)); + } + printf("\n\n"); + printf( + " - - - - - - 0 - - 1 - - 2 - - 3 - - 4 - - 5 - - 6 - - 7 - - 8 - - 9\n"); + printf("\n"); + return(1); +} + + +static int test_acl(char *path, int flag) +{ + int ret; + acl_t acl= NULL; + char *acl_text= NULL; + unsigned char *result= NULL; + size_t result_len; + + acl= acl_get_file(path, ACL_TYPE_ACCESS); + if(acl == NULL) { + fprintf(stderr, "acl_get_file failed: %d %s\n", + errno, errno != 0 ? strerror(errno) : ""); + ret= 0; goto ex; + } + acl_text= acl_to_text(acl, NULL); + if(acl_text == NULL) { + fprintf(stderr, "acl_to_text failed: %d %s\n", + errno, errno != 0 ? strerror(errno) : ""); + 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); + 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= 1; +ex:; + if(acl_text != NULL) + acl_free(acl_text); + if(acl != NULL) + acl_free(acl); + if(result != NULL) + free(result); + return(ret); +} + int main(int argc, char **argv) { int ret, l, mult= 0, k; @@ -48,6 +125,10 @@ int main(int argc, char **argv) unsigned char *rpt; unsigned int skipped, was_skipped= 0; + + test_acl("/u/test/acl", 0); + + if(argc < 3 || (argc % 2) == 0) { fprintf(stderr, "usage: %s [-]name[xNNN] [-]value[xNNN] ...\n", argv[0]); exit(1); @@ -91,23 +172,7 @@ int main(int argc, char **argv) fprintf(stderr, "%s : aaip_encode failed with ret= %d\n", argv[0], ret); exit(2); } - printf( - " - - - - - - 0 - - 1 - - 2 - - 3 - - 4 - - 5 - - 6 - - 7 - - 8 - - 9\n"); - printf("\n"); - printf("%4u : ", 0); - for(i= 0; i < result_len; i++) { - if(result[i] >= 32 && result[i] <= 126) - printf("'%c' ", result[i]); - else - printf("%3u ", (unsigned int) ((unsigned char *) result)[i]); - if((i % 10) == 9) - printf("\n%4u : ", (unsigned int) (i + 1)); - } - printf("\n\n"); - printf( - " - - - - - - 0 - - 1 - - 2 - - 3 - - 4 - - 5 - - 6 - - 7 - - 8 - - 9\n"); - printf("\n"); - + print_result(result, result_len, 0); aaip_init(aaip, "AA", 0); rpt= result;