## 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] */