diff --git a/test/aaip.c b/test/aaip.c deleted file mode 100644 index e90819ad..00000000 --- a/test/aaip.c +++ /dev/null @@ -1,537 +0,0 @@ - -/* - - Arbitrary Attribute Interchange Protocol , AAIP - Demonstration program for encoding and decoding types PAIR and ACL1. - - See http://libburnia-project.org/wiki/AAIP - - Compile: cc -g -Wall -o test/aaip test/aaip.c - - Usage: ./aaip name value - Long parameters ./aaip -name"x100" -value"x100" - -*/ - -#include -#include -#include -#include -#include -#include - -/* <<< */ -#define Aaip_encode_debuG 1 - - -/* --------------------------------- Encoder ---------------------------- */ - -static unsigned int aaip_encode_parameter(char aa_name[2], - char *field_start, unsigned int field_fill, - unsigned int num_payload, char *payload, - int flag); - - -/* Convert the given type and parameters into a series of AAIP fields. - - @param aa_name The 2 byte SUSP Signature Word of the fields - (recommended is "AA") - @param type The 4 byte Attribute Type ("ATTR" or "ACL1" for now) - @param num_params Number of attribute parameters (>= 0) - @param param_lengths Array of byte lengths for each parameter - @param params Array of pointers to the parameter bytes - @param result_len Number of bytes in the resulting SUSP field string - @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 Unused yet. Submit 0 - @return >0 is the number of SUSP fields generated, - <= 0 means error -*/ -int aaip_encode(char aa_name[2], char type[4], unsigned int num_params, - unsigned int *param_lengths, char **params, - size_t *result_len, char **result, int flag) -{ - size_t mem_size= 0; - char *wpt, *field_start; - unsigned char *upt; - int ret; - unsigned int fl= 0, follow_fields, i, payload= 0; - unsigned int number_of_fields; - - *result_len= 0; - *result= NULL; - - /* Predict memory needs and number of SUSP fields */ - mem_size= 16; /* First field up to NUM_FIELDS */ - number_of_fields= 1; - for(i= 0; i < num_params; i++) { - if(i == 0) { - if(i > 239) - fl= param_lengths[i] - 239; /* what exceeds the first field */ - else - fl= 0; - } else - fl= param_lengths[i]; - follow_fields= (fl / 251) + ((fl % 251) > 0); - number_of_fields+= follow_fields; - mem_size+= param_lengths[i] + (follow_fields ) * 5; - } - -#ifdef Aaip_encode_debuG - *result= calloc(1, mem_size + 10240); /* generous honeypot for overflows */ -#else - *result= calloc(1, mem_size); -#endif - - if(*result == NULL) - return(-1); - wpt= *result; - - /* ----- First SUSP field ----- */ - - field_start= wpt; - *(wpt++)= aa_name[0]; - *(wpt++)= aa_name[1]; - /* number of bytes in first field */ - if(num_params > 0) { - if(param_lengths[0] > 239) - payload= 239; - else - payload= param_lengths[0]; - *((unsigned *) (wpt++))= payload + 16; - } else - *(wpt++)= 16; - *(wpt++)= 1; - - /* Attribute type */ - memcpy(wpt, type, 4); - wpt+= 4; - - /* Number of fields LSB and MSB */ - upt= (unsigned char *) wpt; - for(i= 0; i < 4; i++) - upt[7 - i]= upt[i]= (number_of_fields >> (8 * i)) & 0xff; - wpt+= 8; - - /* ----- Parameters ----- */ - /* Eventual first parameter */ - if(num_params > 0) { - ret= aaip_encode_parameter(aa_name, field_start, - (unsigned int) (wpt - field_start), - param_lengths[0], params[0], 0); - wpt+= ret; - } - /* Further parameters */ - for(i= 1; i < num_params; i++) { - ret= aaip_encode_parameter(aa_name, wpt, 0, param_lengths[i], params[i], 0); - wpt+= ret; - } - *result_len= wpt - *result; - -#ifdef Aaip_encode_debuG - if(*result_len != mem_size) { - fprintf(stderr, "aaip_encode(): MEMORY MISMATCH BY %d BYTES\n", - (int) (mem_size - *result_len)); - } - ret= 0; - for(i= 0; i < *result_len; i+= ((unsigned char *) (*result))[i + 2]) - ret++; - if(ret != number_of_fields) { - fprintf(stderr, "aaip_encode(): WRONG NUMBER OF FIELDS %d <> %d\n", - number_of_fields, ret); - } -#endif /* Aaip_encode_debuG */ - - return(number_of_fields); -} - - -/* >>> Encoder for ACL */ - - -/* Helper function: - Write the parameter into an eventually partially written field and into - eventually necessary further fields. - - @param aa_name The 2 byte SUSP Signature Word of the fields - @param field_start Points to the start of the current field - @param field_fill Number of bytes already written in field (0 or >5) - @param num_payload Number of parameter bytes - @param payload Points to parameter bytes - @param flag bit0= do not write further fields - bit1= with new field set FOLLOW bit 1 - @return Number of bytes written (payload and overhead) - -*/ -static unsigned int aaip_encode_parameter(char aa_name[2], - char *field_start, unsigned int field_fill, - unsigned int num_payload, char *payload, - int flag) -{ - int ret; - unsigned int num_head= 0, num_pay= 0; - char *wpt, *rpt; - - if(field_fill < 5) { - field_start[0]= aa_name[0]; - field_start[1]= aa_name[1]; - field_start[2]= 5; - field_start[3]= 1; - field_start[4]= !!(flag & 2); - num_head= field_fill= 5; - } - if(num_payload <= 0) - return(num_head); - if(num_payload + field_fill > 255) - num_pay= 255 - field_fill; - else - num_pay= num_payload; - memcpy(field_start + field_fill, payload, num_pay); - - /* Update field length */ - ((unsigned char *) field_start)[2]= field_fill + num_pay; - - if(!(flag & 1)) { - /* Write further fields */ - wpt= field_start + field_fill + num_pay; - rpt= payload + num_pay; - while(num_pay < num_payload) { - ret= aaip_encode_parameter(aa_name, wpt, 0, num_payload - num_pay, rpt, - 3); - wpt+= ret; - num_head+= 5; - rpt+= ret - 5; - num_pay+= ret - 5; - } - } - return(num_head + num_pay); -} - - -/* --------------------------------- Decoder ---------------------------- */ - - -/* A size limit for single parameters in order to prevent resource ehaustion. -*/ -#define Aaip_param_memory_limiT 1024*1024 - -static int aaip_decode_parameter(char *start_field, unsigned int num_fields, - char **new_pos, unsigned int *field_idx, - size_t *result_len, char **result, int flag); - - -/* Checks whether an encoded attribute is complete yet, or how many more fields - need to be added, or whether the encoded bytes represent no valid attribute. - This function assumes to get fed with complete SUSP fields, though. - It also computes a pointer to the first byte after the fields of the - attribute if it is valid at all. - - @param aa_name The 2 byte SUSP Signature Word of the fields as of - the ER field with signature "AAIP_2008A" - @param attr_start Points to the first first field of the attribute. - @param up_to Maximum number of bytes to be checked - @param num_params Will tell number of parameters of the attribute - @param num_fields Will tell number of fields of the attribute. See return. - @param new_pos Will point to the desired byte position if return is 1 - @param flag Unused yet. Submit 0 - @return 1 ok, *new_pos and *num_fields are valid - 0 not ok, *num_fields tells number of missing fields - -1 not ok, not an attribute start -*/ -int aaip_decode_check(char aa_name[2], char *attr_start, size_t up_to, - unsigned int *num_params, unsigned int *num_fields, - char **new_pos, int flag) -{ - unsigned int i, number_of_fields; - char *rpt; - unsigned char *upt; - - /* check signature */ - if(up_to < 16) - return(-1); - rpt= attr_start; - upt= (unsigned char *) rpt; - if(rpt[0] != aa_name[0] || rpt[1] != aa_name[1] || upt[4] < 0x20) - return(-1); - - number_of_fields= upt[8] | (upt[9] << 8) | (upt[10] << 16) | (upt[11] << 24); - *num_params= 1; - for(i= 0; i < number_of_fields; i++) { - if(i > 0) { - if(rpt[0] != aa_name[0] || rpt[1] != aa_name[1] || upt[4] >= 0x20) - return(-1); - if(!(upt[4] & 1)) - (*num_params)++; - } - rpt+= upt[2]; - upt= (unsigned char *) rpt; - if(rpt - attr_start >= up_to && i < number_of_fields - 1) { - *num_fields= number_of_fields - 1 - i; - return(0); - } - } - *new_pos= rpt; - *num_fields= number_of_fields; - return(1); -} - - -/* Check whether the given fields are an attribute of type PAIR and eventually - retrieve its name and value. *value and *name will be allocated memory which - has to be freed when no longer needed. Both will have a trailing 0 byte - which is not counted in their len values. - - @param aa_name The 2 byte SUSP Signature Word of the fields as of - the ER field with signature "AAIP_2008A" - @param attr_start Points to the first first field of the attribute. - @param up_to Maximum number of bytes to be checked - @param new_pos Will point to the desired byte position if return is 1 - @param name_len Will point to the number of bytes in *name - @param name Will point to the bytes of the pair name - @param value_len Will point to the number of bytes in *value - @param value Will point to the bytes of the pair value - @param flag Unused yet. Submit 0 - - @return 1 ok, result is valid - 0 not ok, not a PAIR type attribute or not complete - -1 not ok, other error -*/ -int aaip_decode_pair(char aa_name[2], char *attr_start, size_t up_to, - char **new_pos, - size_t *name_len, char **name, - size_t *value_len, char **value, int flag) -{ - unsigned int num_fields, num_params, field_idx= 0; - int ret; - char *peek_pos; - - *name_len= *value_len= 0; - *name= *value= NULL; - if(up_to < 9) - return(0); - if(strncmp(attr_start + 4, "PAIR", 4) != 0) - return(0); - ret= aaip_decode_check(aa_name, attr_start, up_to, &num_params, &num_fields, - &peek_pos, 0); - if(ret <= 0) - return(ret); - if(num_params != 2) - return(0); - ret= aaip_decode_parameter(attr_start, num_fields, &attr_start, &field_idx, - name_len, name, 0); - if(ret <= 0) - return(-1); - ret= aaip_decode_parameter(attr_start, num_fields, &attr_start, &field_idx, - value_len, value, 0); - if(ret <= 0) - return(-1); - *new_pos= peek_pos; - return(1); -} - - -/* Check whether the given fields are an attribute of type ACL1 and eventually - retrieve its long text form ready for acl_from_text(3). This text is - terminated by a 0 byte. - *text will be allocated memory which has to be freed when no longer needed. - - @param aa_name The 2 byte SUSP Signature Word of the fields as of - the ER field with signature "AAIP_2008A" - @param attr_start Points to the first first field of the attribute. - @param up_to Maximum number of bytes to be checked - @param new_pos Will point to the desired byte position if return is 1 - @param text Will point to the bytes of the ACL text form - @param flag Unused yet. Submit 0 - - @return 1 ok, result is valid - 0 not ok, not a ACL1 type attribute or not complete - -1 not ok, other error -*/ -int aaip_decode_acl1(char aa_name[2], char *attr_start, size_t up_to, - char **new_pos, char **text, int flag) -{ - unsigned int num_fields, num_params, field_idx= 0; - int ret; - size_t data_len; - char *peek_pos, *data= NULL; - - *text= NULL; - if(up_to < 9) - return(0); - if(strncmp(attr_start + 4, "ACL1", 4) != 0) - return(0); - ret= aaip_decode_check(aa_name, attr_start, up_to, &num_params, &num_fields, - &peek_pos, 0); - if(ret <= 0) - return(ret); - if(num_params != 1) - return(0); - ret= aaip_decode_parameter(attr_start, num_fields, &attr_start, &field_idx, - &data_len, &data, 0); - if(ret <= 0) - return(-1); - - /* >>> convert parameter into long text form of ACL . see man 5 acl */; - - *new_pos= peek_pos; - if(data != NULL) - free(data); - return(1); -} - - -/* Helper function: - Read a parameter from one or more fields and return the number of consumed - bytes. It is assumed that the completeness of the attribute has been - checked already. - - @param start_field Points to the field where the parameter starts - @param num_fields Total number of fields in the attribute - @param new_pos Will point to the byte position after the parameter - @param field_idx Number of fields read so far. This will be updated - by this call. - @param result_len Will point to the number of bytes in result - @param result Will point to bytes of the parameter. A terminating 0 - is added for convenience but not counted in result_len - @param flag Unused yet. Submit 0. - @return >0 Number of bytes consumed (payload and overhead) - This is eventually the start of the next field - after the parameter. - <=0 error -*/ -static int aaip_decode_parameter(char *start_field, unsigned int num_fields, - char **new_pos, unsigned int *field_idx, - size_t *result_len, char **result, int flag) -{ - int overhead, pass; - unsigned int fi; - char *rpt, *wpt; - unsigned char *upt; - size_t mem_size= 0; - - *result_len= 0; - *result= NULL; - fi= *field_idx; - - for(pass= 0; pass < 2; pass++) { - rpt= start_field; - upt= (unsigned char *) rpt; - for(fi= *field_idx; fi < num_fields; fi++) { - if(upt[4] >= 0x20) - overhead= 16; - else - overhead= 5; - if(pass == 0) { - mem_size+= upt[2] - overhead; - } else { - memcpy(wpt, rpt + overhead, upt[2] - overhead); - wpt+= upt[2] - overhead; - } - rpt+= upt[2]; - upt= (unsigned char *) rpt; - if(fi < num_fields - 1) - if(upt[4] < 0x20 && !(upt[4] & 1)) - break; /* start of next parameter found */ - } - if(pass == 0) { - if(mem_size >= Aaip_param_memory_limiT) - return(-1); - (*result)= calloc(1, mem_size + 1); - if(*result == NULL) - return(-1); - *result_len= mem_size; - wpt= *result; - wpt[mem_size]= 0; /* a trailing zero cannot harm */ - } - } - *field_idx= fi; - *new_pos= rpt; - return(1); -} - - -/* ------------------------- Test ------------------------ */ - - -int main(int argc, char **argv) -{ - int ret, l, mult= 0, k; - size_t result_len, i, name_len, value_len; - char *result= NULL, *new_pos, *name= NULL, *value= NULL, *params[2], *cpt; - unsigned int param_lengths[2]; - - if(argc != 3) { - fprintf(stderr, "usage: %s [-]name[xNNN] [-]value[xNNN]\n", argv[0]); - exit(1); - } - for(i= 0; i < 2; i++) { - params[i]= argv[i + 1]; - if(argv[i + 1][0] == '-') { - cpt= strchr(argv[i + 1], 'x'); - if(cpt != NULL) { - l= cpt - argv[i + 1] - 1; - if(l > 0) - sscanf(cpt + 1, "%d", &mult); - if(l > 0 && mult > 0) { - params[i]= calloc(1, l * mult + 1); - if(params[i] != NULL) { - for(k= 0; k < mult; k++) - memcpy(params[i] + k * l, argv[i + 1] + 1, l); - params[i][mult * l]= 0; - } else - params[i]= argv[i + 1]; - } - } - } - } - param_lengths[0]= strlen(params[0]); - param_lengths[1]= strlen(params[1]); - ret= aaip_encode("AA", "PAIR", 2, param_lengths, params, - &result_len, &result, 0); - if(ret <= 0) { - 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"); - - ret= aaip_decode_pair("AA", result, result_len, &new_pos, - &name_len, &name, &value_len, &value, 0); - if(ret <= 0) { - fprintf(stderr, "%s : aaip_decode_pair failed with ret= %d\n", - argv[0], ret); - exit(3); - } - if(mult == 0 || (name_len < 1000 && value_len < 1000)) { - printf("name = '%s' (%lu)\n", name, (unsigned long) name_len); - printf("value= '%s' (%lu)\n", value, (unsigned long) value_len); - } else { - printf("name = (%lu)\n", (unsigned long) name_len); - printf("value= (%lu)\n", (unsigned long) value_len); - } - printf("\n"); - - if(result != NULL) - free(result); - if(name != NULL) - free(name); - if(value != NULL) - free(value); - exit(0); -} -