bin/dbupdate/dbupdate.cc

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

FUNCTIONS

This source file includes following functions.
  1. error_init
  2. delete_key
  3. import_key
  4. get_keyowner_fingerpr
  5. process_object
  6. process_file
  7. generate_upd_file
  8. create_lock_file
  9. remove_lock_file
  10. write_checkpoint
  11. remove_checkpoint
  12. main

   1 /***************************************
   2   $Revision: 1.75 $
   3 
   4   DBupdate 
   5 
   6   Status: NOT REVIEWED, TESTED
   7 
   8   Author(s):       Engin Gunduz
   9 
  10   ******************/ /******************
  11   Modification History:
  12         engin (01/03/2000) Created.
  13   ******************/ /******************
  14   Copyright (c) 2000                              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 
  36 
  37 #include <config.h>
  38 #include "dbupdate.h"
  39 #include "UP_extrnl_syntax.h"
  40 #include "UP_subject.h"
  41 #include "er_yacc_helper.h"
  42 #include "erroutines.h"
  43 #include "ca_configFns.h"
  44 #include "ca_dictionary.h"
  45 #include "ca_macros.h"
  46 #include "ca_srcAttribs.h"
  47 #include "notification.h"
  48 #include "gpg.h"
  49 #include "mail_parser.h"
  50 #include "process.h"
  51 
  52 #ifdef HAVE_SYS_PARAM_H
  53 #include <sys/param.h>
  54 #endif
  55 
  56 
  57 int tracing = 0;
  58 int test_mode = 0;
  59 int supress_ack_notif = 0;
  60 int print_out_ack = 0;
  61 
  62 /* do we process a mail */
  63 int reading_from_mail = 0;
  64 
  65 /* are we processing networkupdate? */
  66 int networkupdate = 0;
  67 
  68 /* IP of the networkupdate client */
  69 char * netupdclientIP = NULL;
  70 
  71 
  72 /* sender of the mail, in case of a mail update */
  73 char *update_mail_sender = NULL;
  74 char *update_mail_subject = NULL;
  75 char *update_mail_date = NULL;
  76 char *update_mail_ID = NULL;
  77 char *update_mail_cc = NULL;
  78 
  79 /* required configuration variables */
  80 char *tmpdir = NULL;
  81 char *lockdir = NULL;
  82 char *mailcmd = NULL;
  83 char *notitxt = NULL;
  84 char *notimailtxt = NULL;
  85 char *notinetworktxt = NULL;
  86 char *fwtxt   = NULL;
  87 char *fwmailtxt = NULL;
  88 char *mtfwheader = NULL; 
  89 char *mtfwtxt = NULL;
  90 char *mailtxt = NULL;
  91 char *acksig = NULL;
  92 char *defmail = NULL;
  93 char *updlog = NULL;
  94 char *notiflog = NULL;
  95 char *crosslog = NULL;
  96 char *acklog = NULL;
  97 char *forwlog = NULL;
  98 char *humailbox = NULL;
  99 char *autobox = NULL;
 100 char *copyright_notice = NULL;
 101 char *overridecryptedpw = NULL;
 102 char *country = NULL;
 103 char *countries[400];
 104 char *sources[100];
 105 char *pgppath = NULL;
 106 char *gpgcmd = NULL;
 107 char *pgp_public_key_ring = NULL;
 108 char *autodbmhelp = NULL; 
 109 char *update_host = NULL;
 110 int  update_port;
 111 char *query_host = NULL;
 112 int  query_port;
 113 char *cn_subject_add = NULL;
 114 char *cn_subject_del = NULL;
 115 char *cn_explain_add = NULL;
 116 char *cn_explain_del = NULL;
 117 char *cn_overlap_add = NULL;
 118 char *cn_overlap_del = NULL;
 119 char *cno_subject_add = NULL;
 120 char *cno_subject_del = NULL;
 121 char *cno_explain_add = NULL;
 122 char *cno_explain_del = NULL;
 123 char *cno_overlap_add = NULL;
 124 char *cno_overlap_del = NULL;
 125 char *mheader = NULL;
 126 char *DBhost = NULL;
 127 int  DBport;
 128 char *DBuser = NULL;
 129 char *DBname = NULL;
 130 char *DBpasswd = NULL;
 131 /* end of config variables */
 132 
 133 char * fingerprint = NULL;
 134 char * keyowner = NULL;
 135 
 136 /* result of subject line processing is kept in the following struct. */
 137 up_subject_struct subject_result;
 138 
 139 
 140 /* hostname and pid are used all over the program, so we save them into these variables */
 141 char hostname[MAXHOSTNAMELEN];
 142 //char * hostname;
 143 int pid;
 144 
 145 /* name of the lock file, which is used for the crash recovery mechanism */
 146 char * lock_file_name;
 147 
 148 void error_init(int argc, char ** argv) {
     /* [<][>][^][v][top][bottom][index][help] */
 149 
 150   ER_init("dbupdate", 1);
 151   
 152 
 153 } /* error_init() */
 154 
 155 
 156 
 157 
 158 
 159 
 160 /* 'lockfile' struct is for keeping both the name of the lock file and the file descriptor
 161     of it, which is open during the execution of dbupdate. We need the filedes to close it,
 162     when dbupdate finishes, and the name to delete the file. */
 163 typedef struct {
 164    char * lockname;
 165    int filedes;
 166 } lockfilestruct;
 167 
 168 
 169 lockfilestruct lockfile;
 170 
 171 
 172 
 173 /* Deletes the key defined in the incoming object (a key-cert object)
 174    from the public keyring. Returns NULL if there was no error,
 175    returns an error message if there is an error */
 176 char * delete_key(char * obj){
     /* [<][>][^][v][top][bottom][index][help] */
 177 
 178   struct ImportKeyObject iKO;
 179   char * obj_keyID;
 180   char * key_cert_attr;
 181   GSList * templist, * certiflist, * next;
 182   u32 keyID;
 183   char * tempfile;
 184   char ** lines;
 185   int i;
 186   FILE * key_file;
 187   char * temp, * temp2;
 188   char * error_string;
 189 
 190   templist = get_attr_list(obj, "key-cert");
 191   key_cert_attr = strdup((char *)templist->data);
 192   g_slist_free(templist);
 193 
 194   tempfile = (char *)malloc(strlen(tmpdir) + strlen("tmp-key.") + 32);
 195   sprintf(tempfile, "%s/tmp-key.%i", tmpdir, pid /*getpid()*/);
 196 
 197   /* now we must write certif attribute(s) of this key-certif into the tempfile */
 198   /* get the certif first */
 199   certiflist = get_attr_list(obj, "certif");
 200   if(( key_file = fopen(tempfile, "w")) == NULL){
 201      //fprintf(stderr, "Can't open temporary file, %s", tempfile);
 202      ER_perror(FAC_UP, UP_CANTOPEN, "Can't open temporary file, %s", tempfile);
 203      exit(1);
 204   }
 205   for( next = certiflist; next != NULL ; next = g_slist_next(next) ){
 206     lines = g_strsplit((char *)next->data, "\n", 0);
 207     if(lines[0] == NULL){/* if this was an empty attribute, just print an empty line */
 208       fprintf(key_file, "\n"); 
 209     }
 210     for(i = 0; lines[i] != NULL; i++){
 211       temp = strdup(lines[i]);
 212       if(i != 0 && temp[0] == '+'){/* if it begins with a plus */
 213         temp2 = strdup(temp + 1);
 214         g_strstrip(temp2);
 215         fprintf(key_file, "%s\n", temp2);
 216         free(temp);free(temp2);
 217       }else{
 218         g_strstrip(temp);
 219         fprintf(key_file, "%s\n", temp);
 220         free(temp); 
 221       }
 222     }
 223     g_strfreev(lines);
 224     //fprintf(key_file, "%s\n", (char *)next->data);
 225   }
 226   fclose(key_file);
 227   g_slist_free(certiflist);
 228 
 229   strcpy(iKO.iFilename, tempfile);
 230 
 231   if(tracing){
 232     printf("TRACING: delete_key: key_cert_attr: [%s]\n", key_cert_attr);
 233   }
 234   
 235   obj_keyID = strdup(key_cert_attr + strlen("PGPKEY-"));
 236 
 237   if(tracing){
 238     printf("TRACING: delete_key: obj_keyID: [%s]\n", obj_keyID);
 239   }
 240   
 241   keyID = strtoul(obj_keyID, NULL, 16);
 242 
 243   if(tracing){
 244     printf("TRACING: delete_key: keyID is: %u, %X\n", keyID, keyID);
 245   }
 246   
 247   
 248   
 249   strcpy(iKO.keyRing, pgp_public_key_ring);
 250   PA_RemoveKey(&iKO);
 251 
 252   if(tracing){
 253     printf("TRACING: importKeyObj status:\n");
 254     printf("TRACING: isValid: %d\n", iKO.rc);
 255   }
 256   
 257 
 258 
 259   unlink(tempfile);
 260   if(iKO.rc == iKO_OK){/* if PA_RemoveKey returned OK */
 261     return NULL;
 262   }else{/* if PA_RemoveKey returned not OK */
 263       switch(iKO.rc){
 264         case iKO_UNCHANGED:      error_string = strdup("the key is already in the keyring");break; 
 265         case iKO_NOUSERID:       error_string = strdup("no user ID could be extracted");break;
 266         case iKO_GENERAL:        error_string = strdup("general PGP error");break;
 267         case iKO_NOTVALIDUSERID: error_string = strdup("no valid user ID ");break;
 268         case iKO_NOPUBLICKEY:    error_string = strdup("no public key in the object");break;
 269         case iKO_NODEFAULTPUBLICKEYRING: error_string = strdup("general PGP error");break;
 270         case iKO_CRC_ERROR:      error_string = strdup("CRC error in the certificate");break;
 271         case iKO_NO_OPENPGP_DATA:error_string = strdup("no OpenPGP data in the object");break;
 272         case iKO_NO_IN_FILES:    error_string = strdup("general PGP error");break;
 273         case iKO_GENERALFAILURE: error_string = strdup("general PGP error");break;
 274         default:            error_string = strdup("general PGP error");
 275       }
 276       return error_string; 
 277   }
 278 
 279   return NULL;
 280 }
 281 
 282 
 283 /* Takes a key-certif object, extracts its 'certif' attribute and adds
 284    the key into public keyring
 285    If there is no problem, it returns NULL
 286    If there is a problem, then it returns a string which contains an error
 287    message */
 288 char * import_key(char *obj){
     /* [<][>][^][v][top][bottom][index][help] */
 289 
 290   char * tempfile;
 291   struct ImportKeyObject iKO;
 292   GSList * certiflist, * next, * templist;
 293   FILE * key_file;
 294   char keyID[9];
 295   char * obj_keyID, * key_cert_attr;
 296   char * error_string = NULL;
 297   char ** lines;
 298   int i;
 299   char * temp, * temp2;
 300    
 301   tempfile = (char *)malloc(strlen(tmpdir) + strlen("tmp-key.") + 32);
 302   sprintf(tempfile, "%s/tmp-key.%i", tmpdir, pid );
 303 
 304   /* now we must write certif attribute(s) of this key-certif into the tempfile */
 305   /* get the certif first */
 306   certiflist = get_attr_list(obj, "certif");
 307   if(( key_file = fopen(tempfile, "w")) == NULL){
 308      ER_perror(FAC_UP, UP_CANTOPEN, "Can't open temporary file, %s", tempfile);
 309      exit(1);
 310   }
 311   for( next = certiflist; next != NULL ; next = g_slist_next(next) ){
 312     lines = g_strsplit((char *)next->data, "\n", 0);
 313     if(lines[0] == NULL){/* if this was an empty attribute, just print an empty line */
 314       fprintf(key_file, "\n"); 
 315     }
 316     for(i = 0; lines[i] != NULL; i++){
 317       temp = strdup(lines[i]);
 318       if(i != 0 && temp[0] == '+'){/* if it begins with a plus */
 319         temp2 = strdup(temp + 1);
 320         g_strstrip(temp2);
 321         fprintf(key_file, "%s\n", temp2);
 322         free(temp);free(temp2);
 323       }else{
 324         g_strstrip(temp);
 325         fprintf(key_file, "%s\n", temp);
 326         free(temp); 
 327       }
 328     }
 329     g_strfreev(lines);
 330   }
 331   fclose(key_file);
 332   g_slist_free(certiflist);
 333 
 334   strcpy(iKO.iFilename, tempfile);
 335   strcpy(iKO.keyRing, pgp_public_key_ring);
 336   PA_ImportKey(&iKO);
 337 
 338   if(tracing){
 339     printf("importKeyObj status:\n");
 340     
 341     printf("isValid: %d\n", iKO.rc);
 342     printf("keyID: %08lX\n", iKO.keyID);
 343   }
 344   snprintf(keyID, 9, "%08lX", iKO.keyID);
 345   
 346   if(tracing){
 347     printf("keyID: [%s]\n", keyID);
 348   }
 349   
 350   unlink(tempfile);
 351   free(tempfile);
 352 
 353   
 354   templist = get_attr_list(obj, "key-cert");
 355   key_cert_attr = strdup((char *)templist->data);
 356   g_slist_free(templist);
 357 
 358   if(tracing){
 359     printf("key_cert_attr: [%s]\n", key_cert_attr);
 360   }
 361   obj_keyID = strdup(key_cert_attr + strlen("PGPKEY-"));
 362   if(tracing){
 363     printf("obj_keyID: [%s]\n", obj_keyID);
 364   }
 365   if(iKO.rc == iKO_OK && (strcasecmp(obj_keyID, keyID) == 0)){/* if PA_ImportKey returned OK 
 366                                                             and the real keyID is equal to the
 367                                                             keyID in the 'key-cert' attribute */
 368     fingerprint = strdup(iKO.fingerPrint); 
 369     keyowner    = strdup(iKO.keyOwner);                                                           
 370     return NULL;
 371   }else{/* if PA_ImportKey returned not OK or obj_keyID, keyID didn't match */
 372     if(iKO.rc != iKO_OK){
 373       switch(iKO.rc){
 374         case iKO_UNCHANGED:      error_string = strdup("the key is already in the keyring");break; 
 375         case iKO_NOUSERID:       error_string = strdup("no user ID could be extracted");break;
 376         case iKO_GENERAL:        error_string = strdup("general PGP error");break;
 377         case iKO_NOTVALIDUSERID: error_string = strdup("no valid user ID ");break;
 378         case iKO_NOPUBLICKEY:    error_string = strdup("no public key in the object");break;
 379         case iKO_NODEFAULTPUBLICKEYRING: error_string = strdup("general PGP error");break;
 380         case iKO_CRC_ERROR:      error_string = strdup("CRC error in the certificate");break;
 381         case iKO_NO_OPENPGP_DATA:error_string = strdup("no OpenPGP data in the object");break;
 382         case iKO_NO_IN_FILES:    error_string = strdup("general PGP error");break;
 383         case iKO_GENERALFAILURE: error_string = strdup("general PGP error");break;
 384         default:            error_string = strdup("general PGP error");
 385       }
 386       return error_string; 
 387     }else{
 388       error_string = (char *)malloc(1024);/* this should be enough */
 389       sprintf(error_string, "Keyid for this certificate (%s) is not the same as the PGPKEY field (%s)", 
 390                  keyID, obj_keyID);
 391       return error_string;
 392     }
 393   }
 394       
 395 }
 396 
 397 
 398 
 399 
 400 
 401 /* Gets the keyowner and fingerprint of a PGP key 
 402    from the keycert object. The keycert object must already
 403    be in the database (thus, in the keyring) 
 404    The fingerprint and keyowner will be saved in global variables */
 405    
 406 void * get_keyowner_fingerpr(char *obj){
     /* [<][>][^][v][top][bottom][index][help] */
 407 
 408   GSList * templist = NULL;
 409   char * obj_keyID = NULL;
 410   struct ImportKeyObject iKO;
 411   u32 keyID;
 412   char * key_cert_attr;
 413    
 414   
 415   templist = get_attr_list(obj, "key-cert");
 416   key_cert_attr = strdup((char *)templist->data);
 417   g_slist_free(templist);
 418 
 419   if(tracing){
 420     printf("get_keyowner_fingerpr: key_cert_attr is [%s]\n", key_cert_attr);
 421   } 
 422   obj_keyID = strdup(key_cert_attr + strlen("PGPKEY-"));
 423   if(tracing){
 424     printf("get_keyowner_fingerpr: obj_keyID is [%s]\n", obj_keyID);
 425   }
 426  
 427   sscanf(obj_keyID, "%8X", &keyID); 
 428   if(tracing){
 429     printf("get_keyowner_fingerpr: keyID is [%s]\n", keyID);
 430   }
 431   
 432   /* set appropriate fields of iKO */ 
 433   iKO.keyID = keyID;
 434   strcpy(iKO.keyRing, pgp_public_key_ring);
 435 
 436   GetFingerPrint(&iKO);
 437   fingerprint = strdup(iKO.fingerPrint);
 438   
 439   GetKeyOwner(&iKO);
 440   keyowner = strdup(iKO.keyOwner); 
 441 
 442 
 443   if(tracing){
 444     if(fingerprint != NULL){
 445       printf("get_keyowner_fingerpr: fingerprint is [%s]\n", fingerprint);
 446     }
 447     if(keyowner){
 448       printf("get_keyowner_fingerpr: keyowner is [%s]\n", keyowner);
 449     }
 450   }
 451 }
 452 
 453 
 454 
 455 
 456 
 457 
 458 /* Checks the object's syntax, retrives the old version of it from the db, 
 459    and checks auth2. If everything is OK, then sends it to RIPdb, where referential
 460    integrity is checked, and the object is really committed to the db.
 461   
 462      Arguments:
 463         char * arg: The object,
 464         credentials_struct credentials: The struct containing the credentials, such as 
 465           'From:' field of the e-mail update,
 466         GHashTable * NIC_hdl_hash: A hash containing 
 467         char * ack_file_name:  The file name, to be used to store ACK message 
 468 */
 469 
 470 
 471 
 472 int process_object(char * incoming, credentials_struct credentials, 
     /* [<][>][^][v][top][bottom][index][help] */
 473                    GHashTable * NIC_hdl_hash, char * ack_file_name,
 474                    GHashTable * ntfy_hash, GHashTable * forw_hash, GHashTable * cross_hash){
 475   
 476     bool code = true;
 477     Object *o;
 478     char * old_version = NULL;
 479     o = new Object;
 480     int result = 0;
 481     //int result_from_RIPupd = 0;
 482     up_ripupd_result_struct * result_from_RIPupd;
 483     char * result_from_import_key = NULL;
 484     char * result_from_delete_key = NULL;
 485     char * auto_nic = NULL;
 486     char * changed_obj = NULL;
 487     char * obj_with_AUTO_NIC_hdl;
 488     char * assigned_NIC;
 489     char * formatted_object;
 490     char * type;
 491     char * arg;
 492     char * arg2;
 493     char * generated_object;
 494     external_syntax_struct * external_syntax_results;
 495 
 496 
 497     char * value = NULL;/* these two are for */
 498     Attr * attr;        /* ack messages only */ 
 499 
 500     arg = strdup(incoming);
 501     
 502     if(has_ref_to_AUTO_nic_hdl(arg)){/* if this object has refs to AUTO NIC hdls*/
 503        /* then first replace AUTO NIC hdls with assigned NIC hdls (in NIC_hdl_hash) */
 504        if((changed_obj = replace_refs_to_AUTO_NIC_hdl(changed_obj, arg, NIC_hdl_hash)) == NULL){
 505          /* try to parse the object only for reporting purposes */
 506          o->scan_silent(arg,strlen(arg));
 507          AK_add_to_ack(ack_file_name, "\nUpdate FAILED: [%s] Unknown AUTO NIC handle referenced\n%s\n", 
 508                  (o && o->type) ? o->type->getName() : "unknown-type", arg);
 509          delete(o);
 510          return UP_ANE; /* AUTO NIC hdl error */
 511          
 512        }else{ /* in this case, we must use changed_obj instead of arg */
 513 
 514          free(arg); 
 515          arg = changed_obj; 
 516 
 517        };
 518     }
 519   
 520     
 521     code = o->scan_silent(arg,strlen(arg));
 522     if(code){
 523       type = get_class_type(o);
 524       /* is the object to be deleted? */
 525       if(o->isDeleted){
 526         old_version = get_old_version(arg);
 527         if(old_version == NULL){ /* the object doesn't exist in the db! */
 528           AK_add_to_ack(ack_file_name, "\nDelete FAILED: [%s] %s\nEntry not found\n\n%s\n", 
 529                         o->type->getName(), get_search_key(o, o->type->getName(), arg), arg);
 530           return UP_NSO; /* no such object */
 531         }else {/* the object is in the db */
 532           if(identical(old_version, arg) /* if the old & new versions are identical */
 533              || (strcmp(o->type->getName(), "key-cert") == 0)  /* or it is a key-cert object  */
 534              || (strcmp(o->type->getName(), "inet6num") == 0)){/* or it is an inet6num object */
 535             result = check_auth(NULL, old_version, o->type->getName(), credentials);
 536             if(result == UP_AUTH_OK){ 
 537               if(tracing) {
 538                 printf("TRACING: Will send the obj to be deleted\n");
 539               }
 540               if(strcmp(type, "key-cert") == 0){
 541                 result_from_delete_key = delete_key(arg);
 542               }else{
 543                 result_from_delete_key = NULL;
 544               }
 545               /* if there was no problem with key deletion from the key-ring */
 546               if(result_from_delete_key == NULL){
 547                 result_from_RIPupd = send_object_db(arg, NULL, "DEL");
 548                 if(result_from_RIPupd->result == 0){
 549                   AK_add_to_ack(ack_file_name, "\nDelete OK: [%s] %s\n", 
 550                                 o->type->getName(), get_search_key(o, o->type->getName(), arg));
 551                   NT_write_all_ntfs(old_version, NULL, NULL, tmpdir, ntfy_hash, forw_hash, cross_hash, 
 552                                     credentials.from);
 553                 }else{
 554                   AK_add_to_ack(ack_file_name, "\nDelete FAILED: [%s] %s\n%s\n",
 555                                 o->type->getName(), get_search_key(o, o->type->getName(), arg),
 556                                 result_from_RIPupd->error_str);
 557                 }
 558                 result_from_RIPupd->result = 0;
 559               }else{
 560                  AK_add_to_ack(ack_file_name, "\nDelete FAILED: [%s] %s\n%s\n",
 561                                 o->type->getName(), get_search_key(o, o->type->getName(), arg), result_from_delete_key);
 562               }
 563             }else{ /* auth failed */
 564               if(tracing) {
 565                 printf("TRACING: Auth failed\n");
 566               }
 567 
 568               AK_add_to_ack(ack_file_name, "\nDelete FAILED: [%s] %s\nAuthorisation failed, request forwarded to maintainer.\n%s\n",
 569                             o->type->getName(), get_search_key(o, o->type->getName(), arg), arg);
 570               NT_write_all_frwds(arg, NULL, tmpdir, ntfy_hash, forw_hash, cross_hash, credentials.from);
 571               return UP_AUF; /* Auth failed */
 572             } 
 573           }else{/* the new & old versions do not match */
 574             AK_add_to_ack(ack_file_name, "\nDelete FAILED: [%s] %s\nnew & old versions do not match\n%s\n",
 575                  o->type->getName(), get_search_key(o, o->type->getName(), arg), arg);
 576             return UP_NOM; /* new & old versions do not match */
 577           }
 578         }
 579       }else {/* the object is _not_ to be deleted */
 580         
 581         if(has_AUTO_NIC_hdl(arg)){/* if the object has an AUTO NIC hdl */
 582           external_syntax_results = UP_check_external_syntax(o, arg);
 583           if(     external_syntax_results->result != UP_EXTSYN_ERR 
 584                && external_syntax_results->result != UP_EXTSYN_ERR_WARN){/* if there is no error */
 585             /* then its nic-hdl attribute must be modified so that RIPupdate
 586                would understand that it must assign a NIC handle to it */
 587             /* but first check the auth */
 588             result = check_auth(arg, NULL, o->type->getName(), credentials);
 589             if(result == UP_AUTH_OK){
 590               if(tracing) {                                
 591                   printf("TRACING: Will send the obj to be created with AUTO NIC hdl\n");
 592               }
 593               auto_nic = (char *)malloc(1024); /* should be enough for a NIC hdl */
 594               obj_with_AUTO_NIC_hdl = replace_AUTO_NIC_hdl(external_syntax_results->new_obj, auto_nic);
 595               if(tracing) {  
 596                 printf("TRACING:  Called replace_AUTO_NIC_hdl, get [%s]\n", obj_with_AUTO_NIC_hdl);
 597                 printf("TRACING: Will send the obj to be added\n");
 598               }
 599               assigned_NIC = (char *)malloc(128); /* this should be enough for a NIC hdl */
 600               result_from_RIPupd = send_object_db(obj_with_AUTO_NIC_hdl, assigned_NIC, "ADD");
 601               if(result_from_RIPupd->result == 0){
 602                 AK_add_to_ack(ack_file_name, "\nNew OK: [%s] %s\n", 
 603                               o->type->getName(), assigned_NIC);
 604                 /* replace the AUTO nic hdl with the assigned one (for reporting purposes, in the notif mesg) */
 605                 formatted_object = UP_put_assigned_NIC(external_syntax_results->new_obj, assigned_NIC);
 606                 formatted_object = delete_override(formatted_object);
 607                 arg2 = delete_override(arg);
 608                 NT_write_all_ntfs(NULL, arg2, formatted_object, tmpdir, ntfy_hash, forw_hash, cross_hash, 
 609                                   credentials.from);
 610               }else{
 611                 AK_add_to_ack(ack_file_name, "\nNew FAILED: [%s]\n%s\n%s\n",
 612                               o->type->getName(), arg,
 613                               result_from_RIPupd->error_str);
 614               }
 615               result_from_RIPupd->result = 0;
 616               if(tracing && assigned_NIC != NULL) {  
 617                 printf("TRACING: send_object_db returned [%s] as assigned NIC hdl\n", assigned_NIC);
 618               }
 619               if(assigned_NIC != NULL){
 620                 if(tracing){
 621                   printf("TRACING: auto_nic=[%s], assigned_NIC=[%s]\n", auto_nic, assigned_NIC);
 622                 }
 623                 g_hash_table_insert(NIC_hdl_hash, auto_nic, assigned_NIC);
 624                 if(tracing){
 625                   printf("TRACING: NIC_hdl_hash has %i pairs\n",g_hash_table_size(NIC_hdl_hash));
 626                 }
 627               }
 628               
 629             }else{
 630               /* auth failed ! */
 631               if(tracing) {
 632                 printf("TRACING: Auth failed\n");
 633               }
 634   
 635               AK_add_to_ack(ack_file_name, "\nNew FAILED: [%s] %s\nAuthorisation failed, request forwarded to maintainer.\n%s\n",
 636                             o->type->getName(), get_search_key(o, o->type->getName(), arg), arg);
 637               arg2 = delete_override(arg);
 638               NT_write_all_frwds(NULL, arg2, tmpdir, ntfy_hash, forw_hash, cross_hash, credentials.from);
 639               return UP_AUF; /* Auth failed */
 640             }
 641           }else{/* external syntax check failed */
 642             AK_add_to_ack(ack_file_name, "\nUpdate FAILED: [%s] %s\n%s%s\n",
 643                    o->type->getName(), get_search_key(o, o->type->getName(), arg), 
 644                    arg, external_syntax_results->error_str);
 645           }
 646         }
 647         else{ 
 648           old_version = get_old_version(arg);
 649           if(old_version != NULL){/* so, this is an update operation */
 650             if( (!reading_from_mail) || 
 651                 (subject_result.result != UP_SUBJ_NEW_ENFORCED)){/* If the user didn't enforce 
 652                                                                     creation in the subject line */
 653               external_syntax_results = UP_check_external_syntax(o, arg);
 654               if(    external_syntax_results->result != UP_EXTSYN_ERR 
 655                   && external_syntax_results->result != UP_EXTSYN_ERR_WARN){/* if there is no error */
 656                 /* if the old version & the new one are not identical */ 
 657                 if(identical(old_version, arg) != 1){
 658                   result = check_auth(arg, old_version, o->type->getName(), credentials);    
 659                   if(result == UP_AUTH_OK){
 660                     if(tracing) {                                
 661                       printf("TRACING: Will send the obj to be updated\n");
 662                     }
 663 
 664                     if(strcasecmp(o->type->getName(), "key-cert") == 0){
 665                       get_keyowner_fingerpr(arg);
 666                       generated_object = UP_generate_kc_attrs(o, arg);
 667                       external_syntax_results->new_obj = generated_object;
 668                     }
 669                     
 670                     result_from_RIPupd = send_object_db(external_syntax_results->new_obj, NULL, "UPD");
 671                     if(result_from_RIPupd->result == 0){
 672                       AK_add_to_ack(ack_file_name, "\nUpdate OK: [%s] %s\n",
 673                                     o->type->getName(), get_search_key(o, o->type->getName(), arg));
 674                       arg2 = delete_override(arg);
 675                       NT_write_all_ntfs(old_version, arg2, NULL, tmpdir, ntfy_hash, forw_hash, cross_hash, 
 676                                         credentials.from);
 677                     }else{
 678                       AK_add_to_ack(ack_file_name, "\nUpdate FAILED: [%s] %s\n%s\n",
 679                       
 680                                     o->type->getName(), get_search_key(o, o->type->getName(), arg),
 681                                     result_from_RIPupd->error_str);
 682                     }
 683                     result_from_RIPupd->result = 0;
 684                   }else{
 685                     /* auth failed ! */
 686                     if(tracing) {
 687                       printf("TRACING: Auth failed\n");
 688                     }
 689       
 690                     AK_add_to_ack(ack_file_name, "\nUpdate FAILED: [%s] %s\nAuthorisation failed, request forwarded to maintainer.\n%s\n",
 691                                   o->type->getName(), get_search_key(o, o->type->getName(), arg), arg);
 692                     arg2 = delete_override(arg);
 693                     NT_write_all_frwds(old_version, arg2, tmpdir, ntfy_hash, forw_hash, cross_hash, credentials.from);
 694                     return UP_AUF; /* Auth failed */
 695                   }
 696 
 697                 }else{/* if the old and new versions of the object are the same */
 698                   if(tracing) {                                
 699                       printf("TRACING: The obj sent is identical to the one in the DB (NOOP)\n");
 700                   }
 701                   AK_add_to_ack(ack_file_name, "\nUpdate NOOP: [%s] %s\n",
 702                                     o->type->getName(), get_search_key(o, o->type->getName(), arg));
 703    
 704                 }
 705               }else{/* if there is an error in external syntax checks */
 706                 AK_add_to_ack(ack_file_name, "\nUpdate FAILED: [%s] %s\n%s%s\n",
 707                      o->type->getName(), get_search_key(o, o->type->getName(), arg), 
 708                      arg, external_syntax_results->error_str);
 709               }
 710 
 711             }else{/* if the user enforced creation (using NEW keyword) in the subject line */
 712 
 713               AK_add_to_ack(ack_file_name, "\nUpdate FAILED: [%s] %s\n%s\n"
 714                    "***ERROR:  Object already exists\n",
 715                    o->type->getName(), get_search_key(o, o->type->getName(), arg), 
 716                    arg);
 717               
 718             }
 719           }else { /* old_version  == NULL, so, creation */
 720             external_syntax_results = UP_check_external_syntax(o, arg);
 721             if(    external_syntax_results->result != UP_EXTSYN_ERR 
 722                 && external_syntax_results->result != UP_EXTSYN_ERR_WARN){/* if there is no error */
 723               result = check_auth(arg, NULL, o->type->getName(), credentials);
 724               if(result == UP_AUTH_OK){ 
 725                 if(tracing) {                                
 726                   printf("TRACING: Will send the obj to be added\n");
 727                 }
 728                  /* if the object is a key-cert object, then we must import the PGP key */
 729                 if(strcmp(type, "key-cert") == 0){
 730                   result_from_import_key = import_key(arg);
 731                 }else{
 732                   result_from_import_key = NULL;
 733                 }
 734                 if(result_from_import_key == NULL){/* no PGP problem */
 735                   if(strcmp(type, "key-cert") == 0){/* if the object is a key-cert object */
 736 
 737                     generated_object = UP_generate_kc_attrs(o, arg);
 738                     result_from_RIPupd = send_object_db(generated_object, NULL, "ADD");                     
 739                   }else{
 740                     
 741                     result_from_RIPupd = send_object_db(external_syntax_results->new_obj, NULL, "ADD");
 742 
 743                   }
 744                   if(result_from_RIPupd->result == 0){/* if there was no problem */
 745                     AK_add_to_ack(ack_file_name, "\nNew OK: [%s] %s\n",
 746                                   o->type->getName(), get_search_key(o, o->type->getName(), arg));
 747                     arg2 = delete_override(arg);
 748                     NT_write_all_ntfs(NULL, arg2, NULL, tmpdir, ntfy_hash, forw_hash, cross_hash, 
 749                                       credentials.from);
 750 
 751                   }else{
 752                     //AK_add_to_ack(ack_file_name, "\nNew FAILED: [%s] %s\nReferential integrity failure\n",
 753                     AK_add_to_ack(ack_file_name, "\nNew FAILED: [%s] %s\n%s\n",
 754                                   o->type->getName(), get_search_key(o, o->type->getName(), arg),
 755                                   result_from_RIPupd->error_str);
 756                   }
 757                   result_from_RIPupd = 0;
 758                 }else{/* there was a problem with PGP key import */
 759                   AK_add_to_ack(ack_file_name, "\nNew FAILED: [%s] %s\n%s\n",
 760                                   o->type->getName(), get_search_key(o, o->type->getName(), arg),
 761                                   result_from_import_key);
 762                 }
 763               }else if(result == UP_FWD){ /* this was a maintainer or as-block creation request, so
 764                                              forward it to <HUMAILBOX> */
 765 
 766                 if(tracing){
 767 
 768                   printf("TRACING: Maintainer or as-block request will be forwarded to <HUMAILBOX>\n");
 769                   
 770                 }
 771 
 772                 AK_add_to_ack(ack_file_name, "\nNew FAILED: [%s] %s\n%s\n"
 773                               "*ERROR*:     %s objects cannot be created automatically\n"
 774                               "*ERROR*:     This object has been forwarded to %s\n"
 775                               "*ERROR*:     for authorisation.\n"
 776                               "*ERROR*:     No further action from your part is required\n",
 777                               o->type->getName(), get_search_key(o, o->type->getName(), arg),
 778                               external_syntax_results->new_obj, o->type->getName(), humailbox);
 779 
 780                 /* and forward this creation request to <HUMAILBOX> */
 781                 NT_forw_create_req(external_syntax_results->new_obj);
 782                 
 783               }else if(result == UP_HOF){/* hierarchical authorisation failed */
 784                 if(tracing) {
 785                   printf("TRACING: Auth failed\n");
 786                 }
 787 
 788                 AK_add_to_ack(ack_file_name, "\nNew FAILED: [%s] %s\nHierarchical authorisation failed, request forwarded to maintainer.\n%s\n",
 789                               o->type->getName(), get_search_key(o, o->type->getName(), arg), arg);
 790                 arg2 = delete_override(arg);
 791                 NT_write_all_frwds(NULL, arg2, tmpdir, ntfy_hash, forw_hash, cross_hash, credentials.from);
 792                 return UP_AUF;
 793                 
 794                 
 795               }else{
 796                 /* auth failed ! */
 797                 if(tracing) {
 798                   printf("TRACING: Auth failed\n");
 799                 }
 800 
 801                 AK_add_to_ack(ack_file_name, "\nNew FAILED: [%s] %s\nAuthorisation failed, request forwarded to maintainer.\n%s\n",
 802                               o->type->getName(), get_search_key(o, o->type->getName(), arg), arg);
 803                 arg2 = delete_override(arg);
 804                 NT_write_all_frwds(NULL, arg2, tmpdir, ntfy_hash, forw_hash, cross_hash, credentials.from);
 805                 return UP_AUF; /* Auth failed */
 806               }
 807             }else{
 808               AK_add_to_ack(ack_file_name, "\nNew FAILED: [%s] %s\n%s%s\n",
 809                               o->type->getName(), get_search_key(o, o->type->getName(), arg), 
 810                               arg, external_syntax_results->error_str);
 811             }
 812           } 
 813         }
 814 
 815       }
 816     }else{/* even if obj doesn't parse properly, it may be a legacy object
 817             which the user wants to delete... */
 818        if(tracing){   
 819          printf("TRACING: Object didn't parse\n");   
 820        }
 821        /* if it is for deletion */
 822        if(o->isDeleted){
 823          /* here delete it */
 824          old_version = get_old_version(arg);
 825          if(old_version == NULL){ /* the object doesn't exist in the db! */
 826             AK_add_to_ack(ack_file_name, "\nDelete FAILED: [%s] %s\nEntry not found\n\n%s\n", 
 827                           o->type->getName(), get_search_key(o, o->type->getName(), arg), arg);
 828             return UP_NSO; /* no such object */
 829           }else {/* the object is in the db */
 830             if(identical(old_version, arg)){/* if the old & new versions are identical */
 831               result = check_auth(NULL, old_version, o->type->getName(), credentials);
 832               if(result == UP_AUTH_OK){ 
 833                 if(tracing) {
 834                   printf("TRACING: Will send the obj to be deleted\n");
 835                 }
 836                 if(strcmp(type, "key-cert") == 0){
 837                   result_from_delete_key = delete_key(arg);
 838                 }else{
 839                   result_from_delete_key = NULL;
 840                 }
 841                 /* if there was no problem with key deletion from the key-ring */
 842                 if(result_from_delete_key == NULL){
 843                   result_from_RIPupd = send_object_db(arg, NULL, "DEL");
 844                   if(result_from_RIPupd->result == 0){
 845                     AK_add_to_ack(ack_file_name, "\nDelete OK: [%s] %s\n", 
 846                                   o->type->getName(), get_search_key(o, o->type->getName(), arg));
 847                     NT_write_all_ntfs(arg, NULL, NULL, tmpdir, ntfy_hash, forw_hash, cross_hash, 
 848                                       credentials.from);
 849                   }else{
 850                     AK_add_to_ack(ack_file_name, "\nDelete FAILED: [%s] %s\n%s\n",
 851                                   o->type->getName(), get_search_key(o, o->type->getName(), arg),
 852                                   result_from_RIPupd->error_str);
 853                   }
 854                   result_from_RIPupd = 0;
 855                 }else{
 856                    AK_add_to_ack(ack_file_name, "\nDelete FAILED: [%s] %s\n%s\n",
 857                                   o->type->getName(), get_search_key(o, o->type->getName(), arg), result_from_delete_key);
 858                 }
 859               }else{ /* auth failed */
 860                 if(tracing) {
 861                   printf("TRACING: Auth failed\n");
 862                 }
 863 
 864                 AK_add_to_ack(ack_file_name, "\nDelete FAILED: [%s] %s\nAuthorisation failed, request forwarded to maintainer.\n%s\n",
 865                               o->type->getName(), get_search_key(o, o->type->getName(), arg), arg);
 866                 NT_write_all_frwds(arg, NULL, tmpdir, ntfy_hash, forw_hash, cross_hash, credentials.from);
 867                 return UP_AUF; /* Auth failed */
 868               } 
 869             }else{/* the new & old versions do not match */
 870               AK_add_to_ack(ack_file_name, "\nDelete FAILED: new & old versions do not match\n%s\n", arg);
 871               return UP_NOM; /* new & old versions do not match */
 872             }
 873           }
 874                
 875        }else{/* syntax error AND not deletion */
 876          AK_add_to_ack(ack_file_name, "\nUpdate FAILED: Syntax error in object\n");
 877        
 878          if(o->attrs.head() != NULL){
 879            for(attr = o->attrs.head(); attr; attr = o->attrs.next(attr)){
 880              if(attr->len > 0){
 881                value = (char*)malloc(attr->len);
 882                strncpy(value, (char *)(arg+attr->offset) ,
 883                  attr->len - 1);
 884                value[attr->len - 1] = '\0';
 885                AK_add_to_ack(ack_file_name, "%s\n", value);
 886                if(!attr->errors.empty()){
 887                  AK_add_to_ack_string(ack_file_name, attr->errors);
 888                }
 889                free(value);
 890              }else{
 891                if(!attr->errors.empty()){
 892                  AK_add_to_ack_string(ack_file_name, attr->errors);
 893                }
 894              }
 895            }
 896          }
 897          if(o->has_error){
 898            AK_add_to_ack_string(ack_file_name, o->errors);
 899          }
 900          AK_add_to_ack(ack_file_name, "\n");
 901        
 902          return UP_SYN; /* syntax error */
 903        }
 904     }
 905 }
 906 
 907 
 908 
 909 
 910 
 911 /* processes the objects in the given file */
 912 void process_file(char * filename, credentials_struct credentials, 
     /* [<][>][^][v][top][bottom][index][help] */
 913                   GHashTable * AUTO_NIC_hdl_hash, char * ack_file_name, 
 914                   GHashTable * ntfy_hash, GHashTable * forw_hash, GHashTable * cross_hash){
 915 
 916 FILE * input_file;
 917 GSList *list_of_objects = NULL, *list_of_objects2 = NULL;   
 918 GSList *next = NULL;
 919 int object_count = 0;
 920 char *object = NULL;
 921 char * line;
 922 char * lwrcase_line;
 923 int result = 0;
 924 struct VerifySignObject vSO, *pvSO;
 925 
 926 
 927   
 928     line = (char *)malloc(1024);
 929 
 930     if((input_file = fopen(filename, "r")) == NULL){
 931         ER_perror(FAC_UP, UP_CANTOPEN, "Couldn't open the file %s: %s\n", filename, strerror(errno));
 932         exit(1);  
 933     }
 934 
 935   
 936     while(fgets(line, 1023, input_file) != NULL){
 937       /* first, if it is a pasword, save it, but do not regard it as an attrib */ 
 938       lwrcase_line = strdup(line);
 939       g_strdown(lwrcase_line);
 940       if(strstr(lwrcase_line, "password:") == lwrcase_line){
 941         if(tracing){
 942           printf("TRACING: This is a password\n");
 943         }
 944         credentials.password_list = g_slist_append(credentials.password_list, 
 945                                       g_strstrip(strdup(line + strlen("password:"))));
 946         continue;
 947       }
 948       free(lwrcase_line);
 949       
 950       line = UP_remove_EOLs(line); /* remove '\n's and '\r' first */
 951       /* remove trailing white space */
 952       line = g_strchomp(line); 
 953       if(strlen(line) == 0){/* then, this was an empty line */
 954         if(object != NULL){
 955            list_of_objects = g_slist_append(list_of_objects, object);
 956            if(tracing){
 957              printf("TRACING: added an object: [%s]\n", object);
 958            }
 959            object = NULL;
 960         }
 961       }else{
 962         if(object == NULL && strlen(line) != 0){
 963           object = (char *)malloc(strlen(line) + 2);
 964           object = strcpy(object, line);
 965           object = strcat(object, "\n"); /* add EOL again (we removed it before) */
 966         }
 967         else{
 968           object = (char *)realloc(object, strlen(object) + strlen(line) + 2);
 969           object = strcat(object, line);
 970           object = strcat(object, "\n");
 971         }
 972       }
 973       
 974     }
 975     fclose(input_file);
 976 
 977     /* now, if at the very and of the input file there wasn't an 
 978        empty line, we have to add the remaining object in the 'object'
 979        variable */
 980     if(object != NULL){
 981        list_of_objects = g_slist_append(list_of_objects, object);
 982        object = NULL;
 983     }
 984 
 985 
 986 
 987     if(tracing) {
 988        printf("TRACING: Will process the objects in the list\n");
 989     }
 990     next = list_of_objects;
 991     object_count = 0;
 992     for( next = list_of_objects; next != NULL ; next = g_slist_next(next) ){
 993       object_count++;
 994 
 995       if(tracing) {
 996         cout << "TRACING: Got an object from the list" << endl;
 997         cout << (char *)next->data << endl;
 998       }
 999       
1000       if(has_ref_to_AUTO_nic_hdl((char *)next->data)){/* defer the processing */
1001         if(tracing) {
1002           printf("TRACING: this object has a ref to an AUTO NIC hdl\n");
1003         }
1004         list_of_objects2 = g_slist_append(list_of_objects2, strdup((char *)next->data));
1005       }else{
1006         result = 0;
1007         result = process_object((char *)next->data, credentials, AUTO_NIC_hdl_hash, ack_file_name, 
1008                                  ntfy_hash, forw_hash, cross_hash);
1009       }
1010     }
1011 
1012     if(tracing) {
1013       printf("TRACING: list_of_objects2 has %d entries\n", g_slist_length(list_of_objects2));
1014     }
1015   
1016     if(tracing) {
1017       printf("TRACING: will start to process the second list\n");
1018     }
1019   
1020     for( next = list_of_objects2; next != NULL ; next = g_slist_next(next) ){
1021       if(tracing) {
1022         printf("TRACING: Will process object: %s\n", (char *)next->data);
1023       }
1024       result = process_object((char *)next->data, credentials, AUTO_NIC_hdl_hash, ack_file_name, 
1025                                ntfy_hash, forw_hash, cross_hash);
1026     }
1027   
1028 }/* process_file */
1029 
1030 
1031 
1032 
1033 
1034 
1035 /*  Generates a unique file name and returns the full path of the filename 
1036     for storing notification message.  */
1037       
1038 char * generate_upd_file(){
     /* [<][>][^][v][top][bottom][index][help] */
1039 
1040    char * name;
1041      
1042    /* allocate space for name.  32 should be enough for PID */
1043    name = (char*)malloc(strlen(tmpdir) + strlen("/dbupdate-tmp.") + 32 ); 
1044    
1045    sprintf(name, "%s/dbupdate-tmp.%i", tmpdir, pid /*getpid()*/);
1046 
1047      
1048    return name;
1049       
1050 }
1051 
1052 
1053 /* create_lock_file: creates a lock file in lockdir and locks it. This is a 
1054    part of crash recovery. Must be called in the beginning of the run. At the
1055    end, the file must be removed. */
1056 /* The idea: Create the "lock" file, and lock it. When another process starts
1057    running, it checks the existing lock files. If some exists, then it checks
1058    if it is locked or not. It not locked, then assumes that the corresponding
1059    dbupdate is alredy running. If not locked, assumes that it has crashed. 
1060    (note: when a process crashes, the kernel releases all the files locked by
1061    this process [by the OS]) 
1062    Problem: locking doesn't work properly on some NFS implementations. */
1063 
1064 lockfilestruct create_lock_file(){
     /* [<][>][^][v][top][bottom][index][help] */
1065   
1066   lockfilestruct lock;
1067   int file;
1068   int length;
1069 
1070   /* allocate space for file name */
1071   length = strlen(lockdir) +  strlen(hostname) + 32;
1072   lock.lockname = (char *)malloc(length + 1);
1073 
1074   snprintf(lock.lockname, length, "%s/dbupdate.%s.%ld", lockdir, hostname, pid /*getpid()*/);
1075 
1076   /* we will lock the file, so we have to use open(), but not fopen() (see man 
1077      page of lockf(3C)) */
1078   if(( file = open(lock.lockname, O_RDWR|O_CREAT)) == -1){
1079     ER_perror(FAC_UP, UP_CANTOPEN, "Can't open lock file, %s", lock.lockname);
1080     exit(1);
1081   }
1082  
1083   if(lockf(file, F_LOCK, 0) == -1){
1084     ER_perror(FAC_UP, UP_CANTLOCK, "Can't lock the file, %s", lock.lockname);
1085     exit(1);
1086   }; 
1087 
1088   lock.filedes = file;
1089 
1090   return lock;
1091 
1092 }
1093 
1094 
1095 
1096 
1097 
1098 /* remove_lock_file(): unlocks and removes the file  */
1099 void remove_lock_file(lockfilestruct lockfile){
     /* [<][>][^][v][top][bottom][index][help] */
1100 
1101   close(lockfile.filedes); /* this will remove the lock at the same time */ 
1102   unlink(lockfile.lockname);
1103 
1104 }
1105 
1106 
1107 
1108 /* writes the checkpoint file with the specified state */
1109 void write_checkpoint(int state){
     /* [<][>][^][v][top][bottom][index][help] */
1110 
1111   char * filename;
1112   char * tmpfilename;
1113   int length;
1114   FILE * file;
1115 
1116   if(tracing){
1117     printf("TRACING: write_checkpoint, state=[%i]\n", state); 
1118   }
1119   length = strlen(lockdir) +  strlen(hostname) + 64;
1120   filename    = (char *)malloc(length + 1);
1121   tmpfilename = (char *)malloc(length + 5);
1122  
1123   snprintf(filename,    length, "%s/dbupdate.checkpoint.%s.%ld",     lockdir, hostname, pid );
1124   snprintf(tmpfilename, length, "%s/dbupdate.checkpoint.%s.%ld.tmp", lockdir, hostname, pid );
1125 
1126   if(( file = fopen(tmpfilename, "w")) == NULL){
1127     //fprintf(stderr, "Can't open temp checkpoint file, %s", tmpfilename);
1128     ER_perror(FAC_UP, UP_CANTOPEN, "Can't open temp checkpoint file, %s", tmpfilename);
1129     exit(1);
1130   }
1131 
1132   fprintf(file, "[STATE]\n%i\n", state);
1133 
1134   fprintf(file, "[FLAGS]\n");
1135   /* should print the flags here */
1136   
1137   fprintf(file, "[PARTS]\n");
1138   /* should print the parts (filenames) here */
1139 
1140   fprintf(file, "[OBJECTS1]\n");
1141 
1142   fprintf(file, "[OBJECTS2]\n");
1143 
1144   fprintf(file, "[ACKFILE]\n");
1145   
1146   fprintf(file, "[NOTIFFILES]\n");
1147 
1148   fprintf(file, "[TIDS1]\n");
1149   
1150   fprintf(file, "[TIDS2]\n");
1151 
1152   fprintf(file, "[NICHDLHASH]\n");
1153 
1154   fprintf(file, "[CURRENTOBJECT]\n");
1155 
1156   fprintf(file, "[CURRENTPART]\n");
1157 
1158   
1159   fclose(file);
1160 
1161   rename(tmpfilename, filename);
1162 
1163   /* free the char *'s */
1164   free(tmpfilename);
1165   free(filename);
1166 
1167 }
1168 
1169 
1170 
1171 
1172 /* removes check point file */
1173 void remove_checkpoint(){
     /* [<][>][^][v][top][bottom][index][help] */
1174 
1175   char * filename;
1176   int length;
1177   FILE * file;
1178 
1179   if(tracing){
1180     printf("TRACING: remove_checkpoint\n"); 
1181   }
1182   
1183   length = strlen(lockdir) +  strlen(hostname) + 64;
1184   filename    = (char *)malloc(length + 1);
1185  
1186   snprintf(filename,    length, "%s/dbupdate.checkpoint.%s.%ld",     lockdir, hostname, pid );
1187 
1188   unlink(filename);
1189  
1190   /* free the char * */
1191   free(filename);
1192 
1193 }
1194 
1195 
1196 
1197 
1198 
1199 
1200 
1201 /* main */
1202 void main(int argc, char **argv, char **envp){
     /* [<][>][^][v][top][bottom][index][help] */
1203   //init_and_set_options(argc, argv, envp);
1204 
1205   int count = 0;
1206   int i,j;
1207   int no_of_updateables = 0;
1208   char ** temp_vector;
1209   char * temp;
1210   char * temp_upd_file = NULL;
1211   char *input_file_name = NULL;
1212   GHashTable *AUTO_NIC_hdl_hash;
1213   credentials_struct credentials;
1214   FILE * upd_file;
1215   char c;
1216   char * mheader_replaced = NULL;
1217   char * mailtxt_replaced = NULL;
1218 
1219   /* temp variables to read from conf */
1220   char * source = NULL, * canupd = NULL;
1221   ca_dbSource_t *source_hdl;
1222   ca_updDbSource_t *upd_source_hdl;
1223 
1224   GHashTable *ntfy_hash, *forw_hash, *cross_hash;
1225   
1226 
1227   char *mail_command_line, * ack_file_name;
1228   char *config_file_name = NULL;
1229   
1230 
1231 
1232   /* to use EP module */
1233   EP_Mail_DescrPtr p; 
1234   EPTokenPtr pt;
1235   EPTokenPtr list_item;
1236   EPTokenKeysPtr ptk;
1237 
1238   char * temp_keyid;
1239 
1240   /* a variable to be used to know if the part is pgp_signed or not */
1241   int pgp_signed = 0;
1242 
1243   long debug = 0;
1244     
1245   /* optarg & optind are necessary to use getopt(3C) */ 
1246   extern char *optarg;
1247   extern int optind;
1248 
1249 
1250   /* create notification hashes */
1251   ntfy_hash = g_hash_table_new(g_str_hash, g_str_equal);
1252   forw_hash = g_hash_table_new(g_str_hash, g_str_equal);
1253   cross_hash = g_hash_table_new(g_str_hash, g_str_equal);
1254       
1255   credentials.password_list = NULL;
1256   credentials.from = NULL;
1257   int ch;
1258   char * to_address = NULL;
1259   char * subject = NULL;
1260   char * reply_to = NULL;
1261 
1262   AUTO_NIC_hdl_hash = g_hash_table_new(g_str_hash, g_str_equal);       
1263   
1264       
1265               
1266 
1267   while ((ch = getopt(argc, argv, "MtSTf:c:sn")) != -1){
1268           switch(ch) {
1269           case 'M':
1270                   reading_from_mail = 1;
1271                   break;
1272           case 'f':
1273                   input_file_name = strdup(optarg);
1274                   break;
1275           case 'c':
1276                   config_file_name = strdup(optarg);
1277                   break;
1278           case 't': 
1279                   tracing = 1;
1280                   break;
1281           /* Test mode? In test mode, creation of mntners and as-blocks is possible, without overriding */        
1282           case 'T':
1283                   test_mode = 1; 
1284                   break;
1285           /* Supress acks and notifications? If yes, the acks and notifs will go to DEFMAIL config var */        
1286           case 'S': 
1287                   supress_ack_notif = 1;
1288                   break;
1289           /* Print out the ack to stdout? */        
1290           case 's':
1291                   print_out_ack = 1;
1292                   break;
1293           /* are we processing networkupdate? (invoked via inetd) */        
1294           case 'n':
1295                   networkupdate = 1;
1296                   break;
1297           case '?':
1298           default:
1299                   printf("Unknown option\n"); exit(1);
1300           }
1301   }
1302 
1303 
1304   /* config stuff */
1305   /* if -c flag is given, use the named file as config file, otherwise use
1306      default filename */ 
1307   if( config_file_name != NULL){
1308     /*ca_readConfig(config_file_name, confVars, VARS);*/
1309     ca_init(config_file_name);
1310   }else{
1311     /*ca_readConfig("dbupdate.conf", confVars, VARS);*/
1312     ca_init("dbupdate.conf");
1313   }
1314 
1315   error_init(argc, argv);
1316 
1317 
1318   tmpdir = ca_get_tmpdir;
1319   tmpdir = g_strstrip(tmpdir);
1320   lockdir = ca_get_lockdir;
1321   mailcmd = ca_get_mailcmd;
1322   mailcmd = g_strstrip(mailcmd);
1323   notitxt = ca_get_notitxt;
1324   mailtxt = ca_get_mailtxt; 
1325   defmail = ca_get_defmail; defmail = UP_remove_EOLs(defmail);
1326   crosslog = ca_get_crosslog;
1327   fwtxt = ca_get_fwtxt;
1328   acksig = ca_get_acksig;
1329   humailbox = ca_get_humailbox;
1330   humailbox = g_strstrip(humailbox);
1331   autobox = ca_get_autobox;
1332   overridecryptedpw = ca_get_overridecryptedpw;
1333   overridecryptedpw = g_strstrip(overridecryptedpw);
1334   updlog = ca_get_updlog;
1335   acklog = ca_get_acklog;
1336   notiflog = ca_get_notiflog;
1337   notimailtxt = ca_get_notimailtxt;  
1338   notinetworktxt = ca_get_notinetworktxt;
1339   forwlog = ca_get_forwlog;
1340   fwmailtxt = ca_get_fwmailtxt;
1341   mtfwheader = ca_get_mtfwheader;
1342   mtfwtxt = ca_get_mtfwtxt;
1343   country = ca_get_country;
1344   pgppath = ca_get_pgppath;
1345   gpgcmd = ca_get_gpgcmd;
1346   autodbmhelp = ca_get_autodbmhelp;
1347   cn_subject_add = ca_get_cn_subject_add; cn_subject_add = UP_remove_EOLs(cn_subject_add);
1348   cn_subject_del = ca_get_cn_subject_del; cn_subject_del = UP_remove_EOLs(cn_subject_del);
1349   cn_explain_add = ca_get_cn_explain_add;
1350   cn_explain_del = ca_get_cn_explain_del;
1351   cn_overlap_add = ca_get_cn_overlap_add;
1352   cn_overlap_del = ca_get_cn_overlap_del;
1353   cno_subject_add = ca_get_cno_subject_add; cno_subject_add = UP_remove_EOLs(cno_subject_add); 
1354   cno_subject_del = ca_get_cno_subject_del; cno_subject_del = UP_remove_EOLs(cno_subject_del);
1355   cno_explain_add = ca_get_cno_explain_add;
1356   cno_explain_del = ca_get_cno_explain_del;
1357   cno_overlap_add = ca_get_cno_overlap_add;
1358   cno_overlap_del = ca_get_cno_overlap_del;
1359   copyright_notice = ca_get_pw_resp_header;
1360   mheader = ca_get_mheader;
1361   pgp_public_key_ring = (char *)malloc(strlen(pgppath) + strlen("/pubring.gpg") + 2);
1362   sprintf(pgp_public_key_ring ,"%s/pubring.gpg", pgppath);
1363   if(test_mode != 1){/* if it is not already set to 1 (from command line), read from config */
1364     
1365     test_mode = ca_get_testmode;
1366   }
1367   /* retrieve source variables */
1368   upd_source_hdl = ca_get_UpdSourceHandle(CA_UPDSOURCE);
1369 
1370   if(upd_source_hdl == NULL){
1371     printf("There must be one updateable source in the config file. Exiting.\n");
1372     ER_perror(FAC_UP, UP_CONFERR, "There must be one updateable source in"
1373                                   " the config file. Exiting.");
1374     exit(1);
1375   }else{
1376     if(tracing){
1377       printf("\nTRACING: The upd_source_hdl is: %s\n", upd_source_hdl->name);
1378     }
1379     sources[0] = strdup(upd_source_hdl->name);
1380     update_host = upd_source_hdl->whoisd_host;
1381     query_host = strdup(update_host);
1382     update_port = upd_source_hdl->updPort;
1383     query_port = upd_source_hdl->qryPort;
1384     DBhost = upd_source_hdl->updDb.host;
1385     DBport = upd_source_hdl->updDb.port;
1386     DBname = upd_source_hdl->updDb.dbName;
1387     DBuser = upd_source_hdl->updDb.user;
1388     DBpasswd = upd_source_hdl->updDb.password; 
1389   }
1390 
1391   
1392 
1393   /* construct country array from country string variable */
1394   
1395   temp_vector = g_strsplit(country, "\n", 0);
1396   for(i=0, j=0; temp_vector[i] != NULL; i++){
1397     temp_vector[i] == g_strstrip(temp_vector[i]);
1398     if(strlen(temp_vector[i]) > 0){
1399       countries[j] = strdup(temp_vector[i]);
1400       g_strup(countries[j]);
1401       j++;
1402     }
1403   }
1404   countries[j] = NULL; /* mark the end of array */
1405   
1406   if(tracing){
1407     /* print out the config variables for debugging */
1408     printf("TRACING: countries[%i] = NULL\n", j);
1409  
1410     printf("TMPDIR is: [%s]\n", tmpdir);
1411     printf("MAILCMD is: [%s]\n", mailcmd);
1412     printf("NOTITXT is: [%s]\n", notitxt);
1413     printf("CROSSLOG is: [%s]\n", crosslog);
1414     printf("FWTXT is: [%s]\n", fwtxt);
1415     printf("HUMAILBOX is: [%s]\n", humailbox);
1416     printf("AUTOBOX is: [%s]\n", autobox);
1417     printf("OVERRIDECRYPTEDPW is: [%s]\n", overridecryptedpw);
1418     printf("ACKLOG is: [%s]\n", acklog);
1419     printf("NOTIFLOG is: [%s]\n", notiflog);
1420     printf("FORWLOG is: [%s]\n", forwlog);
1421     printf("NOTIMAILTXT is: [%s]\n", notimailtxt);
1422     printf("FWMAILTXT is: [%s]\n", fwmailtxt);
1423     printf("COUNTRY is: [%s]\n", country);
1424     printf("PGPPATH is: [%s]\n", pgppath);
1425     printf("UPDATE_HOST is: [%s]\n", update_host);
1426     printf("UPDATE_PORT is: [%i]\n", update_port);
1427     printf("QUERY_HOST is: [%s]\n",  query_host);
1428     printf("QUERY_PORT is: [%i]\n",  query_port);   
1429     printf("LOCKDIR is: [%s]\n", lockdir); 
1430     printf("TESTMODE is: [%i]\n", test_mode);
1431     printf("CNO_SUBJECT_ADD is: [%s]\n", cno_subject_add);
1432     printf("CNO_SUBJECT_DEL is: [%s]\n", cno_subject_del);
1433   }
1434   /* end of config stuff */
1435 
1436 
1437   /* set hostname global variable */
1438   gethostname(hostname, MAXHOSTNAMELEN);
1439 
1440   /* set pid global variable */
1441   pid = getpid(); 
1442 
1443   /* create the lock file and lock it */
1444   //lockfile = create_lock_file();
1445 
1446     
1447   /* initialize the parser */
1448   schema.initialize();
1449 
1450 
1451   /* Generate a name for temporary file for storing acks (AK_ack_file_name_generate
1452       also creates it) */
1453   ack_file_name = AK_ack_file_name_generate(tmpdir, ACK_FILE_PREFIX);
1454 
1455   /* initialize credentials.pgp_key_list */
1456   credentials.pgp_key_list = NULL;
1457 
1458 
1459   
1460  
1461   if(reading_from_mail){
1462     if(input_file_name != NULL){
1463       temp_upd_file = generate_upd_file();
1464       if(tracing){
1465         printf("TRACING: temp_upd_file is [%s]\n", temp_upd_file);
1466       }
1467 
1468       /* first log the input in the upd log file */
1469       UP_add_to_upd_log(input_file_name);
1470  
1471       
1472       MM_store(input_file_name, temp_upd_file, 0);
1473       p = EP_ParseMail(input_file_name, tmpdir, pgp_public_key_ring, gpgcmd);
1474       
1475     }else{/* input_file_name == NULL */
1476       temp_upd_file = generate_upd_file();
1477       MM_store("-", temp_upd_file, 0);
1478 
1479       /* first log the input in the upd log file */
1480       UP_add_to_upd_log(temp_upd_file);
1481       
1482       p = EP_ParseMail(temp_upd_file, tmpdir, pgp_public_key_ring, gpgcmd);
1483 
1484     }
1485 
1486     /* write off the checkpoint file */
1487     write_checkpoint(1);
1488 
1489     /* the new stuff using the EP module's interface */
1490     if(tracing){
1491       printf("\nTRACING: From field is: [%s]\n", p->from->field);
1492     }
1493 
1494     temp = (char *)malloc(strlen(p->from->field) + strlen("From: ") + 1);
1495     sprintf(temp, "From: %s", p->from->field);
1496     /* cut off the '\n's and '\r's at the end of temp */
1497     UP_remove_EOLs(temp);
1498     
1499     credentials.from = temp;
1500     credentials.from_email = strdup(p->from->field);
1501 
1502     update_mail_sender = strdup(p->from->field); 
1503     update_mail_sender = UP_remove_EOLs(update_mail_sender);
1504                
1505     if(p->subject != NULL && p->subject->field != NULL){
1506       subject = strdup(p->subject->field);
1507     }else{
1508       subject = strdup("");
1509     }
1510     
1511     /* cut off the '\n' and '\r' from the end */
1512     UP_remove_EOLs(subject);
1513     
1514     update_mail_subject = strdup(subject);
1515 
1516     /* parse the subject line */ 
1517     subject_result = UP_subject_process(update_mail_subject); 
1518 
1519 
1520     if(p->reply_to != NULL && p->reply_to->field != NULL){
1521       reply_to = strdup(p->reply_to->field);
1522     }else{
1523       reply_to = strdup("");
1524     }
1525 
1526     
1527     /* cut off the '\n' and '\r' from the end */                    
1528     UP_remove_EOLs(reply_to);
1529 
1530     
1531 
1532     to_address = find_email_address(credentials.from);
1533 
1534     /* if Reply_To was available in the incoming header, then use it */
1535     if(strlen(reply_to) > 0){
1536       to_address = (char *)realloc(to_address, strlen(reply_to) + 1);
1537       to_address = strcpy(to_address, reply_to);
1538       to_address = find_email_address(to_address); /* so that we take only the email address */
1539     }
1540 
1541     if(p->message_id != NULL && p->message_id->field != NULL){
1542       update_mail_ID = strdup(p->message_id->field);
1543     }else{
1544       update_mail_ID = strdup("");
1545     }
1546 
1547     /* cut off the '\n' and '\r' from the end */
1548     UP_remove_EOLs(update_mail_ID);
1549     
1550 
1551     if(p->date != NULL && p->date->field != NULL){
1552       update_mail_date = strdup(p->date->field);
1553     }else{
1554       update_mail_date = strdup("");
1555     }
1556 
1557     /* cut off the '\n' and '\r' from the end  */
1558     UP_remove_EOLs(update_mail_date);
1559 
1560     
1561     if(tracing){
1562       printf("\nEP_ShowTree outputs:\n");
1563       EP_ShowTree(p->tree);
1564     }
1565     
1566     pt = EP_GetTokens(p->tree, NULL, NULL);
1567 
1568     if(tracing){
1569       /* Print the list out (debugging) */
1570       printf("\nEP_PrintTokens outputs:\n");
1571       EP_PrintTokens(pt);
1572     }
1573 
1574     /* replace the global variables in mheader */
1575     mheader_replaced = UP_replace_globals(mheader);
1576     /* replace the global variables in mailtxt */
1577     mailtxt_replaced = UP_replace_globals(mailtxt);
1578 
1579     /* If this wasn't only a help request, then we need to process the input */
1580     if(subject_result.result != UP_SUBJ_HELP_REQ){
1581       
1582       /* Print out the header of the ackonwledgement */
1583       AK_add_to_ack(ack_file_name, "To: %s\n%s\n\nAcknowledgement message from"
1584         " database software\n\n%s\n", to_address, mheader_replaced, mailtxt_replaced);
1585 
1586       /* ... and now process the items in the list */
1587       list_item = pt;
1588       while (list_item != NULL) {
1589         if(tracing){
1590           printf("\n\nWill process: %s, MIMEtype: %d\n", list_item->file, list_item->MIMEContentType);
1591         }
1592         /* initialize pgp_key_list (XXX This should be a proper freeing of the list) */
1593         credentials.pgp_key_list = NULL;
1594         ptk = list_item->keys;
1595         if(ptk != NULL){
1596           AK_add_to_ack(ack_file_name, "==== BEGIN PGP SIGNED PART (keyID(s):");
1597           pgp_signed = 1; 
1598           while (ptk != NULL) {
1599             if(tracing){
1600               printf("TRACING:     key: %.8X, isValid: %i\n", 
1601                    ptk->keyID, ptk->isValidPGPSignature);
1602             }
1603             temp_keyid = (char *)malloc(10);
1604             sprintf(temp_keyid, "%.8X", ptk->keyID);
1605             if(tracing){
1606               printf("TRACING: This key will be added to the list: [%s]\n", temp_keyid);
1607             }
1608             AK_add_to_ack(ack_file_name, " %s", temp_keyid);
1609             credentials.pgp_key_list = g_slist_append (credentials.pgp_key_list, temp_keyid);
1610             ptk = ptk->next;
1611             if(ptk != NULL){
1612               AK_add_to_ack(ack_file_name, ",");
1613             }else{
1614               AK_add_to_ack(ack_file_name, ") ====\n");
1615             }
1616           }
1617         }
1618         process_file(list_item->file, credentials, 
1619                      AUTO_NIC_hdl_hash, ack_file_name, 
1620                      ntfy_hash, forw_hash, cross_hash);
1621         if(pgp_signed){
1622           AK_add_to_ack(ack_file_name, "==== END PGP SIGNED PART ====\n\n");
1623           pgp_signed = 0;
1624         }
1625         list_item = list_item->next;
1626       }
1627 
1628     }else{/* this was only a help request (inferred from the "Subject" line of the upd message) */
1629 
1630       /* Print out the header of the acknowledgement */
1631       AK_add_to_ack(ack_file_name, "To: %s\n%s\n\nHelp file requested so body of message ignored.\n\n\n"
1632           "============================================================\n\n", 
1633           to_address, mheader_replaced);
1634 
1635       AK_add_file_to_ack(ack_file_name, autodbmhelp);
1636       AK_add_to_ack(ack_file_name, "\n============================================================");
1637        
1638     }
1639     
1640     EP_CleanTokens(pt);
1641 
1642     EP_MailDescrCleanUp(p);
1643 
1644     /* if we have created a temporary file for update, delete it */
1645     if(temp_upd_file != NULL){
1646 
1647       unlink(temp_upd_file);
1648       
1649     }
1650 
1651   }else if(networkupdate){
1652 
1653     /* process networkupdate. Since we use inetd, we just process stdin */
1654     process_networkupdate(credentials, AUTO_NIC_hdl_hash, ack_file_name, 
1655                           ntfy_hash, forw_hash, cross_hash); 
1656 
1657   }else{/* not reading from the mail message or from network */
1658     if(input_file_name != NULL){
1659 
1660       /* first log the input in the upd log file */
1661       UP_add_to_upd_log(input_file_name);
1662 
1663       
1664       write_checkpoint(1);
1665       process_file(input_file_name, credentials, 
1666                   AUTO_NIC_hdl_hash, ack_file_name, 
1667                   ntfy_hash, forw_hash, cross_hash);
1668     }else{/* the filename is not given, so we have to write 
1669              stdin to a temp file, and give it to process_file */
1670        temp_upd_file = generate_upd_file();
1671        if(tracing){
1672          printf("TRACING: main: temp_upd_file=%s\n", temp_upd_file);
1673        }
1674        if(( upd_file = fopen(temp_upd_file, "a")) == NULL){
1675          ER_perror(FAC_UP, UP_CANTOPENW, "Can't open ack file, %s", temp_upd_file);
1676        }
1677 
1678        while((c = getchar()) != EOF){
1679          fprintf(upd_file, "%c",c);
1680        }
1681        fclose(upd_file);
1682 
1683        write_checkpoint(1);
1684        process_file(temp_upd_file, credentials, 
1685                   AUTO_NIC_hdl_hash, ack_file_name, 
1686                   ntfy_hash, forw_hash, cross_hash);
1687        unlink(temp_upd_file);
1688         
1689     }
1690       
1691   }  
1692 
1693 
1694   /* send the ack */
1695   if(reading_from_mail && to_address != NULL){
1696     AK_send_ack(ack_file_name, to_address, mailcmd);
1697   }
1698 
1699   /* if our update wasn't a mail update OR we have been asked explicitely
1700      to print out the ack to the stdout, print it */
1701   if(!reading_from_mail || print_out_ack){
1702     AK_print_ack(ack_file_name);
1703   }
1704   
1705   AK_log_ack(ack_file_name, acklog);
1706   AK_delete_ack(ack_file_name);
1707 
1708   NT_send_ntfy_list(ntfy_hash, mailcmd);
1709   NT_log_ntfy_list(ntfy_hash, notiflog); 
1710   NT_delete_ntfy_list(ntfy_hash);
1711 
1712   NT_send_ntfy_list(forw_hash, mailcmd);
1713   NT_log_ntfy_list(forw_hash, forwlog); 
1714   NT_delete_ntfy_list(forw_hash);
1715 
1716 
1717   NT_send_ntfy_list(cross_hash, mailcmd);
1718   NT_log_ntfy_list(cross_hash, crosslog); 
1719   NT_delete_ntfy_list(cross_hash);
1720       
1721   /* remove the lock file */
1722   //remove_lock_file(lockfile);
1723   
1724  
1725   /* remove checkpoint file */
1726   remove_checkpoint();
1727 
1728      
1729   if(tracing) {
1730     printf("TRACING: END\n");
1731   }
1732 
1733 
1734 }

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