bin/dbupdate/dbupdate.cc
/* [<][>][^][v][top][bottom][index][help] */
FUNCTIONS
This source file includes following functions.
- error_init
- delete_key
- import_key
- process_object
- scan_for_PGP
- process_file
- generate_upd_file
- main
1 /***************************************
2 $Revision: 1.30 $
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 "erroutines.h"
40 #include "ca_configFns.h"
41 #include "ca_dictSyms.h"
42 #include "ca_macros.h"
43 #include "ca_srcAttribs.h"
44 #include "notification.h"
45 #include "gpg.h"
46
47 int tracing = 0;
48 int test_mode = 0;
49 int reading_from_mail = 0;
50
51 /* required configuration variables */
52 char *tmpdir = NULL;
53 char *mailcmd = NULL;
54 char *notitxt = NULL;
55 char *notimailtxt = NULL;
56 char *fwtxt = NULL;
57 char *fwmailtxt = NULL;
58 char *mailtxt = NULL;
59 char *notiflog = NULL;
60 char *crosslog = NULL;
61 char *acklog = NULL;
62 char *forwlog = NULL;
63 char *humailbox = NULL;
64 char *overridecryptedpw = NULL;
65 char *country = NULL;
66 char *countries[400];
67 char *sources[100];
68 char *pgppath = NULL;
69 char *pgp_public_key_ring = NULL;
70 char *update_host = NULL;
71 int update_port;
72 char *query_host = NULL;
73 int query_port;
74
75 /* end of config variables */
76
77 void error_init(int argc, char ** argv) {
/* [<][>][^][v][top][bottom][index][help] */
78 er_path_t erlogstr;
79
80 ER_init(argc, argv);
81
82 erlogstr.fdes = stderr;
83 erlogstr.asp = 0;
84 erlogstr.sev = ER_SEV_W;
85 erlogstr.mode = ER_M_SEVCHAR | ER_M_TEXTLONG;
86
87 ER_setpath(& erlogstr);
88
89 } /* error_init() */
90
91
92
93 /* Deletes the key defined in the incoming object (a key-cert object)
94 from the public keyring. Returns NULL if there was no error,
95 returns an error message if there is an error */
96 char * delete_key(char * obj){
/* [<][>][^][v][top][bottom][index][help] */
97
98 struct ImportKeyObject iKO;
99 char * obj_keyID;
100 char * key_cert_attr;
101 GSList * templist, * certiflist, * next;
102 u32 keyID;
103 char * tempfile;
104 char ** lines;
105 int i;
106 FILE * key_file;
107 char * temp, * temp2;
108 char * error_string;
109
110 templist = get_attr_list(obj, "key-cert");
111 key_cert_attr = strdup((char *)templist->data);
112 g_slist_free(templist);
113
114 tempfile = (char *)malloc(strlen(tmpdir) + strlen("tmp-key.") + 32);
115 sprintf(tempfile, "%s/tmp-key.%i", tmpdir, getpid());
116 printf("DEBUG: tempfile=%s\n", tempfile);
117
118 /* now we must write certif attribute(s) of this key-certif into the tempfile */
119 /* get the certif first */
120 certiflist = get_attr_list(obj, "certif");
121 if(( key_file = fopen(tempfile, "w")) == NULL){
122 fprintf(stderr, "Can't open temporary file, %s", tempfile);
123 exit(1);
124 }
125 for( next = certiflist; next != NULL ; next = g_slist_next(next) ){
126 lines = g_strsplit((char *)next->data, "\n", 0);
127 //printf("DEBUG: attr: %s\n", (char *)next->data);
128 if(lines[0] == NULL){/* if this was an empty attribute, just print an empty line */
129 fprintf(key_file, "\n");
130 }
131 for(i = 0; lines[i] != NULL; i++){
132 //printf("DEBUG: i=%i\n", i);
133 temp = strdup(lines[i]);
134 if(i != 0 && temp[0] == '+'){/* if it begins with a plus */
135 temp2 = strdup(temp + 1);
136 g_strstrip(temp2);
137 fprintf(key_file, "%s\n", temp2);
138 free(temp);free(temp2);
139 }else{
140 g_strstrip(temp);
141 fprintf(key_file, "%s\n", temp);
142 free(temp);
143 }
144 }
145 g_strfreev(lines);
146 //fprintf(key_file, "%s\n", (char *)next->data);
147 }
148 fclose(key_file);
149 g_slist_free(certiflist);
150
151 strcpy(iKO.iFilename, tempfile);
152
153 printf("DEBUG: delete_key: key_cert_attr: [%s]\n", key_cert_attr);
154 obj_keyID = strdup(key_cert_attr + strlen("PGPKEY-"));
155 printf("DEBUG: delete_key: obj_keyID: [%s]\n", obj_keyID);
156 keyID = strtoul(obj_keyID, NULL, 16);
157 printf("DEBUG: delete_key: keyID is: %u, %X\n", keyID, keyID);
158
159
160
161 strcpy(iKO.keyRing, pgp_public_key_ring);
162 //iKO.keyID = keyID;
163 PA_RemoveKey(&iKO);
164 printf("DEBUG: importKeyObj status:\n");
165 printf("DEBUG: isValid: %d\n", iKO.rc);
166
167
168
169 unlink(tempfile);
170 if(iKO.rc == iKO_OK){/* if PA_RemoveKey returned OK */
171 return NULL;
172 }else{/* if PA_RemoveKey returned not OK */
173 switch(iKO.rc){
174 case iKO_UNCHANGED: error_string = strdup("the key is already in the keyring");break;
175 case iKO_NOUSERID: error_string = strdup("no user ID could be extracted");break;
176 case iKO_GENERAL: error_string = strdup("general PGP error");break;
177 case iKO_NOTVALIDUSERID: error_string = strdup("no valid user ID ");break;
178 case iKO_NOPUBLICKEY: error_string = strdup("no public key in the object");break;
179 case iKO_NODEFAULTPUBLICKEYRING: error_string = strdup("general PGP error");break;
180 case iKO_CRC_ERROR: error_string = strdup("CRC error in the certificate");break;
181 case iKO_NO_OPENPGP_DATA:error_string = strdup("no OpenPGP data in the object");break;
182 case iKO_NO_IN_FILES: error_string = strdup("general PGP error");break;
183 case iKO_GENERALFAILURE: error_string = strdup("general PGP error");break;
184 default: error_string = strdup("general PGP error");
185 }
186 return error_string;
187 }
188
189 return NULL;
190 }
191
192
193 /* Takes a key-certif object, extracts its 'certif' attribute and adds
194 the key into public keyring
195 If there is no problem, it returns NULL
196 If there is a problem, then it returns a string which contains an error
197 message */
198 char * import_key(char *obj){
/* [<][>][^][v][top][bottom][index][help] */
199
200 char * tempfile;
201 struct ImportKeyObject iKO;
202 GSList * certiflist, * next, * templist;
203 FILE * key_file;
204 char keyID[9];
205 char * obj_keyID, * key_cert_attr;
206 char * error_string = NULL;
207 char ** lines;
208 int i;
209 char * temp, * temp2;
210
211 tempfile = (char *)malloc(strlen(tmpdir) + strlen("tmp-key.") + 32);
212 sprintf(tempfile, "%s/tmp-key.%i", tmpdir, getpid());
213 printf("DEBUG: tempfile=%s\n", tempfile);
214
215 /* now we must write certif attribute(s) of this key-certif into the tempfile */
216 /* get the certif first */
217 certiflist = get_attr_list(obj, "certif");
218 if(( key_file = fopen(tempfile, "w")) == NULL){
219 fprintf(stderr, "Can't open temporary file, %s", tempfile);
220 exit(1);
221 }
222 for( next = certiflist; next != NULL ; next = g_slist_next(next) ){
223 lines = g_strsplit((char *)next->data, "\n", 0);
224 //printf("DEBUG: attr: %s\n", (char *)next->data);
225 if(lines[0] == NULL){/* if this was an empty attribute, just print an empty line */
226 fprintf(key_file, "\n");
227 }
228 for(i = 0; lines[i] != NULL; i++){
229 //printf("DEBUG: i=%i\n", i);
230 temp = strdup(lines[i]);
231 if(i != 0 && temp[0] == '+'){/* if it begins with a plus */
232 temp2 = strdup(temp + 1);
233 g_strstrip(temp2);
234 fprintf(key_file, "%s\n", temp2);
235 free(temp);free(temp2);
236 }else{
237 g_strstrip(temp);
238 fprintf(key_file, "%s\n", temp);
239 free(temp);
240 }
241 }
242 g_strfreev(lines);
243 //fprintf(key_file, "%s\n", (char *)next->data);
244 }
245 fclose(key_file);
246 g_slist_free(certiflist);
247
248 strcpy(iKO.iFilename, tempfile);
249 strcpy(iKO.keyRing, pgp_public_key_ring);
250 PA_ImportKey(&iKO);
251
252 printf("importKeyObj status:\n");
253
254 printf("isValid: %d\n", iKO.rc);
255 printf("keyID: %08lX\n", iKO.keyID);
256 snprintf(keyID, 9, "%08lX", iKO.keyID);
257 printf("keyID: [%s]\n", keyID);
258
259 unlink(tempfile);
260 free(tempfile);
261
262
263 templist = get_attr_list(obj, "key-cert");
264 key_cert_attr = strdup((char *)templist->data);
265 g_slist_free(templist);
266
267 printf("key_cert_attr: [%s]\n", key_cert_attr);
268 obj_keyID = strdup(key_cert_attr + strlen("PGPKEY-"));
269 printf("obj_keyID: [%s]\n", obj_keyID);
270 if(iKO.rc == iKO_OK && (strcmp(obj_keyID, keyID) == 0)){/* if PA_ImportKey returned OK
271 and the real keyID is equal to the
272 keyID in the 'key-cert' attribute */
273 return NULL;
274 }else{/* if PA_ImportKey returned not OK or obj_keyID, keyID didn't match */
275 if(iKO.rc != iKO_OK){
276 switch(iKO.rc){
277 case iKO_UNCHANGED: error_string = strdup("the key is already in the keyring");break;
278 case iKO_NOUSERID: error_string = strdup("no user ID could be extracted");break;
279 case iKO_GENERAL: error_string = strdup("general PGP error");break;
280 case iKO_NOTVALIDUSERID: error_string = strdup("no valid user ID ");break;
281 case iKO_NOPUBLICKEY: error_string = strdup("no public key in the object");break;
282 case iKO_NODEFAULTPUBLICKEYRING: error_string = strdup("general PGP error");break;
283 case iKO_CRC_ERROR: error_string = strdup("CRC error in the certificate");break;
284 case iKO_NO_OPENPGP_DATA:error_string = strdup("no OpenPGP data in the object");break;
285 case iKO_NO_IN_FILES: error_string = strdup("general PGP error");break;
286 case iKO_GENERALFAILURE: error_string = strdup("general PGP error");break;
287 default: error_string = strdup("general PGP error");
288 }
289 return error_string;
290 }else{
291 error_string = (char *)malloc(1024);/* this should be enough */
292 sprintf(error_string, "Keyid for this certificate (%s) is not the same as the PGPKEY field (%s)",
293 keyID, obj_keyID);
294 return error_string;
295 }
296 }
297
298 }
299
300
301
302 /* Checks the object's syntax, retrives the old version of it from the db,
303 and checks auth2. If everything is OK, then sends it to RIPdb, where referential
304 integrity is checked, and the object is really committed to the db.
305
306 Arguments:
307 char * arg: The object,
308 credentials_struct credentials: The struct containing the credentials, such as
309 'From:' field of the e-mail update,
310 GHashTable * NIC_hdl_hash: A hash containing
311 char * ack_file_name: The file name, to be used to store ACK message
312 */
313
314
315
316 int process_object(char * arg, credentials_struct credentials, GHashTable * NIC_hdl_hash, char * ack_file_name,
/* [<][>][^][v][top][bottom][index][help] */
317 GHashTable * ntfy_hash, GHashTable * forw_hash, GHashTable * cross_hash){
318 bool code = true;
319 Object *o;
320 char * old_version = NULL;
321 o = new Object;
322 int result = 0;
323 int result_from_RIPupd = 0;
324 char * result_from_import_key = NULL;
325 char * result_from_delete_key = NULL;
326 char * auto_nic = NULL;
327 char * changed_obj = NULL;
328 char * obj_with_AUTO_NIC_hdl;
329 char * assigned_NIC;
330 char * type;
331
332 char * value = NULL;/* these two are for */
333 Attr * attr; /* ack messages only */
334
335 if(has_ref_to_AUTO_nic_hdl(arg)){/* if this object has refs to AUTO NIC hdls*/
336 /* then first replace AUTO NIC hdls with assigned NIC hdls (in NIC_hdl_hash) */
337 if((arg = replace_refs_to_AUTO_NIC_hdl(changed_obj, arg, NIC_hdl_hash)) == NULL){
338 return UP_ANE; /* AUTO NIC hdl error */
339 };
340 }
341
342 code = o->scan(arg,strlen(arg));
343 if(code){
344 type = get_type(o);
345 /* is the object to be deleted? */
346 if(o->isDeleted){
347 //printf("DEBUG: This object is to be deleted\n");
348 old_version = get_old_version(arg);
349 if(old_version == NULL){ /* the object doesn't exist in the db! */
350 AK_add_to_ack(ack_file_name, "\nDelete FAILED: [%s] %s\nEntry not found\n\n%s\n",
351 o->type->getName(), get_search_key(o, o->type->getName(), arg), arg);
352 return UP_NSO; /* no such object */
353 }else {/* the object is in the db */
354 if(identical(old_version, arg)){/* if the old & new versions are identical */
355 result = check_auth(NULL, old_version, o->type->getName(), credentials);
356 if(result == UP_AUTH_OK){
357 if(tracing) {
358 printf("TRACING: Will send the obj to be deleted\n");
359 }
360 if(strcmp(type, "key-cert") == 0){
361 result_from_delete_key = delete_key(arg);
362 }else{
363 result_from_delete_key = NULL;
364 }
365 /* if there was no problem with key deletion from the key-ring */
366 if(result_from_delete_key == NULL){
367 result_from_RIPupd = send_object_db(arg, NULL, "DEL");
368 if(result_from_RIPupd == 0){
369 AK_add_to_ack(ack_file_name, "\nDelete OK: [%s] %s\n",
370 o->type->getName(), get_search_key(o, o->type->getName(), arg));
371 NT_write_all_ntfs(arg, NULL, tmpdir, ntfy_hash, forw_hash, cross_hash, credentials.from);
372 }else{
373 AK_add_to_ack(ack_file_name, "\nDelete FAILED: [%s] %s\nReferential integrity failure\n",
374 o->type->getName(), get_search_key(o, o->type->getName(), arg));
375 }
376 result_from_RIPupd = 0;
377 }else{
378 AK_add_to_ack(ack_file_name, "\nDelete FAILED: [%s] %s\n%s\n",
379 o->type->getName(), get_search_key(o, o->type->getName(), arg), result_from_delete_key);
380 }
381 }else{ /* auth failed */
382 if(tracing) {
383 printf("TRACING: Auth failed\n");
384 }
385
386 AK_add_to_ack(ack_file_name, "\nDelete FAILED: [%s] %s\nAuth failed\n",
387 o->type->getName(), get_search_key(o, o->type->getName(), arg));
388 NT_write_all_frwds(arg, NULL, tmpdir, ntfy_hash, forw_hash, cross_hash, credentials.from);
389 return UP_AUF; /* Auth failed */
390 }
391 }else{/* the new & old versions do not match */
392 AK_add_to_ack(ack_file_name, "\nDelete FAILED: new & old versions do not match\n");
393 return UP_NOM; /* new & old versions do not match */
394 }
395 }
396 }else {/* the object is _not_ to be deleted */
397 if(has_AUTO_NIC_hdl(arg)){/* it the object has an AUTO NIC hdl */
398 /* then its nic-hdl attribute must be modified so that RIPupdate
399 would understand that it must assign a NIC handle to it */
400 /* but first check the auth */
401 result = check_auth(arg, NULL, o->type->getName(), credentials);
402 if(result == UP_AUTH_OK){
403 if(tracing) {
404 printf("TRACING: Will send the obj to be created with AUTO NIC hdl\n");
405 }
406 auto_nic = (char *)malloc(1024); /* should be enough for a NIC hdl */
407 obj_with_AUTO_NIC_hdl = replace_AUTO_NIC_hdl(arg, auto_nic);
408 if(tracing) {
409 printf("TRACING: Called replace_AUTO_NIC_hdl, get [%s]\n", obj_with_AUTO_NIC_hdl);
410 printf("TRACING: Will send the obj to be added\n");
411 }
412 assigned_NIC = (char *)malloc(128); /* this should be enough for a NIC hdl */
413 result_from_RIPupd = send_object_db(obj_with_AUTO_NIC_hdl, assigned_NIC, "ADD");
414 if(result_from_RIPupd == 0){
415 AK_add_to_ack(ack_file_name, "\nNew OK: [%s] %s\n",
416 o->type->getName(), assigned_NIC);
417 NT_write_all_ntfs(NULL, arg, tmpdir, ntfy_hash, forw_hash, cross_hash, credentials.from);
418 }else{
419 AK_add_to_ack(ack_file_name, "\nNew FAILED: [%s] %s\nReferential integrity failure\n",
420 o->type->getName(), arg);
421 }
422 result_from_RIPupd = 0;
423 if(tracing && assigned_NIC != NULL) {
424 printf("TRACING: send_object_db returned [%s] as assigned NIC hdl\n", assigned_NIC);
425 }
426 if(assigned_NIC != NULL){
427 printf("DEBUG: auto_nic=[%s], assigned_NIC=[%s]\n", auto_nic, assigned_NIC);
428 g_hash_table_insert(NIC_hdl_hash, auto_nic, assigned_NIC);
429 printf("DEBUG: NIC_hdl_hash has %i pairs\n",g_hash_table_size(NIC_hdl_hash));
430 }
431
432 }else{
433 /* auth failed ! */
434 if(tracing) {
435 printf("TRACING: Auth failed\n");
436 }
437
438 ER_perror(0, result, "");
439 AK_add_to_ack(ack_file_name, "\nNew FAILED: [%s] %s\nAuth failed\n",
440 o->type->getName(), get_search_key(o, o->type->getName(), arg));
441 NT_write_all_frwds(NULL, arg, tmpdir, ntfy_hash, forw_hash, cross_hash, credentials.from);
442 return UP_AUF; /* Auth failed */
443 }
444 }
445 else{
446 old_version = get_old_version(arg);
447 if(old_version != NULL){/* so, this is an update operation */
448 result = check_auth(arg, old_version, o->type->getName(), credentials);
449 if(result == UP_AUTH_OK){
450 if(tracing) {
451 printf("TRACING: Will send the obj to be updated\n");
452 }
453 result_from_RIPupd = send_object_db(arg, NULL, "UPD");
454 if(result_from_RIPupd == 0){
455 AK_add_to_ack(ack_file_name, "\nUpdate OK: [%s] %s\n",
456 o->type->getName(), get_search_key(o, o->type->getName(), arg));
457 NT_write_all_ntfs(old_version, arg, tmpdir, ntfy_hash, forw_hash, cross_hash, credentials.from);
458 }else{
459 AK_add_to_ack(ack_file_name, "\nUpdate FAILED: [%s]\n%s\nReferential integrity failure\n",
460 o->type->getName(), get_search_key(o, o->type->getName(), arg));
461 }
462 result_from_RIPupd = 0;
463 }else{
464 /* auth failed ! */
465 if(tracing) {
466 printf("TRACING: Auth failed\n");
467 }
468
469 AK_add_to_ack(ack_file_name, "\nUpdate FAILED: [%s] %s\nAuth failed\n",
470 o->type->getName(), get_search_key(o, o->type->getName(), arg));
471 NT_write_all_frwds(old_version, arg, tmpdir, ntfy_hash, forw_hash, cross_hash, credentials.from);
472 return UP_AUF; /* Auth failed */
473 }
474 }else { /* old_version == NULL, so, creation */
475 result = check_auth(arg, NULL, o->type->getName(), credentials);
476 if(result == UP_AUTH_OK){
477 if(tracing) {
478 printf("TRACING: Will send the obj to be added\n");
479 }
480 /* if the object is a key-cert object, then we must import the PGP key */
481 if(strcmp(type, "key-cert") == 0){
482 result_from_import_key = import_key(arg);
483 }else{
484 result_from_import_key = NULL;
485 }
486 if(result_from_import_key == NULL){/* no PGP problem */
487 result_from_RIPupd = send_object_db(arg, NULL, "ADD");
488 if(result_from_RIPupd == 0){/* if there was no problem */
489 AK_add_to_ack(ack_file_name, "\nNew OK [%s] %s\n",
490 o->type->getName(), get_search_key(o, o->type->getName(), arg));
491 NT_write_all_ntfs(NULL, arg, tmpdir, ntfy_hash, forw_hash, cross_hash, credentials.from);
492
493 }else{
494 AK_add_to_ack(ack_file_name, "\nNew FAILED: [%s] %s\nReferential integrity failure\n",
495 o->type->getName(), get_search_key(o, o->type->getName(), arg));
496 }
497 result_from_RIPupd = 0;
498 }else{/* there was a problem with PGP key import */
499 AK_add_to_ack(ack_file_name, "\nNew FAILED: [%s] %s\n%s\n",
500 o->type->getName(), get_search_key(o, o->type->getName(), arg),
501 result_from_import_key);
502 }
503 }else{
504 /* auth failed ! */
505 if(tracing) {
506 printf("TRACING: Auth failed\n");
507 }
508
509 ER_perror(0, result, "");
510 AK_add_to_ack(ack_file_name, "\nNew FAILED: [%s] %s\nAuth failed\n",
511 o->type->getName(), get_search_key(o, o->type->getName(), arg));
512 NT_write_all_frwds(NULL, arg, tmpdir, ntfy_hash, forw_hash, cross_hash, credentials.from);
513 return UP_AUF; /* Auth failed */
514 }
515 }
516 }
517 }
518 }else{/* even if obj doesn't parse properly, it may be a legacy object
519 which the user wants to delete... */
520 if(tracing){
521 printf("TRACING: Object didn't parse\n");
522 }
523 AK_add_to_ack(ack_file_name, "\nUpdate FAILED: Syntax error in object\n");
524 //////////////////////////////////
525 if(o->attrs.head() != NULL){
526 for(attr = o->attrs.head(); attr; attr = o->attrs.next(attr)){
527 if(attr->len > 0){
528 value = (char*)malloc(attr->len);
529 strncpy(value, (char *)(arg+attr->offset) ,
530 attr->len - 1);
531 value[attr->len - 1] = '\0';
532 AK_add_to_ack(ack_file_name, "%s\n", value);
533 if(!attr->errors.empty()){
534 AK_add_to_ack_string(ack_file_name, attr->errors);
535 }
536 free(value);
537 }else{
538 if(!attr->errors.empty()){
539 AK_add_to_ack_string(ack_file_name, attr->errors);
540 }
541 }
542 }
543 }
544 if(o->has_error){
545 AK_add_to_ack_string(ack_file_name, o->errors);
546 }
547 AK_add_to_ack(ack_file_name, "\n");
548 //////////////////////////////////
549 return UP_NIY; /* Not implemented yet */
550 }
551 }
552
553
554 /* A temporary function to test if there is a PGP signed portion in the file */
555 int scan_for_PGP(const char * filename){
/* [<][>][^][v][top][bottom][index][help] */
556
557 FILE *file;
558 char *line;
559
560 line = (char *)malloc(1024);
561 if((file = fopen(filename, "r")) == NULL){
562 printf("Couldn't open the file %s: %s\n", filename, strerror(errno));
563 exit(1);
564 }
565 while(fgets(line, 1024, file) != NULL){
566 if(strstr(line, "-----BEGIN PGP") == line){/* yes, we have a PGP signed portion, so return true */
567 fclose(file);
568 free(line);
569 return 1;
570 }
571 }
572 fclose(file);
573 free(line);
574 return 0; /* no, we din't have any PGP signed portions */
575 }
576
577
578
579
580
581 /* processes the objects in the given file */
582 void process_file(char * filename, credentials_struct credentials,
/* [<][>][^][v][top][bottom][index][help] */
583 GHashTable * AUTO_NIC_hdl_hash, char * ack_file_name,
584 GHashTable * ntfy_hash, GHashTable * forw_hash, GHashTable * cross_hash){
585
586 FILE * input_file;
587 GSList *list_of_objects = NULL, *list_of_objects2 = NULL;
588 GSList *next = NULL;
589 int object_count = 0;
590 char *object = NULL;
591 char line[1024];
592 int result = 0;
593 struct VerifySignObject vSO, *pvSO;
594
595
596 /* allocate space for pgp_struct, it will be set to pgp key ID when we encounter a pgp signed message */
597 credentials.pgp_struct == (char *)malloc(10);
598
599 //line = (char *)malloc(1024);
600
601 /* if we have PGP signed portions in the message */
602 if(scan_for_PGP(filename)){
603 strcpy(vSO.outputPath, "/tmp");
604 strcpy(vSO.iDocSigFilename, filename);
605 strcpy(vSO.iSigFilename, "");
606 strcpy(vSO.keyRing, pgp_public_key_ring);
607
608 PA_VerifySignature(&vSO);
609
610 pvSO = vSO.next;
611 while (pvSO != NULL) {
612 printf("isValid: %d\n", pvSO->isValid);
613 printf("key ID: %x\n", pvSO->keyID);
614 printf("oStream is %s\n", pvSO->oStream);
615
616
617 if(pvSO->isValid == vSO_IS_VALID){/* if this PGP signed portion is valid, read it */
618 if((input_file = fopen( pvSO->oStream/*filename*/, "r")) == NULL){
619 printf("Couldn't open the file %s: %s\n", filename, strerror(errno));
620 exit(1);
621 }
622 AK_add_to_ack(ack_file_name, "\n*** Beginning of PGP signed part from key ID %X\n", pvSO->keyID);
623 sprintf(credentials.pgp_struct, "%.8X", pvSO->keyID);
624 printf("DEBUG: credentials.pgp_struct=[%s]\n", credentials.pgp_struct);
625 while(fgets(line, 1024, input_file) != NULL){
626 /* first, if it is a pasword, save it, but do not regard it as an attrib */
627 if(strstr(line, "password:") == line){
628 if(tracing){
629 printf("DEBUG: This is a password\n");
630 }
631 credentials.password_list = g_slist_append(credentials.password_list,
632 g_strstrip(strdup(line + strlen("password:"))));
633 continue;
634 }
635 /* if the length of the line read is 2, then this is an empty line ("\n\r")*/
636 if(strlen(line) == 2){
637 if(object != NULL){
638 list_of_objects = g_slist_append(list_of_objects, object);
639 object = NULL;
640 }
641 }else{
642 /* if the line contains only the EOL sequence "\n\r" */
643 if(object == NULL && strlen(line) != 2){
644 object = (char *)malloc(strlen(line));
645 object = strdup(line);
646 }
647 else{
648 object = (char *)realloc(object, strlen(object) + strlen(line) + 1);
649 object = strcat(object, line);
650 }
651 }
652
653 }
654 fclose(input_file);
655
656 /* now, if at the very and of the input file there wasn't an
657 empty line, we have to add the remaining object in the 'object'
658 variable */
659 if(object != NULL){
660 //cout << "The object was" << endl << object << endl;
661 list_of_objects = g_slist_append(list_of_objects, object);
662 object = NULL;
663 }
664
665
666
667 if(tracing) {
668 printf("TRACING: Will process the objects in the list\n");
669 }
670 next = list_of_objects;
671 object_count = 0;
672 for( next = list_of_objects; next != NULL ; next = g_slist_next(next) ){
673 object_count++;
674
675 if(tracing) {
676 cout << "TRACING: Got an object from the list" << endl;
677 cout << (char *)next->data << endl;
678 }
679
680 if(has_ref_to_AUTO_nic_hdl((char *)next->data)){/* defer the processing */
681 if(tracing) {
682 printf("TRACING: this object has a ref to an AUTO NIC hdl\n");
683 }
684 list_of_objects2 = g_slist_append(list_of_objects2, strdup((char *)next->data));
685 }else{
686 result = 0;
687 result = process_object((char *)next->data, credentials, AUTO_NIC_hdl_hash, ack_file_name,
688 ntfy_hash, forw_hash, cross_hash);
689 }
690 }
691
692 if(tracing) {
693 printf("TRACING: list_of_objects2 has %d entries\n", g_slist_length(list_of_objects2));
694 }
695
696 if(tracing) {
697 printf("TRACING: will start to process the second list\n");
698 }
699
700 for( next = list_of_objects2; next != NULL ; next = g_slist_next(next) ){
701 if(tracing) {
702 printf("TRACING: Will process object: %s\n", (char *)next->data);
703 }
704 result = process_object((char *)next->data, credentials, AUTO_NIC_hdl_hash, ack_file_name,
705 ntfy_hash, forw_hash, cross_hash);
706 }
707 /* empty the object lists (this must be done by properly freeing the memory taken by them!) */
708 list_of_objects = NULL;
709 list_of_objects2 = NULL;
710 AK_add_to_ack(ack_file_name, "\n*** End of PGP signed part from key ID %X\n", pvSO->keyID);
711
712 }else{
713 AK_add_to_ack(ack_file_name, "\n*** Ignoring PGP signed part from key ID %X", pvSO->keyID);
714 AK_add_to_ack(ack_file_name, "\n*** Bad signature or key is not in public key ring or other error\n\n");
715 }
716
717 pvSO = pvSO->next;
718 /* empty out credentials.pgp_struct for the next loop */
719 strcpy(credentials.pgp_struct,"");
720 }
721
722 }
723 else{/* the file doesn't contain PGP signed portions */
724 if((input_file = fopen(filename, "r")) == NULL){
725 printf("Couldn't open the file %s: %s\n", filename, strerror(errno));
726 exit(1);
727 }
728
729
730 while(fgets(line, 1024, input_file) != NULL){
731 /* first, if it is a pasword, save it, but do not regard it as an attrib */
732 if(strstr(line, "password:") == line){
733 if(tracing){
734 printf("DEBUG: This is a password\n");
735 }
736 credentials.password_list = g_slist_append(credentials.password_list,
737 g_strstrip(strdup(line + strlen("password:"))));
738 continue;
739 }
740 /* if the length of the line read is 2, then this is an empty line ("\n\r")*/
741 if(strlen(line) == 2){
742 if(object != NULL){
743 list_of_objects = g_slist_append(list_of_objects, object);
744 object = NULL;
745 }
746 }else{
747 /* if the line contains only the EOL sequence "\n\r" */
748 if(object == NULL && strlen(line) != 2){
749 object = (char *)malloc(strlen(line));
750 object = strdup(line);
751 }
752 else{
753 object = (char *)realloc(object, strlen(object) + strlen(line) + 1);
754 object = strcat(object, line);
755 }
756 }
757
758 }
759 fclose(input_file);
760
761 /* now, if at the very and of the input file there wasn't an
762 empty line, we have to add the remaining object in the 'object'
763 variable */
764 if(object != NULL){
765 //cout << "The object was" << endl << object << endl;
766 list_of_objects = g_slist_append(list_of_objects, object);
767 object = NULL;
768 }
769
770
771
772 if(tracing) {
773 printf("TRACING: Will process the objects in the list\n");
774 }
775 next = list_of_objects;
776 object_count = 0;
777 for( next = list_of_objects; next != NULL ; next = g_slist_next(next) ){
778 object_count++;
779
780 if(tracing) {
781 cout << "TRACING: Got an object from the list" << endl;
782 cout << (char *)next->data << endl;
783 }
784
785 if(has_ref_to_AUTO_nic_hdl((char *)next->data)){/* defer the processing */
786 if(tracing) {
787 printf("TRACING: this object has a ref to an AUTO NIC hdl\n");
788 }
789 list_of_objects2 = g_slist_append(list_of_objects2, strdup((char *)next->data));
790 }else{
791 result = 0;
792 result = process_object((char *)next->data, credentials, AUTO_NIC_hdl_hash, ack_file_name,
793 ntfy_hash, forw_hash, cross_hash);
794 }
795 }
796
797 if(tracing) {
798 printf("TRACING: list_of_objects2 has %d entries\n", g_slist_length(list_of_objects2));
799 }
800
801 if(tracing) {
802 printf("TRACING: will start to process the second list\n");
803 }
804
805 for( next = list_of_objects2; next != NULL ; next = g_slist_next(next) ){
806 if(tracing) {
807 printf("TRACING: Will process object: %s\n", (char *)next->data);
808 }
809 result = process_object((char *)next->data, credentials, AUTO_NIC_hdl_hash, ack_file_name,
810 ntfy_hash, forw_hash, cross_hash);
811 }
812
813 }
814
815 }/* process_file */
816
817
818
819
820
821
822 /* Generates a unique file name and returns the full path of the filename
823 for storing notification message. */
824
825 char * generate_upd_file(){
/* [<][>][^][v][top][bottom][index][help] */
826
827 char * name;
828
829 /* allocate space for name. 32 should be enough for PID */
830 name = (char*)malloc(strlen("/tmp/dbupdate-tmp.") + strlen("notify") +32 );
831
832 sprintf(name, "/tmp/dbupdate-tmp.%i", getpid());
833
834
835 return name;
836
837 }
838
839
840
841
842
843 /* main */
844 void main(int argc, char **argv, char **envp){
/* [<][>][^][v][top][bottom][index][help] */
845 //init_and_set_options(argc, argv, envp);
846
847 int count = 0;
848 int i,j;
849 int no_of_updateables = 0;
850 char ** temp_vector;
851 char * temp;
852 char * temp_upd_file = NULL;
853 char *input_file_name = NULL;
854 GHashTable *AUTO_NIC_hdl_hash;
855 credentials_struct credentials;
856 FILE * upd_file;
857 char c;
858 /* temp variables to read from conf */
859 char * source = NULL, * canupd = NULL;
860 ca_dbSource_t *source_hdl;
861
862 GHashTable *ntfy_hash, *forw_hash, *cross_hash;
863
864
865 char *mail_command_line, * ack_file_name;
866 char *config_file_name = NULL;
867
868
869 /* for using MM module */
870 int retcode;
871 MM_header *mail_header = NULL;
872 MM_xmp_list *part_list;
873 MM_xmp *partptr;
874 long debug = 0;
875
876 /* optarg & optind are necessary to use getopt(3C) */
877 extern char *optarg;
878 extern int optind;
879
880
881 /* create notification hashes */
882 ntfy_hash = g_hash_table_new(g_str_hash, g_str_equal);
883 forw_hash = g_hash_table_new(g_str_hash, g_str_equal);
884 cross_hash = g_hash_table_new(g_str_hash, g_str_equal);
885
886 credentials.password_list = NULL;
887 credentials.from = NULL;
888 int ch;
889 char * to_address = NULL;
890
891 AUTO_NIC_hdl_hash = g_hash_table_new(g_str_hash, g_str_equal);
892 error_init(argc, argv);
893
894
895
896
897 while ((ch = getopt(argc, argv, "MtTf:c:")) != -1){
898 switch(ch) {
899 case 'M':
900 reading_from_mail = 1;
901 break;
902 case 'f':
903 input_file_name = strdup(optarg);
904 break;
905 case 'c':
906 config_file_name = strdup(optarg);
907 break;
908 case 't':
909 tracing = 1;
910 break;
911 case 'T':
912 test_mode = 1;
913 break;
914 case '?':
915 default:
916 printf("Unknown option\n");exit(1);
917 }
918 }
919
920
921 /* config stuff */
922 ca_populateDictionary(dictionary, VARS);
923 /* if -c flag is given, use the named file as config file, otherwise use
924 default filename */
925 if( config_file_name != NULL){
926 ca_readConfig(config_file_name, confVars, VARS);
927 }else{
928 ca_readConfig("dbupdate.conf", confVars, VARS);
929 }
930
931 tmpdir = ca_get_tmpdir;
932 tmpdir = g_strstrip(tmpdir);
933 mailcmd = ca_get_mailcmd;
934 mailcmd = g_strstrip(mailcmd);
935 notitxt = ca_get_notitxt;
936 mailtxt = ca_get_mailtxt;
937 crosslog = ca_get_crosslog;
938 fwtxt = ca_get_fwtxt;
939 humailbox = ca_get_humailbox;
940 humailbox = g_strstrip(humailbox);
941 overridecryptedpw = ca_get_overridecryptedpw;
942 overridecryptedpw = g_strstrip(overridecryptedpw);
943 acklog = ca_get_acklog;
944 notiflog = ca_get_notiflog;
945 notimailtxt = ca_get_notimailtxt;
946 forwlog = ca_get_forwlog;
947 fwmailtxt = ca_get_fwmailtxt;
948 country = ca_get_country;
949 pgppath = ca_get_pgppath;
950 pgp_public_key_ring = (char *)malloc(strlen(pgppath) + strlen("/pubring.gpg") + 2);
951 sprintf(pgp_public_key_ring ,"%s/pubring.gpg", pgppath);
952 if(test_mode != 1){/* if it is not already set to 1 (from command line), read from config */
953 test_mode = ca_get_testmode;
954 }
955 /* retrieve source variables */
956 for(i=0, j=0, no_of_updateables=0; (source_hdl = ca_get_SourceHandleByPosition(i))!=NULL ; i++){
957 source = ca_get_srcname(source_hdl);
958 printf("DEBUG: source: [%s]\n", source);
959 canupd = ca_get_srccanupd(source_hdl);
960 printf("DEBUG: canupd: [%s]\n", canupd);
961 if(strcmp(canupd, "y") == 0){
962 sources[j++] = strdup(source);
963 no_of_updateables++;
964 }
965 if(no_of_updateables == 1 && strcmp(canupd, "y") == 0){/* if this is the first updatable source */
966 /* get the port and hostname of RIPupdate, and those of query server */
967 /* Note: We use NRTM part of the SOURCE line of the conf for update host
968 and MySQL part of it for query host
969 so do not confuse */
970 update_host = ca_get_srcnrtmhost(source_hdl);
971 update_port = ca_get_srcnrtmport(source_hdl);
972 query_host = ca_get_srcdbmachine(source_hdl);
973 query_port = ca_get_srcdbport(source_hdl);
974 }
975 free(source);free(canupd);
976 }
977 sources[j] = NULL; /* mark the end of array */
978 if(no_of_updateables == 0){
979 printf("There must be at least one updateable source in the config file. Exiting.\n");exit(1);
980 }else if(no_of_updateables > 1){
981 printf("Warning: Multiple updateable sources are not supported yet. Exiting.\n");exit(1);
982 }
983
984 /* construct country array from country string variable */
985
986 temp_vector = g_strsplit(country, "\n", 0);
987 for(i=0, j=0; temp_vector[i] != NULL; i++){
988 temp_vector[i] == g_strstrip(temp_vector[i]);
989 if(strlen(temp_vector[i]) > 0){
990 countries[j] = strdup(temp_vector[i]);
991 g_strup(countries[j]);
992 printf("DEBUG: got a country country[%i] =[%s],\n", j, countries[j]);
993 j++;
994 }
995 }
996 countries[j] = NULL; /* mark the end of array */
997 printf("DEBUG: countries[%i] = NULL\n", j);
998
999 printf("TMPDIR is: [%s]\n", tmpdir);
1000 printf("MAILCMD is: [%s]\n", mailcmd);
1001 printf("NOTITXT is: [%s]\n", notitxt);
1002 printf("CROSSLOG is: [%s]\n", crosslog);
1003 printf("FWTXT is: [%s]\n", fwtxt);
1004 printf("HUMAILBOX is: [%s]\n", humailbox);
1005 printf("OVERRIDECRYPTEDPW is: [%s]\n", overridecryptedpw);
1006 printf("ACKLOG is: [%s]\n", acklog);
1007 printf("NOTIFLOG is: [%s]\n", notiflog);
1008 printf("FORWLOG is: [%s]\n", forwlog);
1009 printf("NOTIMAILTXT is: [%s]\n", notimailtxt);
1010 printf("FWMAILTXT is: [%s]\n", fwmailtxt);
1011 printf("COUNTRY is: [%s]\n", country);
1012 printf("PGPPATH is: [%s]\n", pgppath);
1013 printf("UPDATE_HOST is: [%s]\n", update_host);
1014 printf("UPDATE_PORT is: [%i]\n", update_port);
1015 printf("QUERY_HOST is: [%s]\n", query_host);
1016 printf("QUERY_PORT is: [%i]\n", query_port);
1017
1018 printf("TESTMODE is: [%i]\n", test_mode);
1019 /* end of config stuff */
1020
1021
1022
1023 /* initialize the parser */
1024 schema.initialize();
1025
1026
1027 /* Generate a name for temporary file for storing acks (AK_ack_file_name_generate
1028 also creates it) */
1029 ack_file_name = AK_ack_file_name_generate(tmpdir, ACK_FILE_PREFIX);
1030
1031
1032 /* Allocate memory for the header */
1033 mail_header = (MM_header *)malloc(sizeof(MM_header));
1034
1035 /* Initialize the list of extracted MIME parts */
1036 part_list = (MM_xmp_list *)malloc(sizeof(MM_xmp_list));
1037 MM_xmp_list_init (part_list);
1038
1039
1040 if(reading_from_mail){
1041 if(input_file_name != NULL){
1042 temp_upd_file = generate_upd_file();
1043 printf("DEBUG: temp_upd_file is [%s]\n", temp_upd_file);
1044 MM_store(input_file_name, temp_upd_file, 0);
1045 if((retcode = MM_decode(temp_upd_file, mail_header, part_list, 1, 0)) != 0){
1046 printf("DEBUG: MM_decode returned %i\n", retcode);
1047 exit(retcode);
1048 }
1049
1050 }else{/* input_file_name == NULL */
1051 temp_upd_file = generate_upd_file();
1052 printf("DEBUG: temp_upd_file is [%s]\n", temp_upd_file);
1053 MM_store("-", temp_upd_file, 0);
1054 if((retcode = MM_decode(temp_upd_file, mail_header, part_list, 1, 0)) != 0){
1055 printf("DEBUG: MM_decode returned %i\n", retcode);
1056 exit(retcode);
1057 }
1058
1059 }
1060 //unlink(temp_upd_file);
1061 printf ("Mail headers:\n\n");
1062 printf ("From - [%s]",mail_header->from);
1063 /* some MAIL-FROM's in mntner auths contain "From: " string too,
1064 so we have to have it in credential.from */
1065 temp = (char *)malloc(strlen(mail_header->from) + strlen("From: ") + 1);
1066 sprintf(temp, "From: %s", mail_header->from);
1067 temp[strlen(temp) - 4] = '\0'; /* cut two '\r\n's at the end */
1068 credentials.from = temp;
1069 printf ("credentials.from = [%s]\n", credentials.from );
1070 /* cut off the '\n's and '\r's at the end of mail_header->subject */
1071 while(mail_header->subject[strlen(mail_header->subject) - 1] == '\n' ||
1072 mail_header->subject[strlen(mail_header->subject) - 1] == '\r'){
1073 mail_header->subject[strlen(mail_header->subject) - 1] = '\0';
1074 }
1075 //mail_header->subject[strlen(mail_header->subject) - 4] = '\0';
1076 printf ("Subject - [%s]",mail_header->subject);
1077 printf ("Date - [%s]",mail_header->date);
1078 printf ("Message-ID - [%s]",mail_header->message_id);
1079 printf ("Reply-To - [%s]",mail_header->reply_to);
1080 printf ("Cc - [%s]",mail_header->cc);
1081 to_address = find_to_address(credentials.from);
1082 /* if Reply-To was in the incoming mail's header, set to_address to that value */
1083 if(strlen(mail_header->reply_to) > 5){
1084 to_address = (char *)realloc(to_address, strlen(mail_header->reply_to) + 1);
1085 to_address = strcpy(to_address, mail_header->reply_to);
1086 //printf("DEBUG: strlen(to_address)=[%i]\n", strlen(to_address));
1087 while(to_address[strlen(to_address) - 1] == '\n' ||
1088 to_address[strlen(to_address) - 1] == '\r' ){
1089 //printf("DEBUG: cutting final '\\n'\n");
1090 //printf("DEBUG: strlen(to_address)=[%i]\n", strlen(to_address));
1091 to_address[strlen(to_address) - 1] = '\0';
1092 }
1093 //printf("DEBUG: to_address is [%s]\n", to_address);
1094 //printf("DEBUG: strlen(to_address)=[%i]\n", strlen(to_address));
1095 }
1096 AK_add_to_ack(ack_file_name, "To: %s\nFrom: %s\nSubject: Re: %s \nReply-To: %s\n\nAcknowledgement message from database software, beta version\n", to_address, humailbox, mail_header->subject, humailbox);
1097 if(credentials.from != NULL){
1098 AK_add_to_ack(ack_file_name, "\n[%s]\n", credentials.from);
1099 }
1100
1101 partptr = part_list->head;
1102 while (partptr != NULL){
1103
1104 printf("-----------------------------------------\n");
1105 printf ("Section: %s\n",partptr->number);
1106 printf ("Content-type: %s\n",partptr->type);
1107 if (partptr->supported){
1108 printf ("Supported\n");
1109 printf ("Filename is [%s]\n", partptr->file);
1110 process_file(partptr->file, credentials,
1111 AUTO_NIC_hdl_hash, ack_file_name,
1112 ntfy_hash, forw_hash, cross_hash);
1113 }
1114 else{
1115 printf ("Unsupported MIME type\n");
1116 AK_add_to_ack(ack_file_name, "\nWarning: Unsupported MIME type: %s. Ignored.\n", partptr->type);
1117 }
1118 partptr = partptr->next;
1119 }
1120
1121
1122 /* Clean up the temporary files */
1123 MM_cleanup(part_list, 0);
1124
1125
1126 }else{/* not reading from the mail message */
1127 if(input_file_name != NULL){
1128 process_file(input_file_name, credentials,
1129 AUTO_NIC_hdl_hash, ack_file_name,
1130 ntfy_hash, forw_hash, cross_hash);
1131 }else{/* the filename is not given, so we have to write
1132 stdin to a temp file, and give it to process_file */
1133 temp_upd_file = generate_upd_file();
1134 printf("DEBUG: main: temp_upd_file=%s\n", temp_upd_file);
1135 if(( upd_file = fopen(temp_upd_file, "a")) == NULL){
1136 fprintf(stderr, "Can't open ack file, %s", temp_upd_file);
1137 }
1138
1139 while((c = getchar()) != EOF){
1140 fprintf(upd_file, "%c",c);
1141 }
1142 fclose(upd_file);
1143 process_file(temp_upd_file, credentials,
1144 AUTO_NIC_hdl_hash, ack_file_name,
1145 ntfy_hash, forw_hash, cross_hash);
1146 unlink(temp_upd_file);
1147
1148 }
1149
1150 }
1151
1152
1153 if(reading_from_mail && to_address != NULL){
1154 AK_send_ack(ack_file_name, to_address, mailcmd);
1155 }
1156 AK_log_ack(ack_file_name, acklog);
1157 AK_delete_ack(ack_file_name);
1158
1159 NT_send_ntfy_list(ntfy_hash, mailcmd);
1160 NT_log_ntfy_list(ntfy_hash, notiflog);
1161 NT_delete_ntfy_list(ntfy_hash);
1162
1163 NT_send_ntfy_list(forw_hash, mailcmd);
1164 NT_log_ntfy_list(forw_hash, forwlog);
1165 //NT_delete_ntfy_list(forw_hash);
1166
1167
1168
1169 if(tracing) {
1170 printf("TRACING: END\n");
1171 }
1172
1173
1174 }