modules/up/UP_extrnl_syntax.cc

/* [<][>]
[^][v][top][bottom][index][help] */

FUNCTIONS

This source file includes following functions.
  1. up_get_dates
  2. up_changed_has_date
  3. UP_get_current_date
  4. up_add_dates
  5. up_check_date_order
  6. up_check_date
  7. up_check_dates_syntax
  8. up_check_changed_attr
  9. up_check_an_auth_attr
  10. up_check_auth_attr
  11. up_check_an_inetnum_attr
  12. up_get_mntby_list
  13. up_check_a_status_attr
  14. up_check_inetnum_attr
  15. up_add_keycert_attrs
  16. up_get_attribute_list
  17. up_reconstruct_object
  18. UP_check_external_syntax
  19. UP_generate_kc_attrs

   1 /***************************************
   2   $Revision: 1.11 $
   3 
   4   UP external syntax checks
   5 
   6   Status: NOT REVIEWED, NOT TESTED
   7 
   8   Author(s):       Engin Gunduz
   9 
  10   ******************/ /******************
  11   Modification History:
  12         engin (15/12/2000) Created.
  13   ******************/ /******************
  14   Copyright (c) 2001                              RIPE NCC
  15  
  16   All Rights Reserved
  17   
  18   Permission to use, copy, modify, and distribute this software and its
  19   documentation for any purpose and without fee is hereby granted,
  20   provided that the above copyright notice appear in all copies and that
  21   both that copyright notice and this permission notice appear in
  22   supporting documentation, and that the name of the author not be
  23   used in advertising or publicity pertaining to distribution of the
  24   software without specific, written prior permission.
  25   
  26   THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
  27   ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS; IN NO EVENT SHALL
  28   AUTHOR BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY
  29   DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
  30   AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  31   OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  32  ***************************************/
  33 
  34 
  35 #include "rpsl/object.hh"
  36 #include "UP_extrnl_syntax.h"
  37 #include "dbupdate.h"
  38 
  39 #define UP_DATE_OK      0
  40 #define UP_DATE_SYNERR  1
  41 #define UP_DATE_FUTURE  2
  42 #define UP_DATE_TOOSMALL        3
  43 #define UP_DATE_INVMONTH        4
  44 #define UP_DATE_INVDAY  5
  45 #define UP_DATE_WRONGFORMAT 6
  46 #define UP_DATE_NOK    7
  47 
  48 
  49 
  50 char * up_date_errmsgs[]={
  51 
  52   "OK",
  53   "Syntax error in date of 'changed' attribute",
  54   "Date in the future in 'changed' attribute",
  55   "Date is older than the database itself in 'changed' attribute",
  56   "Invalid month in date in 'changed' attribute",
  57   "Invalid day in date in 'changed' attribute",
  58   "Date must be in YYYYMMDD format in 'change' attribute",
  59   "Syntax error in date of 'changed' attribute"
  60 };
  61 
  62 
  63 extern int tracing;
  64 
  65 extern char * fingerprint;
  66 extern char * keyowner;
  67 
  68 extern char * allocmnt;
  69 
  70 
  71 /* obtains a list of dates in the given 
  72    list of attributes (GSList of attribute_struct) */
  73 GSList * up_get_dates(GSList * attribute_list){
     /* [<][>][^][v][top][bottom][index][help] */
  74 
  75   GSList * next;
  76   char * temp, * str; 
  77   int i;
  78   GSList * list = NULL;
  79 
  80   for( next = attribute_list; next != NULL ; next = g_slist_next(next) ){
  81     /* is this a 'changed' attribute? */
  82     if(strcmp((char *)(((attribute_struct *)(next->data))->type), "changed") == 0){
  83       temp = strdup(((attribute_struct *)(next->data))->content);
  84 
  85       /* delete the part after '#', inclusive */
  86       if(index(temp,'#') != NULL){
  87         temp[index(temp, '#') - temp] = '\0';
  88       }
  89       /* replace \n, \r & \t's with " " */
  90       for(i = 0; i < strlen(temp) ;i++){
  91         if(temp[i] == '\n' || temp[i] == '\r' || temp[i] == '\t' ){
  92           temp[i] = ' ';
  93         }
  94       }
  95       g_strstrip(temp);
  96       /* delete multiple spaces */
  97       str = (char *)malloc(strlen(temp) + 1);
  98       up_string_pack(str, temp);
  99       free(temp); 
 100 
 101       /* now, we have the 'changed' attribute's content in "normalized" form 
 102          We are sure it contains a date. So, it must be the second (and last)
 103          word in the attrib. */
 104       assert(index(str,' ') != NULL);
 105       temp = (char *)malloc(strlen(str) - (index(str,' ') - str ));
 106       temp = strncpy(temp, index(str,' ') + 1, strlen(str) - (index(str,' ') - str ) - 1);
 107       temp[strlen(str) - (index(str,' ') - str ) - 1] = '\0'; /* NULL terminate it */
 108       list = g_slist_append (list, temp);   
 109     }
 110   }
 111   
 112   return list;
 113 }
 114 
 115 
 116 
 117 
 118 /* Does the 'changed' attribute we got have a date already?
 119    Returns 1 if it does, 0 if not. */
 120 int up_changed_has_date(char * arg){
     /* [<][>][^][v][top][bottom][index][help] */
 121   
 122   int i;
 123   char * str;
 124   char * temp;
 125   
 126   str = strdup(arg);
 127 
 128   /* cut off the EOL comments */
 129   if(index(str, '#')){
 130     str[index(str, '#') - str - 1 ] = '\0';
 131   }
 132   
 133   /* replace \n, \r & \t's with " " */
 134   for(i = 0; i < strlen(str) ;i++){
 135     if(str[i] == '\n' || str[i] == '\r' || str[i] == '\t' ){
 136       str[i] = ' ';
 137     }
 138   }
 139   g_strstrip(str);
 140   /* delete multiple spaces */
 141   temp = (char *)malloc(strlen(str) + 1);
 142   up_string_pack(temp, str);
 143   
 144   free(str);
 145   str = temp;
 146   
 147   /* now, if there is still a white space, then we have a date in the string
 148      (it has to be something like "ripe-dbm@ripe.net 20001210") */
 149   if(index(str, ' ') != NULL){
 150     return 1; 
 151   }else{
 152     return 0;
 153   }
 154 }
 155 
 156 
 157 
 158 
 159 /* supplies the current date in YYYYMMDD format (for example 20011010) */
 160 char * UP_get_current_date(){
     /* [<][>][^][v][top][bottom][index][help] */
 161   /* We will use Glib's functions here */
 162 
 163   char * date;
 164   struct tm * time_struct;
 165   
 166   time_t * time_loc;
 167 
 168   time_loc = (time_t *)malloc(sizeof(time_t));
 169   time(time_loc);
 170   
 171   time_struct = localtime(time_loc);
 172 
 173 
 174   date = (char *)malloc(9);
 175   sprintf(date, "%04i%02i%02i", 
 176           time_struct->tm_year + 1900, 
 177           time_struct->tm_mon + 1,
 178           time_struct->tm_mday);
 179   return date;
 180 }
 181 
 182 
 183 
 184 
 185 
 186 
 187 
 188 
 189 /* int up_add_dates: adds dates to 'changed' attributes which 
 190      are missing one.
 191      Returns 1 if no problems encountered
 192      Returns 0 if a problem encountered, and the error string is set */
 193 int up_add_dates(GSList * attribute_list, char ** warning_str, char ** error_str){
     /* [<][>][^][v][top][bottom][index][help] */
 194   
 195   GSList * next;
 196   char * attribute, * current_date;
 197   int count_no_date = 0; 
 198   char * temp;
 199   
 200   *warning_str = NULL;
 201   *error_str   = NULL;
 202 
 203   /* get the current date in YYYYMMDD format (for example 20011010) */
 204   current_date = UP_get_current_date();
 205   
 206   for( next = attribute_list; next != NULL ; next = g_slist_next(next) ){
 207     /* is this a 'changed' attribute? */
 208     if(strcmp((char *)(((attribute_struct *)(next->data))->type), "changed") == 0){
 209       /* if this attribute does not have a date in it, add it. Also add 
 210           a warning message about this */
 211       if( !up_changed_has_date((char *)(((attribute_struct *)(next->data))->content))){
 212         count_no_date++;
 213         attribute = (char *)(((attribute_struct *)(next->data))->content);
 214         temp = (char *)malloc(strlen(attribute) + strlen(current_date) + 2 );
 215         if(index(attribute, '#')){/* cut off the EOL comments */
 216           attribute[index(attribute, '#') - attribute - 1] = '\0';
 217         }
 218         sprintf(temp, "%s %s", attribute, current_date);
 219         ((attribute_struct *)(next->data))->content = temp;
 220         free(attribute);
 221         /* add a warning message */
 222         if( *warning_str == NULL){
 223           *warning_str = (char *)malloc(strlen("WARNING  date '' added to 'changed' attribute") + 9 );
 224           sprintf(*warning_str, "WARNING  date '%s' added to 'changed' attribute", current_date);
 225         }else{
 226           temp = (char *)malloc(strlen(*warning_str) + 1 
 227                                        + strlen("WARNING  date '' added to 'changed' attribute") + 9 );
 228           sprintf(temp, "%s\nWARNING  date '%s' added to 'changed' attribute", 
 229                               *warning_str, current_date);
 230           free(*warning_str);
 231           *warning_str = temp; 
 232         }
 233       }
 234     }
 235   }
 236   
 237   if(count_no_date > 1){ 
 238     *error_str = strdup("***Error: More than one 'changed' attributes without dates");
 239     return 0;
 240   }else{
 241     return 1;
 242   }
 243   
 244 
 245 }
 246 
 247 
 248 
 249 
 250 
 251 
 252 /* Checks the order of dates in the given list. 
 253    If they are in order, returns 1, 
 254    if not, returns 0 */
 255 int up_check_date_order(GSList * list){
     /* [<][>][^][v][top][bottom][index][help] */
 256    
 257   GSList * next;
 258   char * previous;
 259 
 260   /* if list is empty, return 1 immediately */
 261   if(list == NULL){
 262     return 1;
 263   }
 264 
 265   /* initialize the 'previous' date */
 266   previous = strdup("00000000");
 267    
 268   for( next = list; next != NULL ; next = g_slist_next(next)){
 269     assert((next->data) != NULL);
 270     /* if the new date is smaller than the previous */
 271     if(strcmp((char *)(next->data), previous) < 0 ){
 272       free(previous);
 273       return 0;
 274     }
 275     free(previous);
 276     previous = strdup((char *)(next->data));
 277   }
 278    
 279   free(previous);
 280   /* Reached the end, without finding out-of-order date. Return 1, then */
 281   return 1; 
 282    
 283 }
 284 
 285 
 286 
 287 
 288 
 289 /* up_check_date: checks the syntax of the date, given as the only
 290    argument (char *). The argument is checked if it is in YYYYMMDD
 291    format, and returns an error code accordingly */
 292 int up_check_date(const char * arg){
     /* [<][>][^][v][top][bottom][index][help] */
 293 
 294   int date_int; /* integer representation of the date (arg) */
 295   char * current_date;
 296   int year, month, day; /* integers for the components of the date */
 297 
 298 
 299   errno = 0;
 300   date_int = atoi(arg);
 301 
 302       
 303   if(errno != 0){/* there was an error in the conversion, syntax error */
 304     return UP_DATE_SYNERR;
 305   }
 306     
 307   /* wrong format */
 308   if(date_int <= 10000000 ){ /* the date is not in YYYYMMDD format */
 309     return UP_DATE_WRONGFORMAT;
 310   }
 311 
 312 
 313   /* check if it is too small */  
 314   if(date_int <= 19880000 ){ /* the date is older than the DB itself! */
 315     return UP_DATE_TOOSMALL;
 316   }
 317 
 318   /* check if it is too big */
 319   if(date_int >= 100000000 ){/* too big: syntax error */
 320     return UP_DATE_SYNERR;
 321   }
 322 
 323   /* and now check year, month and day components */
 324   year = date_int / 10000;
 325   month = (date_int - (year * 10000) ) / 100;
 326   day = (date_int % 100);
 327   
 328   /* check year */
 329   if(year < 1988 ){
 330     return UP_DATE_TOOSMALL;
 331   }
 332 
 333   /* check month */
 334   if(month < 1 || month > 12){
 335     return UP_DATE_INVMONTH;
 336   }
 337 
 338   /* check day */
 339   if(day < 1 || day > 31){
 340     return UP_DATE_INVDAY;
 341   }
 342 
 343   switch( month ){
 344     case 1: case 3: case 5: case 7:
 345     case 8: case 10: case 12:
 346          if (day > 31){
 347            return UP_DATE_INVDAY;
 348          };
 349          break;
 350     case 2: 
 351          if ( (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0)) && (day > 29 )){ /* leap year */
 352            return UP_DATE_INVDAY;
 353          }else if( (!(year % 4 == 0 && (year % 100 != 0 || year % 400 == 0))) && (day > 28) ){/* non-leap year */
 354            return UP_DATE_INVDAY;
 355          };
 356          break;
 357     case 4: case 6: case 9: case 11:
 358          if (day > 30){
 359            return UP_DATE_INVDAY;
 360          };
 361          break;
 362     default: return UP_DATE_INVMONTH;
 363 
 364   }
 365 
 366   /* check if the arg is in the future or not */
 367   current_date = UP_get_current_date();
 368   if(strcmp(current_date, arg) < 0 ){/* arg is in the future */
 369     free(current_date);
 370     return UP_DATE_FUTURE;
 371   }
 372   free(current_date);
 373   
 374     
 375   return UP_DATE_OK;
 376   
 377 }
 378 
 379 
 380 
 381 
 382 
 383 
 384 
 385 
 386 
 387 
 388 /* Checks the syntax of the dates in the list */
 389 date_syntax_struct * up_check_dates_syntax(GSList * list){
     /* [<][>][^][v][top][bottom][index][help] */
 390    
 391   GSList * next;
 392   char * previous;
 393   date_syntax_struct * result;
 394   int res;
 395 
 396   /* initialize the result struct */
 397   result = (date_syntax_struct *)malloc(sizeof(date_syntax_struct));
 398   result->result = UP_DATE_OK;
 399   result->error_str = NULL;
 400 
 401   /* if list is empty, return immediately */
 402   if(list == NULL){
 403     return result;
 404   }
 405 
 406   /* loop through the members of the list, check each of them */
 407   for( next = list; next != NULL ; next = g_slist_next(next)){
 408     assert((next->data) != NULL);
 409     
 410     /* check the date */
 411     res = up_check_date((char *)next->data);
 412     switch (res){
 413       case UP_DATE_OK: break;
 414       
 415       case UP_DATE_FUTURE:
 416       case UP_DATE_TOOSMALL:
 417       case UP_DATE_INVDAY:
 418       case UP_DATE_INVMONTH:
 419       case UP_DATE_WRONGFORMAT:
 420 
 421              if(result->error_str == NULL){
 422                result->error_str = (char *)malloc(strlen("***Error: ") + strlen(up_date_errmsgs[res]) 
 423                                                   + strlen(": ") + strlen((char *)next->data) + 1);
 424                sprintf(result->error_str, "***Error: %s: %s", up_date_errmsgs[res],
 425                        (char *)next->data);
 426              }else{
 427                result->error_str = (char *)realloc(result->error_str, strlen(result->error_str) + 1 
 428                                                    + strlen("***Error: ") + strlen(up_date_errmsgs[res]) 
 429                                                    + strlen(": ") + strlen((char *)next->data) + 1);
 430                sprintf(result->error_str, "%s\n***Error: %s: %s",
 431                        result->error_str, up_date_errmsgs[res], (char *)next->data);
 432              }
 433              result->result = UP_DATE_NOK; /* Not OK */
 434 
 435              break;
 436              
 437              
 438       case UP_DATE_SYNERR: /* syntax error in the date */
 439 
 440       default:
 441              if(result->error_str == NULL){
 442                result->error_str = (char *)malloc(strlen("***Error: ") + strlen(up_date_errmsgs[UP_DATE_SYNERR]) 
 443                                                   + strlen(": ") + strlen((char *)next->data) + 1);
 444                sprintf(result->error_str, "***Error: %s: %s", up_date_errmsgs[UP_DATE_SYNERR],
 445                        (char *)next->data);
 446              }else{
 447                result->error_str = (char *)realloc(result->error_str, strlen(result->error_str) + 1 
 448                                                    + strlen("***Error: ") + strlen(up_date_errmsgs[UP_DATE_SYNERR]) 
 449                                                    + strlen(": ") + strlen((char *)next->data) + 1);
 450                sprintf(result->error_str, "%s\n***Error: %s: %s",
 451                        result->error_str, up_date_errmsgs[UP_DATE_SYNERR], (char *)next->data);
 452              }
 453              result->result = UP_DATE_NOK; /* Not OK */
 454              break;
 455     }
 456 
 457   }
 458   
 459   
 460   return result;
 461    
 462 }
 463 
 464 
 465 
 466 
 467 
 468 
 469 
 470 
 471 
 472 
 473 /* void up_check_changed_attr 
 474    checks the order of dates in the 'changed' attributes */
 475 void up_check_changed_attr(Object * obj, char * obj_text, GSList * attribute_list, 
     /* [<][>][^][v][top][bottom][index][help] */
 476                            external_syntax_struct * result){
 477 
 478   GSList * date_list;
 479   int res;
 480   char ** warning, **error;
 481   char * temp;
 482   date_syntax_struct * date_check_res;
 483 
 484 
 485   warning = (char **)malloc(sizeof(char **));
 486   error   = (char **)malloc(sizeof(char **));
 487    
 488 
 489   /* Now, add dates to the "changed" attributes */
 490   res = up_add_dates(/*changed_list*/attribute_list, warning, error);
 491   if(!res){
 492     /* so, add the error string to result's error string */
 493     if(result->error_str == NULL){
 494       result->error_str = strdup(*error);
 495     }else{
 496       temp = (char *)malloc(strlen(result->error_str) + strlen(*error) + 2);
 497       sprintf(temp, "%s\n%s", result->error_str, *error);
 498       free(result->error_str);
 499       result->error_str = temp;
 500     }
 501   }
 502 
 503   /* and get the list of dates, we must check their order */
 504   date_list = up_get_dates(attribute_list);
 505   /* and check the order */ 
 506   res = up_check_date_order(date_list);
 507   if(!res){
 508     /* so, add the error string to result's error string */
 509     if(result->error_str == NULL){
 510       result->error_str = strdup("***Error: The dates in the 'changed' attributes should be in order");
 511     }else{
 512       temp = (char *)malloc(strlen(result->error_str) 
 513               + strlen("***Error: The dates in the 'changed' attributes should be in order") + 2);
 514       sprintf(temp, "%s\n%s", result->error_str, 
 515               "***Error: The dates in the 'changed' attributes should be in order");
 516       free(result->error_str);
 517       result->error_str = temp;
 518     }
 519     /* and here we have to change the result code of "result" here ... */
 520     switch(result->result){
 521       case UP_EXTSYN_OK:       result->result = UP_EXTSYN_ERR; break;
 522       case UP_EXTSYN_ERR:      result->result = UP_EXTSYN_ERR; break;
 523       case UP_EXTSYN_WARN:     result->result = UP_EXTSYN_ERR_WARN; break;
 524       case UP_EXTSYN_ERR_WARN: result->result = UP_EXTSYN_ERR_WARN; break;
 525       default: ;
 526     }
 527   }
 528 
 529   /* check the syntax of dates */
 530   date_check_res = up_check_dates_syntax(date_list);
 531   if(date_check_res->result != UP_DATE_OK){
 532     /* so, add the error string to result's error string */
 533     if(result->error_str == NULL){
 534       result->error_str = strdup(date_check_res->error_str);
 535     }else{
 536       temp = (char *)malloc(strlen(result->error_str) 
 537               + strlen(date_check_res->error_str) + 2);
 538       sprintf(temp, "%s\n%s", result->error_str, 
 539               date_check_res->error_str);
 540       free(result->error_str);
 541       result->error_str = temp;
 542     }
 543     /* and here we have to change the result code of "result" here ... */
 544     switch(result->result){
 545       case UP_EXTSYN_OK:       result->result = UP_EXTSYN_ERR; break;
 546       case UP_EXTSYN_ERR:      result->result = UP_EXTSYN_ERR; break;
 547       case UP_EXTSYN_WARN:     result->result = UP_EXTSYN_ERR_WARN; break;
 548       case UP_EXTSYN_ERR_WARN: result->result = UP_EXTSYN_ERR_WARN; break;
 549       default: ;
 550     }
 551     
 552   }
 553   
 554 }
 555 
 556 
 557 
 558 
 559 
 560 int up_check_an_auth_attr(const char * arg, char ** error){
     /* [<][>][^][v][top][bottom][index][help] */
 561 
 562   char * attr;
 563   int ret = 1;
 564   char * cryptpw, * key;
 565 
 566 
 567   attr = strdup(arg);
 568   /*  chop the whitespace in hte beginning and end */
 569   g_strstrip(attr);
 570 
 571   /* Convert to uppercase  */
 572   g_strup(attr);
 573 
 574   /* chop the EOL comment off */
 575   if(index(attr, '#') != NULL){
 576     attr[index(attr, '#') - attr ] = '\0';
 577   }
 578 
 579   if(strstr(attr, "MAIL-FROM ") == attr){
 580     /* It must have somethings after "MAIL-FROM ", which are
 581       supposed to be a regexp */
 582     if(strlen(attr) <= strlen("MAIL-FROM ")){
 583       ret = 0;
 584     }
 585   }else if(strstr(attr, "NONE") == attr){
 586     /* We mustn't have anything after "NONE"  */
 587     if(strlen(attr) != strlen("NONE")){
 588       *error = strdup("***Error: There mustn't be anything after NONE in 'auth' attribute");
 589       ret = 0;
 590     }
 591   }else if(strstr(attr, "CRYPT-PW ") == attr){
 592     /* The string after CRYPT-PW must be of length 13 and must consist of certain
 593        characters */
 594     cryptpw = strdup(attr + strlen("CRYPT-PW "));
 595     g_strstrip(cryptpw);
 596     if(strlen(cryptpw) != 13){
 597       *error = strdup("***Error: The crypted password must be 13-character long in 'auth' attribute");
 598       free(cryptpw);
 599       ret = 0;
 600     }
 601   }else if(strstr(attr, "PGPKEY-") == attr){
 602     /* The string after CRYPT-PW must be of length 13 and must consist of certain
 603        characters */
 604     key = strdup(attr + strlen("PGPKEY-"));
 605     g_strchomp(key);
 606     if(strlen(key) != 8){
 607       *error = strdup("***Error: The PGP key must be 8-character long in 'auth' attribute");
 608       
 609       free(key);
 610       ret = 0;
 611     }
 612 
 613   }else{
 614     *error = strdup("***Error: 'auth' attribute must start with MAIL-FROM, NONE, PGPKEY- or CRYPT-PW");
 615     ret = 0;
 616   }
 617 
 618   free(attr);
 619   return ret;
 620 }
 621 
 622 
 623 
 624 
 625 
 626 
 627 
 628 /* void up_check_auth_attr 
 629    checks the syntax of 'auth' attributes */
 630 void up_check_auth_attr(Object * obj, char * obj_text, GSList * attribute_list, external_syntax_struct * result){
     /* [<][>][^][v][top][bottom][index][help] */
 631 
 632   int res;
 633   char **error;
 634   char * temp;
 635   GSList * next;
 636 
 637   error   = (char **)malloc(sizeof(char **));
 638 
 639   /* loop in the attribute_list, find the 'auth' attribs, and check their syntax */
 640   for( next = attribute_list; next != NULL ; next = g_slist_next(next) ){
 641     /* is this an 'auth' attribute? */
 642     if(strcmp((char *)(((attribute_struct *)(next->data))->type), "auth") == 0){
 643       /* chech its syntax */
 644       res = up_check_an_auth_attr((char *)(((attribute_struct *)(next->data))->content), error);
 645       if(!res){
 646         /* so, add the error string to result's error string */
 647         if(result->error_str == NULL){
 648           result->error_str = strdup(*error);
 649         }else{
 650           temp = (char *)malloc(strlen(result->error_str) 
 651                   + strlen(*error) + 2);
 652           sprintf(temp, "%s\n%s", result->error_str, 
 653                   *error);
 654           free(result->error_str);
 655           result->error_str = temp;
 656         }
 657         /* and here we have to change the result code of "result" here ... */
 658         switch(result->result){
 659           case UP_EXTSYN_OK:       result->result = UP_EXTSYN_ERR; break;
 660           case UP_EXTSYN_ERR:      result->result = UP_EXTSYN_ERR; break;
 661           case UP_EXTSYN_WARN:     result->result = UP_EXTSYN_ERR_WARN; break;
 662           case UP_EXTSYN_ERR_WARN: result->result = UP_EXTSYN_ERR_WARN; break;
 663           default: ;
 664         }
 665       }
 666     }
 667   }
 668 }
 669 
 670 
 671 /* performs a simple check on a inetnum attribute. Assumes that
 672    the RPSL parser has already checked it. Tries to see if the attr
 673    is a range or not  */
 674 int up_check_an_inetnum_attr(const char * arg){
     /* [<][>][^][v][top][bottom][index][help] */
 675   
 676 
 677   char * str;
 678   char * pos;
 679 
 680   str = strdup(arg);
 681 
 682   while((pos = index(str, '\n')) != NULL){
 683     *pos = ' ';
 684   }
 685 
 686   /* strip off the comment */
 687   if((pos = index(str, '#')) != NULL){
 688     *pos = '\0';
 689   }
 690    
 691    
 692   /* Most of the syntax check is done by RPSL parser. We only need to check
 693      that the argument is a _range_ of IPv4 addresses. So it suffices to
 694      check the existence of '-' in the arg */
 695   if(index(str, '-') != NULL){
 696     
 697     free(str);
 698     return 1;
 699     
 700   }else{
 701 
 702     free(str);
 703     return 0;
 704 
 705   }
 706 }
 707 
 708 
 709 /* Prepares a list of mnt-by attributes */
 710 GSList * up_get_mntby_list(GSList * attribute_list){
     /* [<][>][^][v][top][bottom][index][help] */
 711 
 712   GSList * to_be_returned = NULL;
 713   GSList * next;
 714 
 715   for(next = attribute_list; next != NULL ; next = g_slist_next(next) ){
 716     
 717     if(strcmp((char *)(((attribute_struct *)(next->data))->type), "mnt-by") == 0){
 718       to_be_returned = g_slist_append(to_be_returned, ((attribute_struct *)(next->data))->content);
 719     }
 720   }
 721 
 722   return to_be_returned;
 723   
 724 }
 725 
 726 
 727 
 728 
 729 
 730 /* Performs a check on status attribute. It can be
 731    ALLOCATED PI or ALLOCATED PA only if the maintainers in the
 732    mnt-by attribute contain at least one of the names mentioned in
 733    ALLOCMNT config variable. 
 734 */
 735 int up_check_a_status_attr(const char * arg, GSList * mnt_by_list){
     /* [<][>][^][v][top][bottom][index][help] */
 736 
 737   GSList * next;
 738   int result;
 739   char * status, * mnt_by_attrib;
 740   char ** allocmnt_list;
 741   int i;
 742 
 743   status = strdup(arg);
 744   g_strdown(status);
 745  
 746   /* construct a list of mntners that are in allocmnt */
 747   allocmnt_list = g_strsplit(allocmnt, " ", 0); /* delimited by " " */
 748    
 749   if(strstr(status, "allocated") != NULL){ 
 750 
 751     result = 1; /* initialize */
 752     
 753     for( next = mnt_by_list; next != NULL ; next = g_slist_next(next) ){
 754 
 755       mnt_by_attrib = strdup((char *)((attribute_struct *)(next->data)));
 756       g_strstrip(mnt_by_attrib);
 757       for(i=0; allocmnt_list[i] != NULL; i++){/* loop thru the list of allocmnt maintainers */
 758         if((strlen(allocmnt_list[i]) != 0) && strcasecmp(mnt_by_attrib, allocmnt_list[i]) == 0){
 759           result = 0; 
 760         }
 761       }  
 762       free(mnt_by_attrib);
 763 
 764     }
 765     
 766     free(status);
 767     return result;
 768  
 769   }else{  /* the status attribute  */
 770   
 771     free(status);
 772     return 0; /* so there is no problem */
 773 
 774   }
 775 
 776   g_strfreev(allocmnt_list);
 777  
 778   free(status); 
 779   return 0;
 780 
 781 }
 782 
 783 
 784 
 785 
 786 
 787 
 788 /* void up_check_inetnum_attr checks the syntax of 'inetnum' 
 789    attributes (this is required to reject inetnums in the 
 790    form of "inetnum: 23.23.23.23". RPSL parser unfortunately
 791    passes them although we define them as a range of ipv4 addreses.) 
 792 
 793    Also, we check for status attribute here: The status attribute can be
 794    ALLOCATED PI or ALLOCATED PA only if the maintainers in the
 795    mnt-by attribute contain at least one of the names mentioned in
 796    ALLOCMNT config variable. 
 797 */
 798 void up_check_inetnum_attr(Object * obj, char * obj_text, GSList * attribute_list, external_syntax_struct * result){
     /* [<][>][^][v][top][bottom][index][help] */
 799 
 800   int res;
 801   char * temp;
 802   GSList * next;
 803   GSList * mnt_by_list = NULL;
 804 
 805   /* Gather a list of mnt-by attributes */
 806   mnt_by_list = up_get_mntby_list(attribute_list);
 807   
 808 
 809   /* loop in the attribute_list, find the 'inetnum' attribs, and check their syntax */
 810   for( next = attribute_list; next != NULL ; next = g_slist_next(next) ){
 811     /* is this an 'inetnum' attribute? */
 812     if(strcmp((char *)(((attribute_struct *)(next->data))->type), "inetnum") == 0){
 813       /* chech its syntax */
 814       res = up_check_an_inetnum_attr((char *)(((attribute_struct *)(next->data))->content));
 815       if(!res){
 816         /* so, add the error string to result's error string */
 817         if(result->error_str == NULL){
 818           result->error_str = strdup("***Error: inetnum must be a range of IPv4 address\n");
 819         }else{
 820           temp = (char *)malloc(strlen(result->error_str) 
 821                   + strlen("***Error: inetnum must be a range of IPv4 address\n") + 2);
 822           sprintf(temp, "%s\n%s", result->error_str, 
 823                   "***Error: inetnum must be a range of IPv4 address\n");
 824           free(result->error_str);
 825           result->error_str = temp;
 826         }
 827         /* and here we have to change the result code of "result" here ... */
 828         switch(result->result){
 829           case UP_EXTSYN_OK:       result->result = UP_EXTSYN_ERR; break;
 830           case UP_EXTSYN_ERR:      result->result = UP_EXTSYN_ERR; break;
 831           case UP_EXTSYN_WARN:     result->result = UP_EXTSYN_ERR_WARN; break;
 832           case UP_EXTSYN_ERR_WARN: result->result = UP_EXTSYN_ERR_WARN; break;
 833           default: ;
 834         }
 835       }
 836     }
 837 
 838     /* is this a status attribute? */
 839     if(strcmp((char *)(((attribute_struct *)(next->data))->type), "status") == 0){
 840       res = up_check_a_status_attr((char *)(((attribute_struct *)(next->data))->content), mnt_by_list);
 841       if(res != 0){/* there was a problem */
 842         /* so, add the error string to result's error string */
 843         if(result->error_str == NULL){
 844           result->error_str = (char *)UT_malloc(strlen("***Error: Status ALLOCATED can be set only by the following mntner(s):\n")
 845                                                 +strlen("***Error:    ") + strlen(allocmnt) + 2);
 846           sprintf(result->error_str, "%s%s%s", "***Error: Status ALLOCATED can be set only by the following mntner(s):\n",
 847                                                "***Error:    ", allocmnt);
 848         }else{
 849           temp = (char *)malloc(strlen(result->error_str) 
 850                   + strlen("***Error: Status ALLOCATED can be set only by the following mntner(s):\n") 
 851                   + strlen("***Error:    ") + strlen(allocmnt) + 2);
 852           sprintf(temp, "%s\n%s%s%s", result->error_str, 
 853                   "***Error: Status ALLOCATED can be set only by the following mntner(s):\n",
 854                   "***Error:    ", allocmnt);
 855           free(result->error_str);
 856           result->error_str = temp;
 857         }
 858         /* and here we have to change the result code of "result" here ... */
 859         switch(result->result){
 860           case UP_EXTSYN_OK:       result->result = UP_EXTSYN_ERR; break;
 861           case UP_EXTSYN_ERR:      result->result = UP_EXTSYN_ERR; break;
 862           case UP_EXTSYN_WARN:     result->result = UP_EXTSYN_ERR_WARN; break;
 863           case UP_EXTSYN_ERR_WARN: result->result = UP_EXTSYN_ERR_WARN; break;
 864           default: ;
 865         }
 866  
 867       }
 868     }
 869   }
 870 }
 871 
 872 
 873 
 874 
 875 
 876 
 877 
 878 /* GSList * up_add_keycert_attrs
 879    adds the generated attrs of key-cert objects */
 880 GSList * up_add_keycert_attrs(Object * obj, char * obj_text, GSList * attribute_list, external_syntax_struct * result){
     /* [<][>][^][v][top][bottom][index][help] */
 881 
 882   int res;
 883   char * type, * content;
 884   char **error;
 885   char * temp;
 886   GSList * new_list;
 887   attribute_struct * attribute;
 888   
 889   new_list = attribute_list;
 890 
 891 
 892   /* if this is a key-cert object */
 893   if(strcmp(obj->type->getName(), "key-cert") == 0){
 894       content = strdup("PGP");
 895       type = strdup("method");
 896       attribute = (attribute_struct *)malloc(sizeof(attribute_struct)); 
 897       attribute->content = content;
 898       attribute->type = type;
 899       new_list = g_slist_insert(new_list, attribute, 1);
 900 
 901       content = strdup(keyowner);
 902       type = strdup("owner");
 903       attribute = (attribute_struct *)malloc(sizeof(attribute_struct)); 
 904       attribute->content = content;
 905       attribute->type = type;
 906       new_list = g_slist_insert(new_list, attribute, 2);
 907 
 908       content = strdup(fingerprint);
 909       type = strdup("fingerpr");
 910       attribute = (attribute_struct *)malloc(sizeof(attribute_struct)); 
 911       attribute->content = content;
 912       attribute->type = type;
 913       new_list = g_slist_insert(new_list, attribute, 3);
 914       
 915   }
 916 
 917   return new_list;
 918 
 919 }
 920 
 921 
 922 
 923 
 924 
 925 
 926 
 927 
 928 
 929 
 930 /* Constructs a list of all attributes of an object, and returns it
 931    as a list of attribute_struct */
 932 GSList * up_get_attribute_list(Object * o, char * text){
     /* [<][>][^][v][top][bottom][index][help] */
 933 
 934   char * value = NULL;
 935   char * type = NULL;
 936   Attr *attr;
 937   GSList *list_of_attributes = NULL;
 938   attribute_struct * attribute;
 939   
 940   for(attr = o->attrs.head(); attr; attr = o->attrs.next(attr)){
 941     value = (char*)malloc((*attr).len - strlen(attr->type->name()) - 1);
 942     strncpy(value, (char *)(text+attr->offset) + strlen(attr->type->name())+1,
 943         attr->len - strlen(attr->type->name()) -2 );
 944     value[attr->len - strlen(attr->type->name()) - 2 ] = '\0';
 945       if(tracing) {
 946         cout << "TRACING: up_get_attributes: adding " << g_strstrip(value) << endl;
 947       }
 948       attribute = (attribute_struct *)malloc(sizeof(attribute_struct)); 
 949       attribute->content = value;
 950       type = strdup(attr->type->name());
 951       g_strdown(type);
 952       attribute->type = type;
 953       list_of_attributes = g_slist_append(list_of_attributes, attribute);
 954   }
 955 
 956   
 957   return list_of_attributes; 
 958 
 959 }
 960 
 961 
 962 
 963 
 964 /* up_reconstruct_object: Reconstructs the object's text representation
 965      using the attribute list */
 966 void up_reconstruct_object(GSList * attr_list, external_syntax_struct *result){
     /* [<][>][^][v][top][bottom][index][help] */
 967 
 968   char * recons_obj = NULL;
 969   char * temp;
 970   char * content, * type;
 971   GSList * next;
 972 
 973 
 974 
 975 
 976   for( next = attr_list; next != NULL ; next = g_slist_next(next) ){
 977 
 978     content = strdup((char *)(((attribute_struct *)(next->data))->content));
 979     type = strdup((char *)(((attribute_struct *)(next->data))->type));
 980 
 981     if(tracing){
 982       printf("TRACING: up_reconstruct_object:[%s:%s]\n", type, content);
 983     }
 984     
 985     if(recons_obj == NULL){
 986       recons_obj = (char *)malloc(14 + strlen(content) + 1 );
 987       /* trim the white spaces in the beginning */
 988       g_strchug(content);
 989 
 990       /* add ':' at the end of 'type' */
 991       temp = (char *)malloc(strlen(type) + 2);
 992       sprintf(temp, "%s:", type);
 993       free(type);
 994       type = temp;
 995 
 996       sprintf(recons_obj, "%-14s%s", type, content);
 997     }else{
 998       /* trim the white spaces in the beginning */
 999       g_strchug(content);
1000 
1001       /* add ':' at the end of 'type' */
1002       temp = (char *)malloc(strlen(type) + 2);
1003       sprintf(temp, "%s:", type);
1004       free(type);
1005       type = temp;
1006       
1007       temp = (char *)malloc(strlen(recons_obj) + 14 + strlen(content) + 3 );
1008       sprintf(temp, "%s\n%-14s%s", recons_obj, type, content);
1009       free(recons_obj);
1010       recons_obj = temp;
1011     }
1012     
1013   }
1014   
1015   result->new_obj = recons_obj;
1016   
1017 }
1018 
1019 
1020 
1021 
1022 /*  UP_check_external_syntax: Checks the syntax of attributes which are not checked
1023        by RAToolSet syntax checker. */
1024 external_syntax_struct * UP_check_external_syntax(Object * arg, char * obj_text){
     /* [<][>][^][v][top][bottom][index][help] */
1025   
1026   external_syntax_struct *result;
1027   GSList * attribute_list;
1028   
1029  
1030 
1031 
1032   result = (external_syntax_struct *)malloc(sizeof(external_syntax_struct));
1033 
1034   /* initialize the struct */
1035   result->result = 0;
1036   result->error_str = strdup(""); 
1037   result->warning_str = strdup("");
1038 
1039   /* get a list of all attributes */
1040   attribute_list = up_get_attribute_list(arg, obj_text);
1041 
1042   up_check_changed_attr(arg, obj_text, attribute_list, result);
1043   up_check_auth_attr   (arg, obj_text, attribute_list, result);  
1044   up_check_inetnum_attr(arg, obj_text, attribute_list, result);
1045   
1046   
1047   up_reconstruct_object(attribute_list, result);
1048 
1049   if(tracing){
1050     printf("TRACING: UP_check_external_syntax: the reconstructed object is=[%s]\n", result->new_obj);
1051     printf("TRACING: UP_check_external_syntax: ... and the result code is=[%i]\n", result->result);
1052   }
1053 
1054   return result;  
1055 }
1056 
1057 
1058 
1059 
1060 
1061 /* generates the "generated" attributes of a key-cert object. Returns the 
1062    new object as a char * */
1063 char * UP_generate_kc_attrs(Object * arg, char * obj_text){
     /* [<][>][^][v][top][bottom][index][help] */
1064   
1065   external_syntax_struct *result;
1066   GSList * attribute_list;
1067   
1068  
1069 
1070 
1071   result = (external_syntax_struct *)malloc(sizeof(external_syntax_struct));
1072 
1073   /* initialize the struct */
1074   result->result = 0;
1075   result->error_str = strdup(""); 
1076   result->warning_str = strdup("");
1077 
1078   /* get a list of all attributes */
1079   attribute_list = up_get_attribute_list(arg, obj_text);
1080 
1081   up_check_changed_attr(arg, obj_text, attribute_list, result);
1082   //up_check_auth_attr   (arg, obj_text, attribute_list, result);  
1083   attribute_list = up_add_keycert_attrs (arg, obj_text, attribute_list, result); 
1084 
1085   
1086   up_reconstruct_object(attribute_list, result);
1087 
1088   if(tracing){
1089     printf("TRACING: UP_check_external_syntax: the reconstructed object is=[%s]\n", result->new_obj);
1090     printf("TRACING: UP_check_external_syntax: ... and the result code is=[%i]\n", result->result);
1091   }
1092 
1093   return result->new_obj;  
1094 }
1095 

/* [<][>][^][v][top][bottom][index][help] */