xorriso  1.5.4.pl02
About: GNU xorriso creates, loads, manipulates and writes ISO 9660 filesystem images with Rock Ridge extensions. It is suitable for incremental data backup and for production of bootable ISO 9660 images. GNU xorriso is a statical compilation of the libraries libburn, libisofs, libisoburn, and libjte.
  Fossies Dox: xorriso-1.5.4.pl02.tar.gz  ("unofficial" and yet experimental doxygen-generated source code documentation)  

aaip_0_2.c
Go to the documentation of this file.
1 
2 /*
3 
4  Arbitrary Attribute Interchange Protocol , AAIP versions 0.2 , 1.0 , 2.0.
5  Implementation of encoding and decoding xattr and ACL.
6 
7  See libisofs/aaip_0_2.h
8  http://libburnia-project.org/wiki/AAIP
9 
10  Copyright (c) 2009 - 2019 Thomas Schmitt
11 
12  This file is part of the libisofs project; you can redistribute it and/or
13  modify it under the terms of the GNU General Public License version 2
14  or later as published by the Free Software Foundation.
15  See COPYING file for details.
16 
17 */
18 
19 #ifdef HAVE_CONFIG_H
20 #include "../config.h"
21 #endif
22 
23 #include <ctype.h>
24 #include <sys/types.h>
25 #include <unistd.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include <stdio.h>
29 #include <pwd.h>
30 #include <grp.h>
31 #include <sys/stat.h>
32 
33 #include "libisofs.h"
34 #include "util.h"
35 #include "messages.h"
36 
37 /*
38 #define Aaip_encode_debuG 1
39 */
40 
41 #include "aaip_0_2.h"
42 
43 #define Aaip_EXEC 1
44 #define Aaip_WRITE 2
45 #define Aaip_READ 4
46 
47 #define Aaip_TRANSLATE 0
48 #define Aaip_ACL_USER_OBJ 1
49 #define Aaip_ACL_USER 2
50 #define Aaip_ACL_GROUP_OBJ 3
51 #define Aaip_ACL_GROUP 4
52 #define Aaip_ACL_MASK 5
53 #define Aaip_ACL_OTHER 6
54 #define Aaip_SWITCH_MARK 8
55 #define Aaip_ACL_USER_N 10
56 #define Aaip_ACL_GROUP_N 12
57 #define Aaip_FUTURE_VERSION 15
58 
59 #define Aaip_with_short_namespaceS yes
60 #define Aaip_max_named_spacE 0x06
61 #define Aaip_min_named_spacE 0x02
62 #define Aaip_maxdef_namespacE 0x1f
63 
64 #define Aaip_namespace_literaL 0x01
65 #define Aaip_namespace_systeM 0x02
66 #define Aaip_namespace_useR 0x03
67 #define Aaip_namespace_isofS 0x04
68 #define Aaip_namespace_trusteD 0x05
69 #define Aaip_namespace_securitY 0x06
70 
71 /* maximum expansion: "security." */
72 #define Aaip_max_name_expansioN 9
73 
75  {"", "", "system.", "user.", "isofs.", "trusted.", "security."};
76 
77 /* --------------------------------- Encoder ---------------------------- */
78 
79 
80 static int aaip_encode_pair(char *name, size_t attr_length, char *attr,
81  unsigned int *num_recs, size_t *comp_size,
82  unsigned char *result, size_t result_fill,
83  int flag);
84 
85 
86 /* Convert an array of Arbitrary Attributes into a series of AAIP fields.
87  @param num_attrs Number of attributes
88  @param names Array of pointers to 0 terminated name strings
89  @param value_lengths Array of byte lengths for each value
90  @param values Array of pointers to the value bytes
91  @param result_len Number of bytes in the resulting SUSP field string
92  @param result *result will point to the start of the result string.
93  This is malloc() memory which needs to be freed when
94  no longer needed
95  @param flag Bitfield for control purposes
96  bit0= set CONTINUE bit of last AAIP field to 1
97  @return >= 0 is the number of SUSP fields generated,
98  < 0 means error
99 */
100 ssize_t aaip_encode(size_t num_attrs, char **names,
101  size_t *value_lengths, char **values,
102  size_t *result_len, unsigned char **result, int flag)
103 {
104  size_t mem_size= 0, comp_size;
105  ssize_t ret;
106  unsigned int number_of_fields, i, num_recs;
107 
108  /* Predict memory needs, number of SUSP fields and component records */
109  *result = NULL;
110  *result_len= 0;
111  for(i= 0; i < num_attrs; i++) {
112  ret= aaip_encode_pair(names[i], value_lengths[i], values[i],
113  &num_recs, &comp_size, NULL, (size_t) 0, 1);
114  if(ret < 0)
115  return(ret);
116  mem_size+= comp_size;
117  }
118  number_of_fields= mem_size / 250 + !!(mem_size % 250);
119  if(number_of_fields == 0)
120  return(0);
121  mem_size+= number_of_fields * 5;
122 
123 #ifdef Aaip_encode_debuG
124  *result= (unsigned char *) calloc(1, mem_size + 1024000);
125  /* generous honeypot for overflows */
126 #else
127  *result= (unsigned char *) calloc(1, mem_size);
128 #endif
129 
130  if(*result == NULL)
131  return ISO_OUT_OF_MEM;
132 
133  /* Encode pairs into result */
134  for(i= 0; i < num_attrs; i++) {
135  ret= aaip_encode_pair(names[i], value_lengths[i], values[i],
136  &num_recs, &comp_size, *result, *result_len, 0);
137  if(ret < 0) {
138  free(*result);
139  *result = NULL;
140  *result_len = 0;
141  return(ret);
142  }
143  (*result_len)+= comp_size;
144  }
145 
146  /* write the field headers */
147  for(i= 0; i < number_of_fields; i++) {
148  (*result)[i * 255 + 0]= 'A';
149  (*result)[i * 255 + 1]= 'L';
150  if(i < number_of_fields - 1 || (mem_size % 255) == 0)
151  (*result)[i * 255 + 2]= 255;
152  else
153  (*result)[i * 255 + 2]= mem_size % 255;
154  (*result)[i * 255 + 3]= 1;
155  (*result)[i * 255 + 4]= (flag & 1) || (i < number_of_fields - 1);
156  }
157  (*result_len)+= number_of_fields * 5;
158 
159 #ifdef Aaip_encode_debuG
160  if(*result_len != mem_size) {
161  fprintf(stderr, "aaip_encode(): MEMORY MISMATCH BY %d BYTES\n",
162  (int) (mem_size - *result_len));
163  } else {
164  unsigned char *hpt;
165  hpt= malloc(*result_len);
166  if(hpt != NULL) {
167  memcpy(hpt, *result, *result_len);
168  free(*result);
169  *result= hpt;
170  }
171  }
172  ret= 0;
173  for(i= 0; i < *result_len; i+= ((unsigned char *) (*result))[i + 2])
174  ret++;
175  if(ret != (int) number_of_fields) {
176  fprintf(stderr, "aaip_encode(): WRONG NUMBER OF FIELDS %d <> %d\n",
177  (int) number_of_fields, ret);
178  }
179 #endif /* Aaip_encode_debuG */
180 
181  return(number_of_fields);
182 }
183 
184 
185 static void aaip_encode_byte(unsigned char *result, size_t *result_fill,
186  unsigned char value)
187 {
188  result[(*result_fill / 250) * 255 + 5 + (*result_fill % 250)]= value;
189  (*result_fill)++;
190 }
191 
192 
193 static int aaip_encode_comp(unsigned char *result, size_t *result_fill,
194  int prefix, char *data, size_t l, int flag)
195 {
196  size_t todo;
197  char *rpt, *comp_start;
198 
199  if(l == 0 && prefix <= 0) {
200  aaip_encode_byte(result, result_fill, 0);
201  aaip_encode_byte(result, result_fill, 0);
202  return(1);
203  }
204  for(rpt= data; rpt - data < (ssize_t) l;) {
205  todo= l - (rpt - data) + (prefix > 0);
206  aaip_encode_byte(result, result_fill, (todo > 255));
207  if(todo > 255)
208  todo= 255;
209  aaip_encode_byte(result, result_fill, todo);
210  if(prefix > 0) {
211  aaip_encode_byte(result, result_fill, prefix);
212  todo--;
213  prefix= 0;
214  }
215  for(comp_start= rpt; rpt - comp_start < (ssize_t) todo; rpt++)
216  aaip_encode_byte(result, result_fill, *((unsigned char *) rpt));
217  }
218  return(1);
219 }
220 
221 
222 /* Write the component records for name and attr. Skip the positions of
223  AAIP field headers.
224  @param flag bit0= only count but do not produce result
225 */
226 static int aaip_encode_pair(char *name, size_t attr_length, char *attr,
227  unsigned int *num_recs, size_t *comp_size,
228  unsigned char *result, size_t result_fill,
229  int flag)
230 {
231  size_t l;
232  int i, prefix= 0;
233 
234 #ifdef Aaip_with_short_namespaceS
235 
236  /* translate name into eventual short form */
237  for(i= Aaip_min_named_spacE; i <= Aaip_max_named_spacE; i++)
238  if(strncmp(name, Aaip_namespace_textS[i], strlen(Aaip_namespace_textS[i]))
239  == 0) {
240  name+= strlen(Aaip_namespace_textS[i]);
241  prefix= i;
242  }
243  /* Eventually prepend escape marker for strange names */
244  if(prefix <= 0 && name[0] > 0 && name[0] <= Aaip_maxdef_namespacE)
245  prefix= Aaip_namespace_literaL;
246 
247 #endif /* Aaip_with_short_namespaceS */
248 
249  l= strlen(name) + (prefix > 0);
250  *num_recs= l / 255 + (!!(l % 255)) + (l == 0) +
251  attr_length / 255 + (!!(attr_length % 255)) + (attr_length == 0);
252  *comp_size= l + attr_length + 2 * *num_recs;
253 
254  if(flag & 1)
255  return(1);
256 
257  aaip_encode_comp(result, &result_fill, prefix, name, l - (prefix > 0), 0);
258  aaip_encode_comp(result, &result_fill, 0, attr, attr_length, 0);
259  return(1);
260 }
261 
262 
263 /* ----------- Encoder for ACLs ----------- */
264 
265 static ssize_t aaip_encode_acl_text(char *acl_text, mode_t st_mode,
266  size_t result_size, unsigned char *result, int flag);
267 
268 
269 /* Convert an ACL text as of acl_to_text(3) into the value of an Arbitrary
270  Attribute. According to AAIP this value is to be stored together with
271  an empty name.
272  @param acl_text The ACL in long text form
273  @param st_mode The stat(2) permission bits to be used with flag bit3
274  @param result_len Number of bytes in the resulting value
275  @param result *result will point to the start of the result string.
276  This is malloc() memory which needs to be freed when
277  no longer needed
278  @param flag Bitfield for control purposes
279  bit0= count only
280  bit1= use numeric qualifiers rather than names
281  bit2= this is a default ACL, prepend SWITCH_MARK
282  bit3= check for completeness of list and eventually
283  fill up with entries deduced from st_mode
284  bit4= be verbose about failure causes
285  @return >0 means ok
286  <=0 means error
287  -1= out of memory
288  -2= program error with prediction of result size
289  -3= error with conversion of name to uid or gid
290  ISO_AAIP_ACL_MULT_OBJ= multiple entries of user::, group::, other::
291 */
292 int aaip_encode_acl(char *acl_text, mode_t st_mode,
293  size_t *result_len, unsigned char **result, int flag)
294 {
295  ssize_t bytes;
296 
297  *result= NULL;
298  *result_len= 0;
299  bytes= aaip_encode_acl_text(acl_text, st_mode,
300  (size_t) 0, NULL, 1 | (flag & (2 | 4 | 8 | 16)));
301  if(bytes < -2)
302  return(bytes);
303  if(bytes < 0)
304  return((int) bytes - 1);
305  if(flag & 1) {
306  *result_len= bytes;
307  return(1);
308  }
309  *result= calloc(bytes + 1, 1);
310  if(*result == NULL)
311  return(-1);
312  (*result)[bytes]= 0;
313  *result_len= bytes;
314  bytes= aaip_encode_acl_text(acl_text, st_mode, *result_len, *result,
315  (flag & (2 | 4 | 8 | 16)));
316  if(bytes < -2)
317  return(bytes);
318  if(bytes < 0)
319  return((int) bytes - 1);
320  if((size_t) bytes != *result_len) {
321  *result_len= 0;
322  return(-2);
323  }
324  return(1);
325 }
326 
327 
328 static double aaip_numeric_id(char *name, int flag)
329 {
330  double num;
331  char *cpt;
332 
333  for(cpt= name; *cpt != 0; cpt++)
334  if(*cpt < '0' || *cpt >'9')
335  break;
336  if(*cpt != 0)
337  return(-1);
338  sscanf(name, "%lf", &num);
339  return(num);
340 }
341 
342 
343 static int aaip_make_aaip_perms(int r, int w, int x)
344 {
345  int perms;
346 
347  perms= 0;
348  if(r)
349  perms|= Aaip_READ;
350  if(w)
351  perms|= Aaip_WRITE;
352  if(x)
353  perms|= Aaip_EXEC;
354  return(perms);
355 }
356 
357 
358 /*
359  @param result_size Number of bytes to store result
360  @param result Pointer to the start of the result string.
361  @param flag Bitfield for control purposes
362  bit0= count only, do not really produce bytes
363  bit1= use numeric qualifiers
364  bit2= this is a default ACL, prepend SWITCH_MARK 1
365  bit3= check for completeness of list and eventually
366  fill up with entries deduced from st_mode
367  bit4= be verbose about failure causes
368  @return >=0 number of bytes produced resp. counted
369  <0 means error
370  -1: result size overflow
371  -2: conversion error with user name or group name
372  ISO_AAIP_ACL_MULT_OBJ: multiple entries of user::, group::, other::
373 */
374 static ssize_t aaip_encode_acl_text(char *acl_text, mode_t st_mode,
375  size_t result_size, unsigned char *result, int flag)
376 {
377  char *rpt, *npt, *cpt;
378  int qualifier= 0, perms, type, i, qualifier_len= 0, num_recs, needed= 0, ret;
379  unsigned int has_u= 0, has_g= 0, has_o= 0, has_m= 0, is_trivial= 1;
380  uid_t uid, huid;
381  gid_t gid, hgid;
382  ssize_t count= 0;
383  struct passwd *pwd;
384  struct group *grp;
385  char *name = NULL;
386  int name_size= 1024;
387  double num;
388 
389  LIBISO_ALLOC_MEM(name, char, name_size);
390  if(flag & 4) {
391  /* set SWITCH_MARK to indicate a default ACL */;
392  if(!(flag & 1)) {
393  if((size_t) count >= result_size)
394  goto result_size_overflow;
395  result[count]= (Aaip_SWITCH_MARK << 4) | Aaip_EXEC;
396  }
397  count++;
398  }
399 
400  for(rpt= acl_text; *rpt != 0; rpt= npt) {
401  npt= strchr(rpt, '\n');
402  if(npt == 0)
403  npt= rpt + strlen(rpt);
404  else
405  npt++;
406  if(*rpt == '#')
407  continue;
408  cpt= strchr(rpt, ':');
409  if(cpt == NULL)
410  continue;
411  cpt= strchr(cpt + 1, ':');
412  if(cpt == NULL)
413  continue;
414  qualifier= 0;
415  if(strncmp(rpt, "user:", 5) == 0) {
416  if(cpt - rpt == 5) {
417  type= Aaip_ACL_USER_OBJ;
418  if (has_u) {
419 
420  /* >>> Duplicate u:: entry. */;
421  /* >>> ??? If it matches the previous one: ignore */
422 
423  if(flag & 16)
425  "Duplicate u:: entry detected in ACL text");
426  ret = ISO_AAIP_ACL_MULT_OBJ;
427  goto ex;
428  }
429  has_u++;
430  } else {
431  if(cpt - (rpt + 5) >= name_size)
432  continue;
433  is_trivial= 0;
434  strncpy(name, rpt + 5, cpt - (rpt + 5));
435  name[cpt - (rpt + 5)]= 0;
436  if(flag & 2) {
437  type= Aaip_ACL_USER_N;
438  pwd= getpwnam(name);
439  if(pwd == NULL) {
440  num= aaip_numeric_id(name, 0);
441  if(num <= 0) {
442  /* ACL_USER is not part of AAIP 2.0 */
443  if(flag & 16)
445  "Unknown user name found in ACL text: '%s'", name);
446  {ret= -2; goto ex;}
447  }
448  uid= huid= num;
449  } else
450  uid= huid= pwd->pw_uid;
451  /* Convert uid into Qualifier Record */
452  for(i= 0; huid != 0; i++)
453  huid= huid >> 8;
454  qualifier_len= i;
455  if(qualifier_len <= 0)
456  qualifier_len= 1;
457  for(i= 0; i < qualifier_len ; i++)
458  name[i]= uid >> (8 * (qualifier_len - i - 1));
459  } else {
460  type= Aaip_ACL_USER;
461  qualifier_len= strlen(name);
462  if(qualifier_len <= 0)
463  qualifier_len= 1;
464  }
465  qualifier= 1;
466  }
467  } else if(strncmp(rpt, "group:", 6) == 0) {
468  if(cpt - rpt == 6) {
469  type= Aaip_ACL_GROUP_OBJ;
470  if (has_g) {
471 
472  /* >>> Duplicate g:: entry. */;
473  /* >>> ??? If it matches the previous one: ignore */
474 
475  if(flag & 16)
477  "Duplicate g:: entry detected in ACL text");
478  ret = ISO_AAIP_ACL_MULT_OBJ;
479  goto ex;
480  }
481  has_g++;
482  } else {
483  if(cpt - (rpt + 6) >= name_size)
484  continue;
485  is_trivial= 0;
486  strncpy(name, rpt + 6, cpt - (rpt + 6));
487  name[cpt - (rpt + 6)]= 0;
488  if(flag & 2) {
489  type= Aaip_ACL_GROUP_N;
490  grp= getgrnam(name);
491  if(grp == NULL) {
492  num= aaip_numeric_id(name, 0);
493  if(num <= 0) {
494  /* ACL_GROUP is not part of AAIP 2.0 */
495  if(flag & 16)
497  "Unknown group name found in ACL text: '%s'", name);
498  {ret= -2; goto ex;}
499  }
500  gid= hgid= num;
501  } else
502  gid= hgid= grp->gr_gid;
503  /* Convert gid into Qualifier Record */
504  for(i= 0; hgid != 0; i++)
505  hgid= hgid >> 8;
506  qualifier_len= i;
507  if(qualifier_len <= 0)
508  qualifier_len= 1;
509  for(i= 0; i < qualifier_len ; i++)
510  name[i]= gid >> (8 * (qualifier_len - i - 1));
511  } else {
512  type= Aaip_ACL_GROUP;
513  qualifier_len= strlen(name);
514  if(qualifier_len <= 0)
515  qualifier_len= 1;
516  }
517  qualifier= 1;
518  }
519  } else if(strncmp(rpt, "other:", 6) == 0) {
520  type= Aaip_ACL_OTHER;
521  if (has_o) {
522 
523  /* >>> Duplicate o:: entry. */;
524  /* >>> ??? If it matches the previous one: ignore */
525 
526  if(flag & 16)
528  "Duplicate o:: entry detected in ACL text");
529  ret = ISO_AAIP_ACL_MULT_OBJ;
530  goto ex;
531  }
532  has_o++;
533  } else if(strncmp(rpt, "mask:", 5) == 0) {
534  type= Aaip_ACL_MASK;
535  has_m++;
536  } else
537  continue;
538 
539  if(npt - cpt < 4)
540  continue;
541  perms= aaip_make_aaip_perms(cpt[1] == 'r', cpt[2] == 'w', cpt[3] == 'x');
542 
543  if(!(flag & 1)) {
544  if((size_t) count >= result_size)
545  goto result_size_overflow;
546  result[count]= perms | ((!!qualifier) << 3) | (type << 4);
547  }
548  count++;
549 
550  if(qualifier) {
551  num_recs= (qualifier_len / 127) + !!(qualifier_len % 127);
552  if(!(flag & 1)) {
553  if((size_t) (count + 1) > result_size)
554  goto result_size_overflow;
555  for(i= 0; i < num_recs; i++) {
556  if(i < num_recs - 1)
557  result[count++]= 255;
558  else {
559  result[count++]= (qualifier_len % 127);
560  if(result[count - 1] == 0)
561  result[count - 1]= 127;
562  }
563  if((size_t) (count + (result[count - 1] & 127)) > result_size)
564  goto result_size_overflow;
565  memcpy(result + count, name + i * 127, result[count - 1] & 127);
566  count+= result[count - 1] & 127;
567  }
568  } else
569  count+= qualifier_len + num_recs;
570  }
571  }
572  if (flag & 8) {
573  /* add eventually missing mandatory ACL entries */
574  needed= (!has_u) + (!has_g) + (!has_o) + !(is_trivial || has_m);
575  if(flag & 1)
576  count+= needed;
577  else {
578  if((size_t) (count + needed) > result_size)
579  goto result_size_overflow;
580  }
581  }
582  if ((flag & 8) && needed > 0 && !(flag & 1)) {
583  if(!has_u) {
584  perms= aaip_make_aaip_perms(st_mode & S_IRUSR, st_mode & S_IWUSR,
585  st_mode * S_IXUSR);
586  result[count++]= perms | (Aaip_ACL_USER_OBJ << 4);
587  }
588  if(!has_g) {
589  perms= aaip_make_aaip_perms(st_mode & S_IRGRP, st_mode & S_IWGRP,
590  st_mode * S_IXGRP);
591  result[count++]= perms | (Aaip_ACL_GROUP_OBJ << 4);
592  }
593  if(!has_o) {
594  perms= aaip_make_aaip_perms(st_mode & S_IROTH, st_mode & S_IWOTH,
595  st_mode * S_IXOTH);
596  result[count++]= perms | (Aaip_ACL_OTHER << 4);
597  }
598  if(!(is_trivial | has_m)) {
599  perms= aaip_make_aaip_perms(st_mode & S_IRGRP, st_mode & S_IWGRP,
600  st_mode * S_IXGRP);
601  result[count++]= perms | (Aaip_ACL_MASK << 4);
602  }
603  }
604  ret= count;
605 ex:;
606  LIBISO_FREE_MEM(name);
607  return(ret);
608 
609 result_size_overflow:;
610  if(flag & 16)
612  "Program error: Text to ACL conversion result size overflow");
613  ret= -1;
614  goto ex;
615 }
616 
617 
618 int aaip_encode_both_acl(char *a_acl_text, char *d_acl_text, mode_t st_mode,
619  size_t *result_len, unsigned char **result, int flag)
620 {
621  int ret;
622  size_t a_acl_len= 0, d_acl_len= 0, acl_len= 0;
623  unsigned char *a_acl= NULL, *d_acl= NULL, *acl= NULL;
624 
625  if(a_acl_text != NULL) {
626  ret= aaip_encode_acl(a_acl_text, st_mode, &a_acl_len, &a_acl,
627  flag & (1 | 2 | 8 | 16));
628  if(ret <= 0)
629  goto ex;
630  }
631  if(d_acl_text != NULL) {
632  ret= aaip_encode_acl(d_acl_text, (mode_t) 0, &d_acl_len, &d_acl,
633  (flag & (1 | 2 | 16)) | 4);
634  if(ret <= 0)
635  goto ex;
636  }
637  if(a_acl == NULL || a_acl_len == 0) {
638  acl= d_acl;
639  d_acl= NULL;
640  acl_len= d_acl_len;
641  } else if (d_acl == NULL || d_acl_len == 0) {
642  acl= a_acl;
643  a_acl= NULL;
644  acl_len= a_acl_len;
645  } else {
646  acl= calloc(a_acl_len + d_acl_len, 1);
647  if(acl == NULL)
648  {ret = -1; goto ex;}
649  memcpy(acl, a_acl, a_acl_len);
650  memcpy(acl + a_acl_len, d_acl, d_acl_len);
651  acl_len= a_acl_len + d_acl_len;
652  }
653  *result= acl;
654  *result_len= acl_len;
655  ret= 1;
656 ex:;
657  if(a_acl != NULL)
658  free(a_acl);
659  if(d_acl != NULL)
660  free(d_acl);
661  return(ret);
662 }
663 
664 
665 /* GNU/Linux man 5 acl says:
666  The permissions defined by ACLs are a superset of the permissions speci-
667  fied by the file permission bits. The permissions defined for the file
668  owner correspond to the permissions of the ACL_USER_OBJ entry. The per-
669  missions defined for the file group correspond to the permissions of the
670  ACL_GROUP_OBJ entry, if the ACL has no ACL_MASK entry. If the ACL has an
671  ACL_MASK entry, then the permissions defined for the file group corre-
672  spond to the permissions of the ACL_MASK entry. The permissions defined
673  for the other class correspond to the permissions of the ACL_OTHER_OBJ
674  entry.
675 
676  Modification of the file permission bits results in the modification of
677  the permissions in the associated ACL entries. Modification of the per-
678  missions in the ACL entries results in the modification of the file per-
679  mission bits.
680 
681 */
682 /* Analyze occurrence of ACL tag types in long text form. If not disabled by
683  parameter flag remove the entries of type "user::" , "group::" , "other::" ,
684  or "other:" from an ACL in long text form if they match the bits in st_mode
685  as described by man 2 stat and man 5 acl.
686  @param acl_text The text to be analyzed and eventually shortened.
687  @param st_mode The component of struct stat which tells POSIX permission
688  bits and eventually shall take equivalent bits as read
689  from the ACL. The caller should submit a pointer
690  to the st_mode variable which holds permissions as
691  indicated by stat(2) resp. ECMA-119 and RRIP data.
692  @param flag bit0= do not remove entries, only determine return value
693  bit1= like bit0 but return immediately if a non-st_mode
694  ACL entry is found
695  bit2= update *st_mode by acl_text
696  ("user::" -> S_IRWXU, "mask::"|"group::" -> S_IRWXG,
697  "other::" -> S_IRWXO)
698  bit3= update acl_text by *st_mode (same mapping as bit 2
699  but with reversed transfer direction)
700  bit4= map "group::" <-> S_IRWXG in any case.
701  I.e. ignore "mask::".
702  @return <0 failure
703  >=0 tells in its bits which tag types were found.
704  The first three tell which types deviate from the
705  corresponding st_mode settings:
706  bit0= "other::" overrides S_IRWXO
707  bit1= "group::" overrides S_IRWXG (no "mask::" found)
708  bit2= "user::" overrides S_IRWXU
709  The second three tell which types comply with st_mode:
710  bit3= "other::" matches S_IRWXO
711  bit4= "group::" matches S_IRWXG (no "mask::" found)
712  bit5= "user::" matches S_IRWXU
713  Given the nature of ACLs nearly all combinations are
714  possible although some would come from invalid ACLs.
715  bit6= other ACL tag types are present. Particularly:
716  bit7= "user:...:" is present
717  bit8= "group:...:" is present
718  bit9= "mask::" is present
719 */
720 int aaip_cleanout_st_mode(char *acl_text, mode_t *in_st_mode, int flag)
721 {
722  char *rpt, *wpt, *npt, *cpt;
723  mode_t m, list_mode, st_mode;
724  int tag_types= 0, has_mask= 0, do_cleanout = 0;
725 
726  list_mode= st_mode= *in_st_mode;
727  do_cleanout = !(flag & 15);
728 
729  has_mask= strncmp(acl_text, "mask:", 5) == 0 ||
730  strstr(acl_text, "\nmask:") != NULL;
731  if(has_mask && (flag & 2))
732  return(64 | 512);
733 
734  for(npt= wpt= rpt= acl_text; *npt != 0; rpt= npt + 1) {
735  npt= strchr(rpt, '\n');
736  if(npt == NULL)
737  npt= rpt + strlen(rpt);
738  if(strncmp(rpt, "user:", 5) == 0) {
739  if(rpt[5] == ':' && npt - rpt == 9) {
740  cpt= rpt + 6;
741  m= 0;
742  if(cpt[0] == 'r')
743  m|= S_IRUSR;
744  if(cpt[1] == 'w')
745  m|= S_IWUSR;
746  if(cpt[2] == 'x')
747  m|= S_IXUSR;
748  list_mode= (list_mode & ~S_IRWXU) | m;
749  if((st_mode & S_IRWXU) == (m & S_IRWXU)) {
750  tag_types|= 32;
751  continue;
752  }
753  if(flag & 8) {
754  cpt[0]= st_mode & S_IRUSR ? 'r' : '-';
755  cpt[1]= st_mode & S_IWUSR ? 'w' : '-';
756  cpt[2]= st_mode & S_IXUSR ? 'x' : '-';
757  }
758  tag_types|= 4;
759  } else {
760  tag_types|= 64 | 128;
761  }
762  } else if(strncmp(rpt, "group:", 6) == 0) {
763  if(rpt[6] == ':' && npt - rpt == 10 && ((flag & 16) || !has_mask)) {
764  /* oddly: mask overrides group in st_mode */
765  cpt= rpt + 7;
766  m= 0;
767  if(cpt[0] == 'r')
768  m|= S_IRGRP;
769  if(cpt[1] == 'w')
770  m|= S_IWGRP;
771  if(cpt[2] == 'x')
772  m|= S_IXGRP;
773  list_mode= (list_mode & ~S_IRWXG) | m;
774  if((st_mode & S_IRWXG) == (m & S_IRWXG)) {
775  tag_types|= 16;
776  continue;
777  }
778  if(flag & 8) {
779  cpt[0]= st_mode & S_IRGRP ? 'r' : '-';
780  cpt[1]= st_mode & S_IWGRP ? 'w' : '-';
781  cpt[2]= st_mode & S_IXGRP ? 'x' : '-';
782  }
783  tag_types|= 2;
784  } else {
785  if(rpt[6] == ':' && npt - rpt == 10)
786  tag_types|= 1024;
787  else
788  tag_types|= 64 | 256;
789  }
790  } else if(strncmp(rpt, "other::", 7) == 0 && npt - rpt == 10) {
791  cpt= rpt + 7;
792 others_st_mode:;
793  m= 0;
794  if(cpt[0] == 'r')
795  m|= S_IROTH;
796  if(cpt[1] == 'w')
797  m|= S_IWOTH;
798  if(cpt[2] == 'x')
799  m|= S_IXOTH;
800  list_mode= (list_mode & ~S_IRWXO) | m;
801  if((st_mode & S_IRWXO) == (m & S_IRWXO)) {
802  tag_types|= 8;
803  continue;
804  }
805  if(flag & 8) {
806  cpt[0]= st_mode & S_IROTH ? 'r' : '-';
807  cpt[1]= st_mode & S_IWOTH ? 'w' : '-';
808  cpt[2]= st_mode & S_IXOTH ? 'x' : '-';
809  }
810  tag_types|= 1;
811  } else if(strncmp(rpt, "other:", 6) == 0 && npt - rpt == 9) {
812  cpt= rpt + 7;
813  goto others_st_mode;
814  } else if(strncmp(rpt, "mask::", 6) == 0 && npt - rpt == 9) {
815  cpt= rpt + 6;
816 mask_st_mode:;
817  tag_types|= 64 | 512;
818  if(!(flag & 16)) {
819  /* oddly: mask overrides group in st_mode */
820  m= 0;
821  if(cpt[0] == 'r')
822  m|= S_IRGRP;
823  if(cpt[1] == 'w')
824  m|= S_IWGRP;
825  if(cpt[2] == 'x')
826  m|= S_IXGRP;
827  list_mode= (list_mode & ~S_IRWXG) | m;
828  if(flag & 8) {
829  cpt[0]= st_mode & S_IRGRP ? 'r' : '-';
830  cpt[1]= st_mode & S_IWGRP ? 'w' : '-';
831  cpt[2]= st_mode & S_IXGRP ? 'x' : '-';
832  }
833  }
834  } else if(strncmp(rpt, "mask:", 5) == 0 && npt - rpt == 8) {
835  cpt= rpt + 5;
836  goto mask_st_mode;
837  } else if(*rpt != 0) {
838  tag_types|= 64;
839  }
840  if (flag & 2)
841  goto ex;
842  if(wpt == rpt) {
843  wpt= npt + 1;
844  continue;
845  }
846  if(do_cleanout)
847  memmove(wpt, rpt, 1 + npt - rpt);
848  wpt+= 1 + npt - rpt;
849  }
850  if(do_cleanout) {
851  if(wpt == acl_text)
852  *wpt= 0;
853  else if(*(wpt - 1) != 0)
854  *wpt= 0;
855  }
856 ex:;
857  if(flag & 4)
858  *in_st_mode= list_mode;
859  return(tag_types);
860 }
861 
862 
863 /* Important: acl_text must provide 42 bytes more than its current length !
864 */
865 int aaip_add_acl_st_mode(char *acl_text, mode_t st_mode, int flag)
866 {
867  char *wpt;
868  int tag_types= 0;
869 
870  tag_types = aaip_cleanout_st_mode(acl_text, &st_mode, 1);
871  if(!(tag_types & (4 | 32))) {
872  wpt= acl_text + strlen(acl_text);
873  sprintf(wpt, "user::%c%c%c\n",
874  st_mode & S_IRUSR ? 'r' : '-',
875  st_mode & S_IWUSR ? 'w' : '-',
876  st_mode & S_IXUSR ? 'x' : '-');
877  }
878  if(!(tag_types & (2 | 16 | 1024))) {
879  wpt= acl_text + strlen(acl_text);
880  sprintf(wpt, "group::%c%c%c\n",
881  st_mode & S_IRGRP ? 'r' : '-',
882  st_mode & S_IWGRP ? 'w' : '-',
883  st_mode & S_IXGRP ? 'x' : '-');
884  }
885  if(!(tag_types & (1 | 8))) {
886  wpt= acl_text + strlen(acl_text);
887  sprintf(wpt, "other::%c%c%c\n",
888  st_mode & S_IROTH ? 'r' : '-',
889  st_mode & S_IWOTH ? 'w' : '-',
890  st_mode & S_IXOTH ? 'x' : '-');
891  }
892  if((tag_types & (128 | 256)) && !(tag_types & 512)) {
893  wpt= acl_text + strlen(acl_text);
894  sprintf(wpt, "mask::%c%c%c\n",
895  st_mode & S_IRGRP ? 'r' : '-',
896  st_mode & S_IWGRP ? 'w' : '-',
897  st_mode & S_IXGRP ? 'x' : '-');
898  }
899  return(1);
900 }
901 
902 
903 /* --------------------------------- Decoder ---------------------------- */
904 
905 /* --- private --- */
906 
907 /* Not less than 2 * 2048 */
908 #define Aaip_buffer_sizE 4096
909 
910 /* Enough for one full component record and three empty ones which might get
911  added in case of unclean end of attribute list.
912 */
913 #define Aaip_buffer_reservE (257 + 3 * 2)
914 
915 
916 struct aaip_state {
917 
918  /* AAIP field status */
919  int aa_head_missing; /* number of bytes needed to complete field header */
920  int aa_missing; /* number of bytes needed to complete current field */
921  int aa_ends; /* 0= still fields expected, 1= last field being processed,
922  2= all fields processed, 3= all is delivered */
923 
924  /* Buffer for component records */
925  int recs_invalid; /* number of components to skip */
927  size_t recs_fill;
928  unsigned char *recs_start;
929  int rec_head_missing; /* number of bytes needed to complete rec header */
930  int rec_missing; /* number of bytes needed to complete current rec */
931  int rec_ends;
932 
933  /* Counter for completed data */
934  unsigned int num_recs;
935  size_t ready_bytes;
936 
937  /* Counter and meaning for completed components */
938  unsigned int num_components;
939  size_t end_of_components; /* start index of eventual incomplete component */
941 
942  /* Last return value of aaip_decode_pair() */
944  unsigned int pairs_skipped;
945 
946  /* status of aaip_decode_attrs() */
948  size_t list_size;
950  char **list_names;
952  char **list_values;
953  char *name_buf;
956  char *value_buf;
960 };
961 
962 
963 /* ------- functions ------ */
964 
965 
966 size_t aaip_count_bytes(unsigned char *data, int flag)
967 {
968  int done = 0;
969  unsigned char *aapt;
970 
971  for(aapt= data; !done; aapt += aapt[2])
972  done = !(aapt[4] & 1);
973  return((size_t) (aapt - data));
974 }
975 
976 
978 {
979  return((size_t) sizeof(struct aaip_state));
980 }
981 
982 
983 int aaip_init_aaip_state(struct aaip_state *aaip, int flag)
984 {
985  aaip->aa_head_missing= 5;
986  aaip->aa_missing= 0;
987 
988  aaip->recs_invalid= 0;
989  memset(aaip->recs, 0, Aaip_buffer_sizE + Aaip_buffer_reservE);
990  aaip->recs_fill= 0;
991  aaip->recs_start= aaip->recs;
992  aaip->rec_head_missing= 2;
993  aaip->rec_missing= 0;
994  aaip->rec_ends= 0;
995 
996  aaip->num_recs= 0;
997  aaip->ready_bytes= 0;
998 
999  aaip->num_components= 0;
1000  aaip->end_of_components= 0;
1001  aaip->first_is_name= 1;
1002 
1003  aaip->pair_status= 2;
1004  aaip->pairs_skipped= 0;
1005 
1006  aaip->list_mem_used= 0;
1007  aaip->list_size= 0;
1008  aaip->list_num_attrs= 0;
1009  aaip->list_names= NULL;
1010  aaip->list_value_lengths= NULL;
1011  aaip->list_values= NULL;
1012  aaip->name_buf= NULL;
1013  aaip->name_buf_size= 0;
1014  aaip->name_buf_fill= 0;
1015  aaip->value_buf= NULL;
1016  aaip->value_buf_size= 0;
1017  aaip->value_buf_fill= 0;
1018  aaip->list_pending_pair= 0;
1019  return(1);
1020 }
1021 
1022 /*
1023 */
1024 #define Aaip_with_ring_buffeR yes
1025 
1026 #ifdef Aaip_with_ring_buffeR
1027 
1028 /* Compute the one or two byte intervals in the ring buffer which form a
1029  given byte interval in the virtual shift fifo.
1030  @param idx The byte start index in the virtual shift fifo.
1031  @param todo Number of bytes to cover
1032  @param start_pt Will return the start address of the first interval
1033  @param at_start_pt Will return the size of the first interval
1034  @param at_recs Will return the size of the second interval which
1035  always starts at aaip->recs
1036  @param flag Bitfield for control purposes
1037  @return 1= next start_pt is *start_pt + *at_start_pt
1038  2= next start_pt is aaip->recs + *at_recs
1039 */
1040 static int aaip_ring_adr(struct aaip_state *aaip, size_t idx, size_t todo,
1041  unsigned char **start_pt, size_t *at_start_pt,
1042  size_t *at_recs, int flag)
1043 {
1044  size_t ahead;
1045 
1047  - (aaip->recs_start - aaip->recs);
1048  if(idx < ahead)
1049  *start_pt= (aaip->recs_start + idx);
1050  else
1051  *start_pt= aaip->recs + (idx - ahead);
1052  ahead= Aaip_buffer_sizE + Aaip_buffer_reservE - (*start_pt - aaip->recs);
1053  if(todo >= ahead) {
1054  *at_start_pt= ahead;
1055  *at_recs= todo - ahead;
1056  return(2);
1057  }
1058  *at_start_pt= todo;
1059  *at_recs= 0;
1060  return(1);
1061 }
1062 
1063 
1064 /*
1065  @param flag Bitfield for control purposes
1066  bit0= count as ready_bytes
1067 */
1068 static int aaip_push_to_recs(struct aaip_state *aaip, unsigned char *data,
1069  size_t todo, int flag)
1070 {
1071  unsigned char *start_pt;
1072  size_t at_start_pt, at_recs;
1073 
1074  aaip_ring_adr(aaip, aaip->recs_fill, todo,
1075  &start_pt, &at_start_pt, &at_recs, 0);
1076  if(at_start_pt > 0)
1077  memcpy(start_pt, data, at_start_pt);
1078  if(at_recs > 0)
1079  memcpy(aaip->recs, data + at_start_pt, at_recs);
1080  aaip->recs_fill+= todo;
1081  if(flag & 1)
1082  aaip->ready_bytes+= todo;
1083  return(1);
1084 }
1085 
1086 
1087 static int aaip_read_from_recs(struct aaip_state *aaip, size_t idx,
1088  unsigned char *data, size_t num_data, int flag)
1089 {
1090  unsigned char *start_pt;
1091  size_t at_start_pt, at_recs;
1092 
1093  aaip_ring_adr(aaip, idx, num_data,
1094  &start_pt, &at_start_pt, &at_recs, 0);
1095  if(at_start_pt > 0)
1096  memcpy(data, start_pt, at_start_pt);
1097  if(at_recs > 0)
1098  memcpy(data + at_start_pt, aaip->recs, at_recs);
1099  return(1);
1100 }
1101 
1102 
1103 static int aaip_set_buffer_byte(struct aaip_state *aaip, size_t idx,
1104  unsigned char data, int flag)
1105 {
1106  unsigned char *start_pt;
1107  size_t at_start_pt, at_recs;
1108 
1109  aaip_ring_adr(aaip, idx, 1,
1110  &start_pt, &at_start_pt, &at_recs, 0);
1111  *start_pt= data;
1112  return(1);
1113 }
1114 
1115 
1116 static int aaip_get_buffer_byte(struct aaip_state *aaip, size_t idx, int flag)
1117 {
1118  unsigned char *start_pt;
1119  size_t at_start_pt, at_recs;
1120 
1121  aaip_ring_adr(aaip, idx, 1,
1122  &start_pt, &at_start_pt, &at_recs, 0);
1123  return((int) *start_pt);
1124 }
1125 
1126 
1127 static int aaip_shift_recs(struct aaip_state *aaip, size_t todo, int flag)
1128 {
1129  int ret;
1130  unsigned char *start_pt;
1131  size_t at_start_pt, at_recs;
1132 
1133  if(todo < aaip->recs_fill) {
1134  ret= aaip_ring_adr(aaip, 0, todo, &start_pt, &at_start_pt, &at_recs, 0);
1135  if(ret == 1)
1136  aaip->recs_start= start_pt + todo;
1137  else
1138  aaip->recs_start= aaip->recs + at_recs;
1139  } else {
1140  aaip->recs_start= aaip->recs;
1141  }
1142  aaip->recs_fill-= todo;
1143  if(aaip->end_of_components >= todo)
1144  aaip->end_of_components-= todo;
1145  else
1146  aaip->end_of_components= 0;
1147  return(1);
1148 }
1149 
1150 
1151 #else /* Aaip_with_ring_buffeR */
1152 
1153 
1154 /*
1155  @param flag Bitfield for control purposes
1156  bit0= count as ready_bytes
1157 */
1158 static int aaip_push_to_recs(struct aaip_state *aaip, unsigned char *data,
1159  size_t todo, int flag)
1160 {
1161  memcpy(aaip->recs + aaip->recs_fill, data, todo);
1162  aaip->recs_fill+= todo;
1163  if(flag & 1)
1164  aaip->ready_bytes+= todo;
1165  return(1);
1166 }
1167 
1168 
1169 static int aaip_read_from_recs(struct aaip_state *aaip, size_t idx,
1170  unsigned char *data, size_t num_data, int flag)
1171 {
1172  memcpy(data, aaip->recs + idx, num_data);
1173  return(1);
1174 }
1175 
1176 
1177 static int aaip_set_buffer_byte(struct aaip_state *aaip, size_t idx,
1178  unsigned char data, int flag)
1179 {
1180  aaip->recs[idx]= data;
1181  return(1);
1182 }
1183 
1184 
1185 static int aaip_get_buffer_byte(struct aaip_state *aaip, size_t idx, int flag)
1186 {
1187  return((int) aaip->recs[idx]);
1188 }
1189 
1190 
1191 static int aaip_shift_recs(struct aaip_state *aaip, size_t todo, int flag)
1192 {
1193  if(todo < aaip->recs_fill)
1194  memmove(aaip->recs, aaip->recs + todo, aaip->recs_fill - todo);
1195  aaip->recs_fill-= todo;
1196 
1197  if(aaip->end_of_components >= todo)
1198  aaip->end_of_components-= todo;
1199  else
1200  aaip->end_of_components= 0;
1201  return(1);
1202 }
1203 
1204 
1205 #endif /* ! Aaip_with_ring_buffeR */
1206 
1207 
1208 static int aaip_consume_rec_head(struct aaip_state *aaip,
1209  unsigned char **data, size_t *num_data, int flag)
1210 {
1211  size_t todo;
1212 
1213  todo= *num_data;
1214  if(todo > (size_t) aaip->aa_missing)
1215  todo= aaip->aa_missing;
1216  if(todo >= (size_t) aaip->rec_head_missing)
1217  todo= aaip->rec_head_missing;
1218  if(!aaip->recs_invalid)
1219  aaip_push_to_recs(aaip, *data, todo, 0);
1220  aaip->rec_head_missing-= todo;
1221  if(aaip->rec_head_missing == 0) {
1222  aaip->rec_missing= aaip_get_buffer_byte(aaip, aaip->recs_fill - 1, 0);
1223  aaip->rec_ends= !(aaip_get_buffer_byte(aaip, aaip->recs_fill - 2, 0) & 1);
1224  }
1225  aaip->aa_missing-= todo;
1226  (*num_data)-= todo;
1227  (*data)+= todo;
1228  return(1);
1229 }
1230 
1231 
1232 static int aaip_consume_rec_data(struct aaip_state *aaip,
1233  unsigned char **data, size_t *num_data, int flag)
1234 {
1235  size_t todo;
1236 
1237  todo= *num_data;
1238  if(todo > (size_t) aaip->aa_missing)
1239  todo= aaip->aa_missing;
1240  if(todo > (size_t) aaip->rec_missing)
1241  todo= aaip->rec_missing;
1242  if(!aaip->recs_invalid)
1243  aaip_push_to_recs(aaip, *data, todo, 1);
1244  aaip->rec_missing-= todo;
1245  aaip->aa_missing-= todo;
1246  (*num_data)-= todo;
1247  (*data)+= todo;
1248  if(aaip->rec_missing <= 0) {
1249  if(aaip->recs_invalid > 0) {
1250  if(aaip->rec_ends)
1251  aaip->recs_invalid--;
1252  } else {
1253  aaip->num_recs++;
1254  if(aaip->rec_ends) {
1255  aaip->num_components++;
1256  aaip->end_of_components= aaip->recs_fill;
1257  }
1258  }
1259  aaip->rec_head_missing= 2;
1260  }
1261  return(0);
1262 }
1263 
1264 
1265 static int aaip_consume_aa_head(struct aaip_state *aaip,
1266  unsigned char **data, size_t *num_data, int flag)
1267 {
1268  size_t todo;
1269  unsigned char aa_head[5];
1270 
1271  todo= *num_data;
1272  if(todo >= (size_t) aaip->aa_head_missing)
1273  todo= aaip->aa_head_missing;
1274  aaip_push_to_recs(aaip, *data, todo, 0);
1275  aaip->aa_head_missing-= todo;
1276  if(aaip->aa_head_missing == 0) {
1277  aaip_read_from_recs(aaip, aaip->recs_fill - 5, aa_head, 5, 0);
1278  if(aa_head[0] != 'A' || (aa_head[1] != 'L' && aa_head[1] != 'A') ||
1279  aa_head[3] != 1)
1280  return(-1);
1281  aaip->aa_missing= aa_head[2];
1282  aaip->aa_ends= !(aa_head[4] & 1);
1283  aaip->recs_fill-= 5; /* AAIP field heads do not get delivered */
1284  if(aaip->aa_missing >= 5)
1285  aaip->aa_missing-= 5;
1286  else
1287  aaip->aa_missing= 0;
1288  }
1289  (*num_data)-= todo;
1290  (*data)+= todo;
1291  return(1);
1292 }
1293 
1294 
1295 static int aaip_consume_aa_data(struct aaip_state *aaip,
1296  unsigned char **data, size_t *num_data, int flag)
1297 {
1298  size_t i;
1299  static unsigned char zero_char[2]= {0, 0};
1300 
1301  while(*num_data > 0 && aaip->aa_missing > 0) {
1302  if(aaip->rec_head_missing > 0) {
1303  aaip_consume_rec_head(aaip, data, num_data, 0);
1304  if(*num_data == 0 || aaip->aa_missing <= 0)
1305  return(1);
1306  }
1307  aaip_consume_rec_data(aaip, data, num_data, 0);
1308  }
1309  if(aaip->aa_missing <= 0) {
1310  if(aaip->aa_ends) {
1311  /* Check for incomplete pair and eventually make emergency closure */
1312  if(aaip->rec_head_missing != 2) { /* incomplete record detected */
1313  if(aaip->rec_head_missing) {
1314  /* fake 0 length record */
1315  aaip_set_buffer_byte(aaip, aaip->recs_fill - 1, (unsigned char) 0, 0);
1316  aaip_push_to_recs(aaip, zero_char, 1, 0);
1317  } else {
1318  /* fill in missing btes */
1319  for(i= 0; (int) i < aaip->rec_missing; i++)
1320  aaip_push_to_recs(aaip, zero_char, 1, 1);
1321  }
1322  aaip->rec_head_missing= 2;
1323  aaip->rec_missing= 0;
1324  aaip->num_recs++;
1325  if(aaip->rec_ends) {
1326  aaip->num_components++;
1327  aaip->end_of_components= aaip->recs_fill;
1328  }
1329  }
1330  if(aaip->end_of_components != aaip->recs_fill &&
1331  aaip->end_of_components != 0) {
1332  /* incomplete component detected */
1333  /* add empty end record */
1334  aaip_push_to_recs(aaip, zero_char, 2, 0);
1335  aaip->num_recs++;
1336  aaip->num_components++;
1337  aaip->end_of_components= aaip->recs_fill;
1338  }
1339  if(!(aaip->first_is_name ^ (aaip->num_components % 2))) {
1340  /* value component is missing */
1341  /* add dummy component */
1342  aaip_push_to_recs(aaip, zero_char, 2, 0);
1343  aaip->num_recs++;
1344  aaip->num_components++;
1345  aaip->end_of_components= aaip->recs_fill;
1346  }
1347  aaip->aa_ends= 2;
1348  } else
1349  aaip->aa_head_missing= 5;
1350  }
1351  return(0);
1352 }
1353 
1354 
1355 /* Submit small data chunk for decoding.
1356  The return value will tell whether data are pending for being fetched.
1357  @param aaip The AAIP decoder context
1358  @param data Not more than 2048 bytes input for the decoder
1359  @parm num_data Number of bytes in data
1360  0 inquires the buffer status avoiding replies <= 0
1361  @param ready_bytes Number of decoded bytes ready for delivery
1362  @param flag Bitfield for control purposes
1363  @return -1= non-AAIP field detected
1364  *ready_bytes gives number of consumed bytes in data
1365  0= cannot accept data because buffer full
1366  1= no component record complete, submit more data
1367  2= component record complete, may be delivered
1368  3= component complete, may be delivered
1369  4= no component available, no more data expected, done
1370 */
1371 int aaip_submit_data(struct aaip_state *aaip,
1372  unsigned char *data, size_t num_data,
1373  size_t *ready_bytes, int flag)
1374 {
1375  int ret;
1376  unsigned char *in_data;
1377 
1378  if(aaip->aa_ends == 3)
1379  return(4);
1380  in_data= data;
1381  if(num_data == 0)
1382  goto ex;
1383  if(aaip->recs_fill + num_data > Aaip_buffer_sizE)
1384  return(0);
1385 
1386  while(num_data > 0) {
1387  if(aaip->aa_head_missing > 0) {
1388  ret= aaip_consume_aa_head(aaip, &data, &num_data, 0);
1389  if(ret < 0) {
1390  *ready_bytes= data - in_data;
1391  return(-1);
1392  }
1393  if(num_data == 0 || aaip->aa_missing <= 0)
1394  goto ex;
1395  }
1396  aaip_consume_aa_data(aaip, &data, &num_data, 0);
1397  if(aaip->aa_missing)
1398  break;
1399  }
1400 ex:;
1401  *ready_bytes= aaip->ready_bytes;
1402  if(aaip->num_components > 0)
1403  return(3);
1404  if(aaip->num_recs > 0)
1405  return(2);
1406  if(aaip->aa_ends && aaip->aa_head_missing == 0 && aaip->aa_missing == 0)
1407  aaip->aa_ends= 2;
1408  if(aaip->aa_ends == 2 && aaip->num_recs == 0)
1409  aaip->aa_ends= 3;
1410  if(aaip->aa_ends == 3)
1411  return(4);
1412  return(1);
1413 }
1414 
1415 
1416 /* Fetch the available part of current component.
1417  The return value will tell whether it belongs to name or to value and
1418  whether that name or value is completed now.
1419  @param aaip The AAIP decoder context
1420  @param result Has to point to storage for the component data
1421  @param result_size Gives the amount of provided result storage
1422  @param num_result Will tell the number of fetched result bytes
1423  @param flag Bitfield for control purposes
1424  bit0= discard data rather than copying to result
1425  @return -2 = insufficient result_size
1426  -1 = no data ready for delivery
1427  0 = result holds the final part of a name
1428  1 = result holds an intermediate part of a name
1429  2 = result holds the final part of a value
1430  3 = result holds an intermediate part of a value
1431 */
1432 int aaip_fetch_data(struct aaip_state *aaip,
1433  char *result, size_t result_size, size_t *num_result,
1434  int flag)
1435 {
1436  int ret= -1, complete= 0, payload;
1437  unsigned int i, num_bytes= 0, h;
1438 
1439  if(aaip->num_recs == 0)
1440  return(-1);
1441 
1442  /* Copy data until end of buffer or end of component */
1443  h= 0;
1444  for(i= 0; i < aaip->num_recs && !complete; i++) {
1445  payload= aaip_get_buffer_byte(aaip, h + 1, 0);
1446  if(!(flag & 1)) {
1447  if(num_bytes + payload > result_size)
1448  return(-2);
1449  aaip_read_from_recs(aaip, h + 2, (unsigned char *) (result + num_bytes),
1450  payload, 0);
1451  *num_result= num_bytes + payload;
1452  }
1453  num_bytes+= payload;
1454  if(!(aaip_get_buffer_byte(aaip, h, 0) & 1))
1455  complete= 1;
1456  h+= payload + 2;
1457  }
1458  aaip->ready_bytes-= num_bytes;
1459  aaip->num_recs-= i;
1460 
1461  /* Shift buffer */
1462  aaip_shift_recs(aaip, h, 0);
1463 
1464  /* Compute reply */
1465  ret= 2 * !aaip->first_is_name;
1466  if(complete) {
1467  aaip->first_is_name= !aaip->first_is_name;
1468  if(aaip->num_components > 0)
1469  aaip->num_components--;
1470  } else
1471  ret|= 1;
1472 
1473  return(ret);
1474 }
1475 
1476 
1477 /* Skip the current component and eventually the following value component.
1478  This has to be called if fetching of a component shall be aborted
1479  but the next component resp. pair shall be fetchable again.
1480  aaip_submit_data() will not indicate readiness for fetching until all
1481  bytes of the skipped components are submitted. Those bytes get discarded.
1482  @param aaip The AAIP decoder context
1483  @param flag Bitfield for control purposes
1484  bit0= do not skip value if current component is name
1485  @return <=0 error , 1= now in skip state, 2= not in skip state
1486 */
1487 int aaip_skip_component(struct aaip_state *aaip, int flag)
1488 {
1489  int to_skip= 1;
1490 
1491  if(aaip->first_is_name && !(flag & 1))
1492  to_skip= 2;
1493  if(aaip->recs_invalid) {
1494  aaip->recs_invalid+= to_skip;
1495  return(1);
1496  }
1497 
1498  if(aaip->num_components) {
1499  /* null-fetch */
1500  aaip_fetch_data(aaip, NULL, (size_t) 0, NULL, 1);
1501  to_skip--;
1502  }
1503  if(aaip->num_components && to_skip) {
1504  /* null-fetch */
1505  aaip_fetch_data(aaip, NULL, (size_t) 0, NULL, 1);
1506  to_skip--;
1507  }
1508  if(to_skip) {
1509  aaip->recs_fill= 0;
1510  aaip->num_recs= 0;
1511  aaip->ready_bytes= 0;
1512  }
1513  aaip->recs_invalid= to_skip;
1514  if(aaip->aa_ends == 2 && aaip->num_recs == 0)
1515  aaip->aa_ends= 3;
1516  return(1 + (aaip->num_recs > 0));
1517 }
1518 
1519 
1520 /* ------------------------- Pair Level Interface ------------------------ */
1521 
1522 /*
1523  @param flag Bitfield for control purposes
1524  bit0= do not skip oversized component but return -2
1525  @return see aaip_decode_pair
1526 */
1527 static int aaip_advance_pair(struct aaip_state *aaip,
1528  char *name, size_t name_size, size_t *name_fill,
1529  char *value, size_t value_size, size_t *value_fill,
1530  int flag)
1531 {
1532  int ret;
1533  char *wpt;
1534  size_t size, num;
1535 
1536 retry:;
1537  if(aaip->first_is_name) {
1538  wpt= name + *name_fill;
1539  size= name_size - *name_fill;
1540  } else {
1541  wpt= value + *value_fill;
1542  size= value_size - *value_fill;
1543  }
1544  ret= aaip_fetch_data(aaip, wpt, size, &num, 0);
1545  if(ret == -2) { /* insufficient result size */
1546  if(flag & 1)
1547  return(-2);
1548  ret= aaip_skip_component(aaip, 0);
1549  *name_fill= *value_fill= 0;
1550  aaip->pairs_skipped++;
1551  if(ret == 2) /* Skip performed, valid data pending */
1552  goto retry;
1553  } else if(ret == -1) { /* No data ready for delivery : may not happen */
1554  return(-1);
1555  } else if(ret == 0) { /* result holds the final part of a name */
1556  (*name_fill)+= num;
1557  /* peek for value data */
1558  ret= aaip_submit_data(aaip, NULL, (size_t) 0, &num, 0);
1559  if(ret == 2 || ret == 3) {
1560  /* fetch value data */;
1561  ret= aaip_advance_pair(aaip, name, name_size, name_fill,
1562  value, value_size, value_fill, flag);
1563  return ret;
1564  } else if(ret == 4)
1565  return(5);
1566  } else if(ret == 1) { /* result holds an intermediate part of a name */
1567  (*name_fill)+= num;
1568  } else if(ret == 2) { /* result holds the final part of a value */
1569  (*value_fill)+= num;
1570  if(aaip->num_components >= 2)
1571  return(3);
1572  if(aaip->aa_ends == 2 && aaip->num_recs == 0)
1573  aaip->aa_ends= 3;
1574  if(aaip->aa_ends == 3)
1575  return(4);
1576  return(2);
1577  } else if(ret == 3) {
1578  /* result holds an intermediate part of a value */;
1579  (*value_fill)+= num;
1580  } else {
1581  return(-1); /* unknown reply from aaip_fetch_data() */
1582  }
1583  return(1);
1584 }
1585 
1586 
1587 /* Accept raw input data and collect a pair of name and value.
1588  The return value will indicate whether the pair is complete, whether more
1589  pairs are complete or whether more data are desired. No input data will be
1590  accepted as long as complete pairs are pending. The end of the attribute
1591  list will be indicated.
1592  @param aaip The AAIP decoder context
1593  @param data The raw data to decode
1594  @param num_data Number of data bytes provided
1595  @param consumed Returns the number of consumed data bytes
1596  @param name Buffer to build the name string
1597  @param name_size Maximum number of bytes in name
1598  @param name_fill Holds the current buffer fill of name
1599  @param value Buffer to build the value string
1600  @param value_size Maximum number of bytes in value
1601  @param value_fill Holds the current buffer fill of value
1602  @param flag Bitfield for control purposes
1603  bit0= do not skip oversized pair but return -2
1604  @return <0 error
1605  -3 buffer full (program error)
1606  -2 insufficient result_size (only with flag bit0)
1607  -1 non-AAIP field detected
1608  0 data not accepted, first fetch pending pairs with num_data == 0
1609  1 name and value are not valid yet, submit more data
1610  2 name and value are valid, submit more data
1611  3 name and value are valid, pairs pending, fetch with num_data == 0
1612  4 name and value are valid, no more data expected
1613  5 name and value are not valid, no more data expected
1614 */
1615 int aaip_decode_pair(struct aaip_state *aaip,
1616  unsigned char *data, size_t num_data, size_t *consumed,
1617  char *name, size_t name_size, size_t *name_fill,
1618  char *value, size_t value_size, size_t *value_fill,
1619  int flag)
1620 {
1621  int ret;
1622  size_t ready_bytes= 0;
1623 
1624 #ifdef Aaip_with_short_namespaceS
1625  char prefix[Aaip_max_name_expansioN + 1];
1626  size_t nl, pl;
1627 #endif
1628 
1629  *consumed= 0;
1630  if((aaip->pair_status < 0 && aaip->pair_status != -2) ||
1631  aaip->pair_status == 4 ||
1632  aaip->pair_status == 5) { /* dead ends */
1633  ret= aaip->pair_status;
1634  goto ex;
1635  } else if(aaip->pair_status == 2 || aaip->pair_status == 3) {
1636  if(aaip->pair_status == 3 && num_data > 0)
1637  {ret= 0; goto ex;}
1638  /* Start a new pair */
1639  if(!aaip->first_is_name) /* Eventually skip orphaned value */
1640  aaip_fetch_data(aaip, NULL, (size_t) 0, NULL, 1);
1641  *name_fill= *value_fill= 0;
1642  }
1643 
1644  if(num_data > 0) {
1645  ret= aaip_submit_data(aaip, data, num_data, &ready_bytes, 0);
1646  } else {
1647  ret= 1;
1648  if(aaip->num_components)
1649  ret= 3;
1650  else if(aaip->num_recs)
1651  ret= 2;
1652  }
1653  if(ret < 0) { /* non-AAIP field detected */
1654  *consumed= ready_bytes;
1655  {ret= -1; goto ex;}
1656  } else if(ret == 0) { /* buffer overflow */;
1657  /* should not happen with correct usage */
1658  {ret= -3; goto ex;}
1659  } else if(ret == 1) { /* no component record complete */
1660  goto ex;
1661  } else if(ret == 2) { /* component record complete, may be delivered */
1662  ;
1663  } else if(ret == 3) { /* component complete, may be delivered */
1664  ;
1665  } else if(ret == 4) { /* no component available, no more data expected */
1666  {ret= 5; goto ex;}
1667  } else
1668  {ret= -1; goto ex;} /* unknown reply from aaip_submit_data() */
1669 
1670  *consumed= num_data;
1671  ret= aaip_advance_pair(aaip, name, name_size - Aaip_max_name_expansioN,
1672  name_fill, value, value_size, value_fill, flag & 1);
1673  if(aaip->aa_ends == 3) {
1674  if(ret >= 2 && ret <= 4)
1675  ret= 4;
1676  else
1677  ret= 5;
1678  }
1679 ex:;
1680 
1681 #ifdef Aaip_with_short_namespaceS
1682 
1683  if(ret >= 2 && ret <= 4 && *name_fill > 0) {
1684  /* Translate name from eventual short form */
1685  nl= *name_fill;
1686  if(name[0] > 0 && name[0] <= Aaip_maxdef_namespacE) {
1687  prefix[0]= 0;
1688  if(name[0] == Aaip_namespace_literaL) {
1689  if(nl > 1) {
1690  /* Remove first character of name */
1691  memmove(name, name + 1, nl - 1);
1692  (*name_fill)--;
1693  }
1694  } else if(name[0] == Aaip_namespace_systeM ||
1695  name[0] == Aaip_namespace_useR ||
1696  name[0] == Aaip_namespace_isofS ||
1697  name[0] == Aaip_namespace_trusteD ||
1698  name[0] == Aaip_namespace_securitY
1699  ) {
1700  strcpy(prefix, Aaip_namespace_textS[(int) name[0]]);
1701  pl= strlen(prefix);
1702  memmove(name + pl, name + 1, nl - 1);
1703  memcpy(name, prefix, pl);
1704  *name_fill= pl + nl - 1;
1705  }
1706  }
1707  }
1708 
1709 #endif /* Aaip_with_short_namespaceS */
1710 
1711  aaip->pair_status= ret;
1712  return(ret);
1713 }
1714 
1715 
1716 unsigned int aaip_get_pairs_skipped(struct aaip_state *aaip, int flag)
1717 {
1718  return(aaip->pairs_skipped);
1719 }
1720 
1721 
1722 /* ------------------------- List Level Interface ------------------------ */
1723 
1724 
1725 #define Aaip_initial_name_leN 256
1726 #define Aaip_initial_value_leN 256
1727 #define Aaip_initial_list_sizE 2
1728 #define Aaip_list_enlargeR 1.5
1729 
1730 
1731 /*
1732  @param flag Bitfield for control purposes
1733  bit0= do not update *buf_size
1734 */
1735 static int aaip_enlarge_buf(struct aaip_state *aaip, size_t memory_limit,
1736  size_t item_size, char **buf, size_t *buf_size, int flag)
1737 {
1738  size_t new_size;
1739  char *new_buf;
1740 
1741  new_size= *buf_size * Aaip_list_enlargeR;
1742  if(aaip->list_mem_used + (new_size - *buf_size) * item_size >= memory_limit)
1743  return(3);
1744  aaip->list_mem_used+= (new_size - *buf_size) * item_size;
1745  new_buf= realloc(*buf, new_size * item_size);
1746  if(new_buf == NULL)
1747  return(-1);
1748  *buf= new_buf;
1749  if(!(flag & 1))
1750  *buf_size= new_size;
1751  return(1);
1752 }
1753 
1754 
1755 /* Accept raw input data and collect arrays of name pointers, value lengths
1756  and value pointers. A handle object will emerge which finally has to be
1757  be freed by a call with bit 15.
1758  @param handle The decoding context.
1759  It will be created by this call with flag bit 0 or if
1760  *handle == NULL. This handle has to be the same as long
1761  as decoding goes on and finally has to be freed by a
1762  call with bit15.
1763  @param memory_limit Maximum number of bytes to allocate
1764  @param num_attr_limit Maximum number of name-value pairs to allocate
1765  @param data The raw data to decode
1766  @param num_data Number of data bytes provided
1767  @param consumed Returns the number of consumed data bytes
1768  @param flag Bitfield for control purposes
1769  bit0= this is the first call with the given handle
1770  (also in effect if *handle is NULL)
1771  bit15= end decoding :
1772  Free handle and its intermediate list memory.
1773  @return <=0 error
1774  -4 interpretation stalled, no valid result
1775  -3 program error, unexpected reply from lower layers
1776  -2 non-AAIP-field detected, arrays are complete,
1777  call aaip_get_decoded_attrs()
1778  -1 out of memory
1779  1 not complete yet, submit more data
1780  2 arrays are complete, call aaip_get_decoded_attrs()
1781  3 limit exceeded, not complete yet,
1782  enlarge memory_limit or call with bit15 and give up
1783  4 limit exceeded, call aaip_get_decoded_attrs() and try again
1784 */
1785 int aaip_decode_attrs(struct aaip_state **handle,
1786  size_t memory_limit, size_t num_attr_limit,
1787  unsigned char *data, size_t num_data, size_t *consumed,
1788  int flag)
1789 {
1790  int ret;
1791  struct aaip_state *aaip;
1792  size_t h_num, *h_lengths, i, new_mem, pair_consumed= 0;
1793  char **h_names, **h_values, *hpt;
1794 
1795  *consumed= 0;
1796  if(flag & (1 << 15)) {
1797  if(*handle == NULL)
1798  return(0);
1799  ret= aaip_get_decoded_attrs(handle, &h_num, &h_names, &h_lengths, &h_values,
1800  0);
1801  if(ret > 0)
1802  aaip_get_decoded_attrs(handle, &h_num, &h_names, &h_lengths, &h_values,
1803  1 << 15);
1804  if((*handle)->name_buf != NULL)
1805  free((*handle)->name_buf);
1806  if((*handle)->value_buf != NULL)
1807  free((*handle)->value_buf);
1808  free((char *) *handle);
1809  *handle= NULL;
1810  return(1);
1811  }
1812 
1813  aaip= *handle;
1814  if(aaip == NULL || (flag & 1)) {
1815  aaip= *handle= calloc(1, sizeof(struct aaip_state));
1816  if(*handle == NULL)
1817  return(-1);
1818  aaip_init_aaip_state(*handle, 0);
1819  }
1820  if(aaip->list_names == NULL || aaip->list_values == NULL ||
1821  aaip->list_value_lengths == NULL) {
1822  /* Initialize arrays */
1824  if(num_attr_limit > 0 && num_attr_limit < aaip->list_size)
1825  aaip->list_size= num_attr_limit;
1826  new_mem= aaip->list_size * (2*sizeof(char *) + sizeof(size_t)) +
1828  if(aaip->list_mem_used + new_mem >= memory_limit)
1829  return(3);
1830  aaip->list_mem_used+= new_mem;
1831  aaip->list_names= calloc(sizeof(char *), aaip->list_size);
1832  aaip->list_value_lengths= calloc(sizeof(size_t), aaip->list_size);
1833  aaip->list_values= calloc(sizeof(char *), aaip->list_size);
1834  if(aaip->list_names == NULL || aaip->list_value_lengths == NULL ||
1835  aaip->list_values == NULL)
1836  return(-1);
1837  for(i= 0; i < aaip->list_size; i++) {
1838  aaip->list_names[i]= NULL;
1839  aaip->list_value_lengths[i]= 0;
1840  aaip->list_values[i]= NULL;
1841  }
1842  }
1843  if(aaip->name_buf == NULL || aaip->value_buf == NULL) {
1845  if(aaip->list_mem_used >= memory_limit)
1846  return(3);
1847  aaip->list_mem_used+= new_mem;
1848  aaip->name_buf= calloc(1, Aaip_initial_name_leN);
1849  aaip->value_buf= calloc(1, Aaip_initial_value_leN);
1850  if(aaip->name_buf == NULL || aaip->value_buf == NULL)
1851  return(-1);
1854  }
1855 
1856  while(1) {
1857  if(aaip->list_pending_pair > 0) {
1858  /* the buffer holds a complete pair from a previous memory limit refusal */
1859  ret= aaip->list_pending_pair;
1860  aaip->list_pending_pair= 0;
1861  } else {
1862  ret= aaip_decode_pair(aaip, data, num_data, &pair_consumed,
1863  aaip->name_buf, aaip->name_buf_size, &aaip->name_buf_fill,
1864  aaip->value_buf, aaip->value_buf_size, &aaip->value_buf_fill,
1865  1);
1866  *consumed+= pair_consumed;
1867  }
1868  if(ret == -2) { /* insufficient result_size */
1869  if(aaip->first_is_name)
1870  ret= aaip_enlarge_buf(aaip, memory_limit, (size_t) 1, &(aaip->name_buf),
1871  &(aaip->name_buf_size), 0);
1872  else
1873  ret= aaip_enlarge_buf(aaip, memory_limit, (size_t) 1,
1874  &(aaip->value_buf), &(aaip->value_buf_size), 0);
1875  if(ret != 1)
1876  return(ret);
1877 
1878  } else if(ret == -1) { /* non-AAIP field detected */
1879  if(pair_consumed <= 0)
1880  return(-4); /* interpretation did not advance */
1881 
1882  } else if(ret < 0) { /* other error */
1883  return(-3);
1884 
1885  } else if(ret == 0) { /* first fetch pending pairs with num_data == 0 */
1886  /* should not happen, fetch more pairs */;
1887 
1888  } else if(ret == 1) {
1889  /* name and value are not valid yet, submit more data */
1890  return(1);
1891 
1892  } else if(ret == 2 || ret == 3 || ret == 4) {
1893  /* name and value are valid, submit more data */
1894  /* name and value are valid, pairs pending, fetch with num_data == 0 */
1895  /* name and value are valid, no more data expected */
1896  aaip->list_pending_pair= ret;
1897 
1898  if(aaip->list_num_attrs >= aaip->list_size) {
1899  hpt= (char *) aaip->list_names;
1900  ret= aaip_enlarge_buf(aaip, memory_limit, sizeof(char *),
1901  &hpt, &(aaip->list_size), 1);
1902  if(ret != 1)
1903  return(ret);
1904  aaip->list_names= (char **) hpt;
1905  hpt= (char *) aaip->list_values;
1906  ret= aaip_enlarge_buf(aaip, memory_limit, sizeof(char *),
1907  &hpt, &(aaip->list_size), 1);
1908  if(ret != 1)
1909  return(ret);
1910  aaip->list_values= (char **) hpt;
1911  hpt= (char *) aaip->list_value_lengths;
1912  ret= aaip_enlarge_buf(aaip, memory_limit, sizeof(size_t),
1913  &hpt, &(aaip->list_size), 0);
1914  if(ret != 1)
1915  return(ret);
1916  aaip->list_value_lengths= (size_t *) hpt;
1917  }
1918 
1919  /* Allocate name and value in list */;
1920  if(aaip->list_mem_used + aaip->name_buf_fill + aaip->value_buf_fill + 2
1921  > memory_limit) {
1922  return(3);
1923  }
1924  aaip->list_mem_used+= aaip->name_buf_fill + aaip->value_buf_fill + 2;
1925  i= aaip->list_num_attrs;
1926  aaip->list_names[i]= calloc(aaip->name_buf_fill + 1, 1);
1927  aaip->list_values[i]= calloc(aaip->value_buf_fill + 1, 1);
1928  memcpy(aaip->list_names[i], aaip->name_buf, aaip->name_buf_fill);
1929  aaip->list_names[i][aaip->name_buf_fill]= 0;
1930  memcpy(aaip->list_values[i], aaip->value_buf, aaip->value_buf_fill);
1931  aaip->list_values[i][aaip->value_buf_fill]= 0;
1932  aaip->list_value_lengths[i]= aaip->value_buf_fill;
1933  aaip->list_num_attrs++;
1934  aaip->name_buf_fill= aaip->value_buf_fill= 0;
1935 
1936  ret= aaip->list_pending_pair;
1937  aaip->list_pending_pair= 0;
1938 
1939  if(ret == 2)
1940  return(1);
1941  if(ret == 4)
1942  break;
1943 
1944  } else if(ret == 5)
1945  break;
1946  else
1947  return(-2);
1948 
1949  num_data= 0; /* consume pending pairs */
1950  }
1951  aaip->list_pending_pair= 5;
1952  return(2);
1953 }
1954 
1955 
1956 /* Obtain the resulting attributes when aaip_decode_attrs() indicates to
1957  be done or to have the maximum possible amount of result ready.
1958  The returned data objects finally have to be freed by a call with flag
1959  bit 15.
1960  @param handle The decoding context created by aaip_decode_attrs()
1961  @param num_attrs Will return the number of name-value pairs
1962  @param names Will return an array of pointers to 0-terminated names
1963  @param value_lengths Will return an array with the lengths of values
1964  @param values Will return an array of pointers to 8-bit values
1965  @param flag Bitfield for control purposes
1966  bit15= free memory of names, value_lengths, values
1967  @return <0 error
1968  0 no attribute list ready
1969  1 ok
1970 */
1971 int aaip_get_decoded_attrs(struct aaip_state **handle, size_t *num_attrs,
1972  char ***names, size_t **value_lengths, char ***values,
1973  int flag)
1974 {
1975  size_t i;
1976  struct aaip_state *aaip;
1977 
1978  aaip= *((struct aaip_state **) handle);
1979  if(flag & (1 << 15)) {
1980  if(*names != NULL) {
1981  for(i= 0; i < *num_attrs; i++) {
1982  if((*names)[i] != NULL)
1983  free((*names)[i]);
1984  (*names)[i]= NULL;
1985  }
1986  free(*names);
1987  *names= NULL;
1988  }
1989  if(*values != NULL) {
1990  for(i= 0; i < *num_attrs; i++) {
1991  if((*values)[i] != NULL)
1992  free((*values)[i]);
1993  (*values)[i]= NULL;
1994  }
1995  free(*values);
1996  *values= NULL;
1997  }
1998  if(*value_lengths != NULL)
1999  free(*value_lengths);
2000  *value_lengths= NULL;
2001  *num_attrs= 0;
2002  return(1);
2003  }
2004 
2005  /* Check whether decoding is finished yet */
2006  if(aaip->list_pending_pair != 5)
2007  return(0);
2008 
2009  *num_attrs= aaip->list_num_attrs;
2010  *names= aaip->list_names;
2011  *value_lengths= aaip->list_value_lengths;
2012  *values= aaip->list_values;
2013 
2014  /* Now the memory is owned by the caller */
2015  aaip->list_num_attrs= 0;
2016  aaip->list_names= NULL;
2017  aaip->list_value_lengths= NULL;
2018  aaip->list_values= NULL;
2019  aaip->list_size= 0;
2020  aaip->list_pending_pair= 0;
2021  return(1);
2022 }
2023 
2024 
2025 /* ------ Decoder for ACLs ------ */
2026 
2027 
2028 static int aaip_write_acl_line(char **result, size_t *result_size,
2029  char *tag_type, char *qualifier,
2030  char *permissions, int flag)
2031 {
2032  size_t needed, tag_len, perm_len, qualifier_len;
2033 
2034  tag_len= strlen(tag_type);
2035  qualifier_len= strlen(qualifier);
2036  perm_len= strlen(permissions);
2037  needed= tag_len + qualifier_len + perm_len + 3;
2038  if((flag & 1)) {
2039  (*result_size)+= needed;
2040  return(1);
2041  }
2042  if(needed + 1 > *result_size) /* +1 : want to append a trailing 0 */
2043  return(-1);
2044  memcpy((*result), tag_type, tag_len);
2045  (*result)[tag_len]= ':';
2046  memcpy((*result) + tag_len + 1, qualifier, qualifier_len);
2047  (*result)[tag_len + 1 + qualifier_len]= ':';
2048  memcpy((*result) + tag_len + 1 + qualifier_len + 1, permissions, perm_len);
2049  (*result)[tag_len + 1 + qualifier_len + 1 + perm_len]= '\n';
2050  (*result)[tag_len + 1 + qualifier_len + 1 + perm_len + 1] = 0;
2051  (*result)+= needed;
2052  (*result_size)-= needed;
2053  return(1);
2054 }
2055 
2056 
2057 static int aaip_read_qualifier(unsigned char *data, size_t num_data,
2058  char *name, size_t name_size, size_t *name_fill,
2059  int flag)
2060 {
2061  int is_done= 0;
2062  size_t rec_len= 0;
2063  unsigned char *rpt;
2064 
2065  *name_fill= 0;
2066  for(rpt= data; !is_done; rpt+= rec_len) {
2067  rec_len= (*rpt) & 127;
2068  is_done= !((*rpt) & 128);
2069  if(*name_fill + rec_len >= name_size ||
2070  (size_t) (rpt + 1 + rec_len - data) > num_data)
2071  return(-1);
2072  memcpy(name + *name_fill, rpt + 1, rec_len);
2073  rpt+= 1 + rec_len;
2074  (*name_fill)+= rec_len;
2075  name[*name_fill]= 0;
2076  }
2077  return(1);
2078 }
2079 
2080 
2081 /* Convert an AAIP ACL attribute value into the long text form of ACL.
2082  @param data The raw data to decode
2083  @param num_data Number of data bytes provided
2084  @param consumed Returns the number of consumed data bytes
2085  @param acl_text Will be filled with ACL long text form
2086  @param acl_text_size Maximum number of bytes to be written to acl_text
2087  @param acl_text_fill Will return the number of bytes in acl_text
2088  @param flag Bitfield for control purposes
2089  bit0= count only, do not really produce bytes:
2090  acl_text will not be touched,
2091  acl_text_size will be ignored,
2092  *acl_text_fill will return the counted number
2093  plus 1 for a trailing zero.
2094  bit1= expected is a default ACL (see return value 2)
2095  @return 1 success
2096  2 success, begin of default/access ACL encountered,
2097  submit data + *consumed for access/default ACL
2098  -1 error with reading of qualifier
2099  -2 error with writing of ACL text line
2100  -3 version mismatch
2101  -4 unknown tag type encountered
2102 */
2103 int aaip_decode_acl(unsigned char *data, size_t num_data, size_t *consumed,
2104  char *acl_text, size_t acl_text_size,
2105  size_t *acl_text_fill, int flag)
2106 {
2107  unsigned char *rpt;
2108  char perm_text[4], *wpt, *name= NULL;
2109  int type, qualifier= 0, perm, ret, cnt, name_size= 1024;
2110  size_t w_size= 0, name_fill= 0, i;
2111  uid_t uid;
2112  gid_t gid;
2113  struct passwd *pwd;
2114  struct group *grp;
2115 
2116  LIBISO_ALLOC_MEM(name, char, name_size);
2117  cnt= flag & 1;
2118  *consumed= 0;
2119  wpt= acl_text;
2120  w_size= acl_text_size;
2121  *acl_text_fill= 0;
2122  for(rpt= data; (size_t) (rpt - data) < num_data; ) {
2123  perm= *rpt;
2124  strcpy(perm_text, "---");
2125  if(perm & Aaip_READ)
2126  perm_text[0]= 'r';
2127  if(perm & Aaip_WRITE)
2128  perm_text[1]= 'w';
2129  if(perm & Aaip_EXEC)
2130  perm_text[2]= 'x';
2131 
2132  type= (*rpt) >> 4;
2133  if(type == Aaip_FUTURE_VERSION) /* indicate to caller: version mismatch */
2134  {ret = -3; goto ex;}
2135 
2136  qualifier= !!((*rpt) & 8);
2137  if(qualifier) {
2138  ret= aaip_read_qualifier(rpt + 1, num_data - (rpt + 1 - data),
2139  name, name_size, &name_fill, 0);
2140  if(ret <= 0)
2141  {ret = -1; goto ex;}
2142  }
2143 
2144  /* Advance read pointer */
2145  (*consumed)+= 1 + (qualifier ? name_fill + 1 : 0);
2146  rpt+= 1 + (qualifier ? name_fill + 1 : 0);
2147 
2148  ret= 1;
2149  if(type == Aaip_TRANSLATE) {
2150  /* rightfully ignored yet */;
2151  continue;
2152  } else if(type == Aaip_ACL_USER_OBJ) {
2153  /* user::rwx */
2154  ret= aaip_write_acl_line(&wpt, &w_size, "user", "", perm_text, cnt);
2155  } else if(type == Aaip_ACL_USER) {
2156  /* user:<username>:rwx */;
2157  ret= aaip_write_acl_line(&wpt, &w_size, "user", name, perm_text, cnt);
2158  } else if(type == Aaip_ACL_GROUP_OBJ) {
2159  /* user::rwx */
2160  ret= aaip_write_acl_line(&wpt, &w_size, "group", "", perm_text, cnt);
2161  } else if(type == Aaip_ACL_GROUP) {
2162  /* group:<groupname>:rwx */;
2163  ret= aaip_write_acl_line(&wpt, &w_size, "group", name, perm_text, cnt);
2164  } else if(type == Aaip_ACL_MASK) {
2165  /* mask::rwx */
2166  ret= aaip_write_acl_line(&wpt, &w_size, "mask", "", perm_text, cnt);
2167  } else if(type == Aaip_ACL_OTHER) {
2168  /* other::rwx */
2169  ret= aaip_write_acl_line(&wpt, &w_size, "other", "", perm_text, cnt);
2170  } else if(type == Aaip_SWITCH_MARK) {
2171  /* Indicate to caller: end of desired ACL type access/default */
2172  if((perm & Aaip_EXEC) ^ (!!(flag & 2)))
2173  {ret= 2; goto ex;}
2174  } else if(type == Aaip_ACL_USER_N) {
2175  /* determine username from uid */
2176  uid= 0;
2177  for(i= 0; i < name_fill; i++)
2178  uid= (uid << 8) | ((unsigned char *) name)[i];
2179  pwd= getpwuid(uid);
2180  if(pwd == NULL)
2181  sprintf(name, "%.f", (double) uid);
2182  else if(strlen(pwd->pw_name) >= (size_t) name_size)
2183  sprintf(name, "%.f", (double) uid);
2184  else
2185  strcpy(name, pwd->pw_name);
2186  /* user:<username>:rwx */;
2187  ret= aaip_write_acl_line(&wpt, &w_size, "user", name, perm_text, cnt);
2188  } else if(type == Aaip_ACL_GROUP_N) {
2189  /* determine username from gid */;
2190  gid= 0;
2191  for(i= 0; i < name_fill; i++)
2192  gid= (gid << 8) | ((unsigned char *) name)[i];
2193  grp= getgrgid(gid);
2194  if(grp == NULL)
2195  sprintf(name, "%.f", (double) gid);
2196  else if(strlen(grp->gr_name) >= (size_t) name_size)
2197  sprintf(name, "%.f", (double) gid);
2198  else
2199  strcpy(name, grp->gr_name);
2200  /* user:<username>:rwx */;
2201  ret= aaip_write_acl_line(&wpt, &w_size, "group", name, perm_text, cnt);
2202  } else {
2203  /* indicate to caller: unknown type */
2204  {ret = -4; goto ex;}
2205  }
2206  if(ret <= 0)
2207  {ret = -2; goto ex;}
2208  }
2209  ret= 1;
2210 ex:;
2211  *acl_text_fill= w_size;
2212  if(flag & 1)
2213  (*acl_text_fill)++;
2214  LIBISO_FREE_MEM(name);
2215  return(ret);
2216 }
2217 
2218 
2219 /* ----------------------- Adapter for operating systems ----------------- */
2220 
2221 
2222 #ifdef Libisofs_use_os_dummY
2223 
2224 #include "aaip-os-dummy.c"
2225 
2226 #else
2227 #ifdef __FreeBSD__
2228 
2229 #include "aaip-os-freebsd.c"
2230 
2231 #else
2232 #ifdef __FreeBSD_kernel__
2233 
2234 #ifdef NIX
2235 #ifdef Libisofs_with_aaip_xattR
2236 /* ts B51213: xattr system library calls are only stubs */
2237 #include "aaip-os-linux.c"
2238 #else
2239 /* ts B51213: extattr system library calls are not even present */
2240 #include "aaip-os-freebsd.c"
2241 #endif /* ! Libisofs_with_aaip_xattR */
2242 #else /* NIX */
2243 /* ts B51213: so we still end up at the dummy */
2244 #include "aaip-os-dummy.c"
2245 #endif /* ! NIX */
2246 
2247 #else
2248 #ifdef __NetBSD__
2249 
2250 #include "aaip-os-freebsd.c"
2251 
2252 #else
2253 #ifdef __OpenBSD__
2254 
2255 #include "aaip-os-freebsd.c"
2256 
2257 #else
2258 #ifdef __linux
2259 
2260 #include "aaip-os-linux.c"
2261 
2262 /* August 2011: aaip-os-linux.c would also work for GNU/Hurd : ifdef __GNU__
2263  Libraries and headers are present on Debian GNU/Hurd but there is no
2264  ACL or xattr support in the filesystems yet.
2265  Further, llistxattr() produces ENOSYS "Function not implemented".
2266  So it makes few sense to enable it here.
2267 */
2268 
2269 #else
2270 
2271 #include "aaip-os-dummy.c"
2272 
2273 #endif /* ! __linux */
2274 #endif /* ! __OpenBSD__ */
2275 #endif /* ! __NetBSD__ */
2276 #endif /* ! __FreeBSD_kernel__ */
2277 #endif /* ! __FreeBSD__ */
2278 #endif /* ! Libisofs_use_os_dummY */
2279 
static int aaip_make_aaip_perms(int r, int w, int x)
Definition: aaip_0_2.c:343
#define Aaip_ACL_USER_OBJ
Definition: aaip_0_2.c:48
#define Aaip_TRANSLATE
Definition: aaip_0_2.c:47
static int aaip_read_qualifier(unsigned char *data, size_t num_data, char *name, size_t name_size, size_t *name_fill, int flag)
Definition: aaip_0_2.c:2057
static int aaip_read_from_recs(struct aaip_state *aaip, size_t idx, unsigned char *data, size_t num_data, int flag)
Definition: aaip_0_2.c:1087
#define Aaip_buffer_reservE
Definition: aaip_0_2.c:913
ssize_t aaip_encode(size_t num_attrs, char **names, size_t *value_lengths, char **values, size_t *result_len, unsigned char **result, int flag)
Definition: aaip_0_2.c:100
#define Aaip_SWITCH_MARK
Definition: aaip_0_2.c:54
#define Aaip_ACL_GROUP_OBJ
Definition: aaip_0_2.c:50
static int aaip_advance_pair(struct aaip_state *aaip, char *name, size_t name_size, size_t *name_fill, char *value, size_t value_size, size_t *value_fill, int flag)
Definition: aaip_0_2.c:1527
static int aaip_enlarge_buf(struct aaip_state *aaip, size_t memory_limit, size_t item_size, char **buf, size_t *buf_size, int flag)
Definition: aaip_0_2.c:1735
#define Aaip_initial_list_sizE
Definition: aaip_0_2.c:1727
#define Aaip_READ
Definition: aaip_0_2.c:45
static int aaip_shift_recs(struct aaip_state *aaip, size_t todo, int flag)
Definition: aaip_0_2.c:1127
int aaip_init_aaip_state(struct aaip_state *aaip, int flag)
Definition: aaip_0_2.c:983
#define Aaip_namespace_trusteD
Definition: aaip_0_2.c:68
#define Aaip_list_enlargeR
Definition: aaip_0_2.c:1728
static int aaip_consume_rec_data(struct aaip_state *aaip, unsigned char **data, size_t *num_data, int flag)
Definition: aaip_0_2.c:1232
unsigned int aaip_get_pairs_skipped(struct aaip_state *aaip, int flag)
Definition: aaip_0_2.c:1716
#define Aaip_max_named_spacE
Definition: aaip_0_2.c:60
int aaip_add_acl_st_mode(char *acl_text, mode_t st_mode, int flag)
Definition: aaip_0_2.c:865
#define Aaip_ACL_OTHER
Definition: aaip_0_2.c:53
#define Aaip_namespace_systeM
Definition: aaip_0_2.c:65
int aaip_submit_data(struct aaip_state *aaip, unsigned char *data, size_t num_data, size_t *ready_bytes, int flag)
Definition: aaip_0_2.c:1371
#define Aaip_ACL_USER_N
Definition: aaip_0_2.c:55
static void aaip_encode_byte(unsigned char *result, size_t *result_fill, unsigned char value)
Definition: aaip_0_2.c:185
size_t aaip_count_bytes(unsigned char *data, int flag)
Definition: aaip_0_2.c:966
static int aaip_encode_comp(unsigned char *result, size_t *result_fill, int prefix, char *data, size_t l, int flag)
Definition: aaip_0_2.c:193
static int aaip_get_buffer_byte(struct aaip_state *aaip, size_t idx, int flag)
Definition: aaip_0_2.c:1116
static int aaip_push_to_recs(struct aaip_state *aaip, unsigned char *data, size_t todo, int flag)
Definition: aaip_0_2.c:1068
int aaip_get_decoded_attrs(struct aaip_state **handle, size_t *num_attrs, char ***names, size_t **value_lengths, char ***values, int flag)
Definition: aaip_0_2.c:1971
int aaip_encode_acl(char *acl_text, mode_t st_mode, size_t *result_len, unsigned char **result, int flag)
Definition: aaip_0_2.c:292
int aaip_decode_pair(struct aaip_state *aaip, unsigned char *data, size_t num_data, size_t *consumed, char *name, size_t name_size, size_t *name_fill, char *value, size_t value_size, size_t *value_fill, int flag)
Definition: aaip_0_2.c:1615
int aaip_cleanout_st_mode(char *acl_text, mode_t *in_st_mode, int flag)
Definition: aaip_0_2.c:720
#define Aaip_ACL_GROUP_N
Definition: aaip_0_2.c:56
static int aaip_ring_adr(struct aaip_state *aaip, size_t idx, size_t todo, unsigned char **start_pt, size_t *at_start_pt, size_t *at_recs, int flag)
Definition: aaip_0_2.c:1040
size_t aaip_sizeof_aaip_state(void)
Definition: aaip_0_2.c:977
static double aaip_numeric_id(char *name, int flag)
Definition: aaip_0_2.c:328
#define Aaip_namespace_securitY
Definition: aaip_0_2.c:69
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)
Definition: aaip_0_2.c:2103
int aaip_decode_attrs(struct aaip_state **handle, size_t memory_limit, size_t num_attr_limit, unsigned char *data, size_t num_data, size_t *consumed, int flag)
Definition: aaip_0_2.c:1785
#define Aaip_min_named_spacE
Definition: aaip_0_2.c:61
static char Aaip_namespace_textS[][9+1]
Definition: aaip_0_2.c:74
#define Aaip_buffer_sizE
Definition: aaip_0_2.c:908
static int aaip_consume_rec_head(struct aaip_state *aaip, unsigned char **data, size_t *num_data, int flag)
Definition: aaip_0_2.c:1208
#define Aaip_max_name_expansioN
Definition: aaip_0_2.c:72
static int aaip_consume_aa_head(struct aaip_state *aaip, unsigned char **data, size_t *num_data, int flag)
Definition: aaip_0_2.c:1265
static int aaip_set_buffer_byte(struct aaip_state *aaip, size_t idx, unsigned char data, int flag)
Definition: aaip_0_2.c:1103
#define Aaip_EXEC
Definition: aaip_0_2.c:43
#define Aaip_namespace_isofS
Definition: aaip_0_2.c:67
#define Aaip_initial_value_leN
Definition: aaip_0_2.c:1726
#define Aaip_ACL_MASK
Definition: aaip_0_2.c:52
#define Aaip_WRITE
Definition: aaip_0_2.c:44
int aaip_skip_component(struct aaip_state *aaip, int flag)
Definition: aaip_0_2.c:1487
#define Aaip_ACL_USER
Definition: aaip_0_2.c:49
#define Aaip_initial_name_leN
Definition: aaip_0_2.c:1725
#define Aaip_FUTURE_VERSION
Definition: aaip_0_2.c:57
#define Aaip_namespace_literaL
Definition: aaip_0_2.c:64
static int aaip_encode_pair(char *name, size_t attr_length, char *attr, unsigned int *num_recs, size_t *comp_size, unsigned char *result, size_t result_fill, int flag)
Definition: aaip_0_2.c:226
#define Aaip_maxdef_namespacE
Definition: aaip_0_2.c:62
int aaip_encode_both_acl(char *a_acl_text, char *d_acl_text, mode_t st_mode, size_t *result_len, unsigned char **result, int flag)
Definition: aaip_0_2.c:618
int aaip_fetch_data(struct aaip_state *aaip, char *result, size_t result_size, size_t *num_result, int flag)
Definition: aaip_0_2.c:1432
#define Aaip_namespace_useR
Definition: aaip_0_2.c:66
static ssize_t aaip_encode_acl_text(char *acl_text, mode_t st_mode, size_t result_size, unsigned char *result, int flag)
Definition: aaip_0_2.c:374
static int aaip_write_acl_line(char **result, size_t *result_size, char *tag_type, char *qualifier, char *permissions, int flag)
Definition: aaip_0_2.c:2028
static int aaip_consume_aa_data(struct aaip_state *aaip, unsigned char **data, size_t *num_data, int flag)
Definition: aaip_0_2.c:1295
#define Aaip_ACL_GROUP
Definition: aaip_0_2.c:51
#define LIBISO_FREE_MEM(pt)
Definition: util.h:627
#define LIBISO_ALLOC_MEM(pt, typ, count)
Definition: util.h:615
#define ISO_OUT_OF_MEM
Definition: libisofs.h:8745
#define ISO_AAIP_BAD_ACL_TEXT
Definition: libisofs.h:8932
#define ISO_AAIP_ACL_MULT_OBJ
Definition: libisofs.h:9112
#define ISO_ASSERT_FAILURE
Definition: libisofs.h:8737
int iso_msg_submit(int imgid, int errcode, int causedby, const char *fmt,...)
Definition: messages.c:579
int rec_missing
Definition: aaip_0_2.c:930
unsigned int num_components
Definition: aaip_0_2.c:938
int first_is_name
Definition: aaip_0_2.c:940
int rec_head_missing
Definition: aaip_0_2.c:929
size_t list_size
Definition: aaip_0_2.c:948
size_t * list_value_lengths
Definition: aaip_0_2.c:951
int list_pending_pair
Definition: aaip_0_2.c:959
char ** list_names
Definition: aaip_0_2.c:950
size_t value_buf_size
Definition: aaip_0_2.c:957
size_t ready_bytes
Definition: aaip_0_2.c:935
size_t list_mem_used
Definition: aaip_0_2.c:947
unsigned char * recs_start
Definition: aaip_0_2.c:928
int recs_invalid
Definition: aaip_0_2.c:925
char * name_buf
Definition: aaip_0_2.c:953
int aa_ends
Definition: aaip_0_2.c:921
char * value_buf
Definition: aaip_0_2.c:956
size_t end_of_components
Definition: aaip_0_2.c:939
size_t name_buf_fill
Definition: aaip_0_2.c:955
size_t list_num_attrs
Definition: aaip_0_2.c:949
size_t value_buf_fill
Definition: aaip_0_2.c:958
unsigned int num_recs
Definition: aaip_0_2.c:934
int aa_missing
Definition: aaip_0_2.c:920
int rec_ends
Definition: aaip_0_2.c:931
size_t name_buf_size
Definition: aaip_0_2.c:954
unsigned char recs[4096+(257+3 *2)]
Definition: aaip_0_2.c:926
int pair_status
Definition: aaip_0_2.c:943
char ** list_values
Definition: aaip_0_2.c:952
unsigned int pairs_skipped
Definition: aaip_0_2.c:944
size_t recs_fill
Definition: aaip_0_2.c:927
int aa_head_missing
Definition: aaip_0_2.c:919