bin/dbupdate/dbupdate.cc
/* [<][>][^][v][top][bottom][index][help] */
FUNCTIONS
This source file includes following functions.
- error_init
- delete_key
- import_key
- process_object
- process_file
- generate_upd_file
- create_lock_file
- remove_lock_file
- write_checkpoint
- remove_checkpoint
- 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 }