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