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. process_object
  5. process_file
  6. generate_upd_file
  7. create_lock_file
  8. remove_lock_file
  9. write_checkpoint
  10. remove_checkpoint
  11. main

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

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