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