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