bin/dbupdate/dbupdate.cc
/* [<][>][^][v][top][bottom][index][help] */
FUNCTIONS
This source file includes following functions.
- error_init
- import_key
- process_object
- scan_for_PGP
- process_file
- generate_upd_file
- main
1 /***************************************
2 $Revision: 1.25 $
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 *pgppath = NULL;
68 char *pgp_public_key_ring = NULL;
69 /* end of config variables */
70
71 void error_init(int argc, char ** argv) {
/* [<][>][^][v][top][bottom][index][help] */
72 er_path_t erlogstr;
73
74 ER_init(argc, argv);
75
76 erlogstr.fdes = stderr;
77 erlogstr.asp = 0;
78 erlogstr.sev = ER_SEV_W;
79 erlogstr.mode = ER_M_SEVCHAR | ER_M_TEXTLONG;
80
81 ER_setpath(& erlogstr);
82
83 } /* error_init() */
84
85
86 /* Takes a key-certif object, extracts its 'certif' attribute and adds
87 the key into public keyring */
88 int import_key(char *obj){
/* [<][>][^][v][top][bottom][index][help] */
89
90 char * tempfile;
91 struct ImportKeyObject iKO;
92 GSList * certiflist, * next;
93 FILE * key_file;
94 char keyID[9];
95
96 tempfile = (char *)malloc(strlen(tmpdir) + strlen("tmp-key.") + 32);
97 sprintf(tempfile, "%s/tmp-key.%i", tmpdir, getpid());
98 printf("DEBUG: tempfile=%s\n", tempfile);
99
100 /* now we must write certif attribute(s) of this key-certif into the tempfile */
101 /* get the certif first */
102 certiflist = get_attr_list(obj, "certif");
103 if(( key_file = fopen(tempfile, "w")) == NULL){
104 fprintf(stderr, "Can't open temporary file, %s", tempfile);
105 exit(1);
106 }
107 for( next = certiflist; next != NULL ; next = g_slist_next(next) ){
108 fprintf(key_file, "%s\n", (char *)next->data);
109 }
110 fclose(key_file);
111
112 strcpy(iKO.iFilename, tempfile);
113 strcpy(iKO.keyRing, pgp_public_key_ring);
114 PA_ImportKey(&iKO);
115
116 printf("importKeyObj status:\n");
117
118 printf("isValid: %d\n", iKO.rc);
119 printf("keyID: %08lX\n", iKO.keyID);
120 snprintf(keyID, 9, "%08lX", iKO.keyID);
121 printf("keyID: [%s]\n", keyID);
122
123 //unlink(tempfile);
124 free(tempfile);
125
126 if(iKO.rc == iKO_OK){/* if PA_ImportKey returned OK */
127 return 1;
128 }else{/* if PA_ImportKey returned not OK */
129 return 0;
130 }
131
132 }
133
134
135
136 /* Checks the object's syntax, retrives the old version of it from the db,
137 and checks auth2. If everything is OK, then sends it to RIPdb, where referential
138 integrity is checked, and the object is really committed to the db.
139
140 Arguments:
141 char * arg: The object,
142 credentials_struct credentials: The struct containing the credentials, such as
143 'From:' field of the e-mail update,
144 GHashTable * NIC_hdl_hash: A hash containing
145 char * ack_file_name: The file name, to be used to store ACK message
146 */
147
148
149
150 int process_object(char * arg, credentials_struct credentials, GHashTable * NIC_hdl_hash, char * ack_file_name,
/* [<][>][^][v][top][bottom][index][help] */
151 GHashTable * ntfy_hash, GHashTable * forw_hash, GHashTable * cross_hash){
152 bool code = true;
153 Object *o;
154 char * old_version = NULL;
155 o = new Object;
156 int result = 0;
157 int result_from_RIPupd = 0;
158 int result_from_import_key = 0;
159 char * auto_nic = NULL;
160 char * changed_obj = NULL;
161 char * obj_with_AUTO_NIC_hdl;
162 char * assigned_NIC;
163 char * type;
164
165 char * value = NULL;/* these two are for */
166 Attr * attr; /* ack messages only */
167
168 if(has_ref_to_AUTO_nic_hdl(arg)){/* if this object has refs to AUTO NIC hdls*/
169 /* then first replace AUTO NIC hdls with assigned NIC hdls (in NIC_hdl_hash) */
170 if((arg = replace_refs_to_AUTO_NIC_hdl(changed_obj, arg, NIC_hdl_hash)) == NULL){
171 return UP_ANE; /* AUTO NIC hdl error */
172 };
173 }
174
175 code = o->scan(arg,strlen(arg));
176 if(code){
177 type = get_type(o);
178 /* is the object to be deleted? */
179 if(o->isDeleted){
180 //printf("DEBUG: This object is to be deleted\n");
181 old_version = get_old_version(arg);
182 if(old_version == NULL){ /* the object doesn't exist in the db! */
183 AK_add_to_ack(ack_file_name, "\nDelete FAILED: [%s] %s\nEntry not found\n\n%s\n",
184 o->type->getName(), get_search_key(o, o->type->getName(), arg), arg);
185 return UP_NSO; /* no such object */
186 }else {/* the object is in the db */
187 if(identical(old_version, arg)){/* if the old & new versions are identical */
188 result = check_auth(NULL, old_version, o->type->getName(), credentials);
189 if(result == UP_AUTH_OK){
190 if(tracing) {
191 printf("TRACING: Will send the obj to be deleted\n");
192 }
193 result_from_RIPupd = send_object_db(arg, NULL, "DEL");
194 if(result_from_RIPupd == 0){
195 AK_add_to_ack(ack_file_name, "\nDelete OK: [%s] %s\n",
196 o->type->getName(), get_search_key(o, o->type->getName(), arg));
197 NT_write_all_ntfs(arg, NULL, tmpdir, ntfy_hash, forw_hash, cross_hash, credentials.from);
198 }else{
199 AK_add_to_ack(ack_file_name, "\nDelete FAILED: [%s] %s\nReferential integrity failure\n",
200 o->type->getName(), get_search_key(o, o->type->getName(), arg));
201 }
202 result_from_RIPupd = 0;
203 }else{ /* auth failed */
204 if(tracing) {
205 printf("TRACING: Auth failed\n");
206 }
207
208 AK_add_to_ack(ack_file_name, "\nDelete FAILED: [%s] %s\nAuth failed\n",
209 o->type->getName(), get_search_key(o, o->type->getName(), arg));
210 NT_write_all_frwds(arg, NULL, tmpdir, ntfy_hash, forw_hash, cross_hash, credentials.from);
211 return UP_AUF; /* Auth failed */
212 }
213 }else{/* the new & old versions do not match */
214 AK_add_to_ack(ack_file_name, "\nDelete FAILED: new & old versions do not match\n");
215 return UP_NOM; /* new & old versions do not match */
216 }
217 }
218 }else {/* the object is _not_ to be deleted */
219 if(has_AUTO_NIC_hdl(arg)){/* it the object has an AUTO NIC hdl */
220 /* then its nic-hdl attribute must be modified so that RIPupdate
221 would understand that it must assign a NIC handle to it */
222 /* but first check the auth */
223 result = check_auth(arg, NULL, o->type->getName(), credentials);
224 if(result == UP_AUTH_OK){
225 if(tracing) {
226 printf("TRACING: Will send the obj to be created with AUTO NIC hdl\n");
227 }
228 auto_nic = (char *)malloc(1024); /* should be enough for a NIC hdl */
229 obj_with_AUTO_NIC_hdl = replace_AUTO_NIC_hdl(arg, auto_nic);
230 if(tracing) {
231 printf("TRACING: Called replace_AUTO_NIC_hdl, get [%s]\n", obj_with_AUTO_NIC_hdl);
232 printf("TRACING: Will send the obj to be added\n");
233 }
234 assigned_NIC = (char *)malloc(128); /* this should be enough for a NIC hdl */
235 result_from_RIPupd = send_object_db(obj_with_AUTO_NIC_hdl, assigned_NIC, "ADD");
236 if(result_from_RIPupd == 0){
237 AK_add_to_ack(ack_file_name, "\nNew OK: [%s] %s\n",
238 o->type->getName(), assigned_NIC);
239 NT_write_all_ntfs(NULL, arg, tmpdir, ntfy_hash, forw_hash, cross_hash, credentials.from);
240 }else{
241 AK_add_to_ack(ack_file_name, "\nNew FAILED: [%s] %s\nReferential integrity failure\n",
242 o->type->getName(), arg);
243 }
244 result_from_RIPupd = 0;
245 if(tracing && assigned_NIC != NULL) {
246 printf("TRACING: send_object_db returned [%s] as assigned NIC hdl\n", assigned_NIC);
247 }
248 if(assigned_NIC != NULL){
249 printf("DEBUG: auto_nic=[%s], assigned_NIC=[%s]\n", auto_nic, assigned_NIC);
250 g_hash_table_insert(NIC_hdl_hash, auto_nic, assigned_NIC);
251 printf("DEBUG: NIC_hdl_hash has %i pairs\n",g_hash_table_size(NIC_hdl_hash));
252 }
253
254 }else{
255 /* auth failed ! */
256 if(tracing) {
257 printf("TRACING: Auth failed\n");
258 }
259
260 ER_perror(0, result, "");
261 AK_add_to_ack(ack_file_name, "\nNew FAILED: [%s] %s\nAuth failed\n",
262 o->type->getName(), get_search_key(o, o->type->getName(), arg));
263 NT_write_all_frwds(NULL, arg, tmpdir, ntfy_hash, forw_hash, cross_hash, credentials.from);
264 return UP_AUF; /* Auth failed */
265 }
266 }
267 else{
268 old_version = get_old_version(arg);
269 if(old_version != NULL){/* so, this is an update operation */
270 result = check_auth(arg, old_version, o->type->getName(), credentials);
271 if(result == UP_AUTH_OK){
272 if(tracing) {
273 printf("TRACING: Will send the obj to be updated\n");
274 }
275 result_from_RIPupd = send_object_db(arg, NULL, "UPD");
276 if(result_from_RIPupd == 0){
277 AK_add_to_ack(ack_file_name, "\nUpdate OK: [%s] %s\n",
278 o->type->getName(), get_search_key(o, o->type->getName(), arg));
279 NT_write_all_ntfs(old_version, arg, tmpdir, ntfy_hash, forw_hash, cross_hash, credentials.from);
280 }else{
281 AK_add_to_ack(ack_file_name, "\nUpdate FAILED: [%s]\n%s\nReferential integrity failure\n",
282 o->type->getName(), get_search_key(o, o->type->getName(), arg));
283 }
284 result_from_RIPupd = 0;
285 }else{
286 /* auth failed ! */
287 if(tracing) {
288 printf("TRACING: Auth failed\n");
289 }
290
291 AK_add_to_ack(ack_file_name, "\nUpdate FAILED: [%s] %s\nAuth failed\n",
292 o->type->getName(), get_search_key(o, o->type->getName(), arg));
293 NT_write_all_frwds(old_version, arg, tmpdir, ntfy_hash, forw_hash, cross_hash, credentials.from);
294 return UP_AUF; /* Auth failed */
295 }
296 }else { /* old_version == NULL, so, creation */
297 result = check_auth(arg, NULL, o->type->getName(), credentials);
298 if(result == UP_AUTH_OK){
299 if(tracing) {
300 printf("TRACING: Will send the obj to be added\n");
301 }
302 /* here we must insert code to import the PGP key, if obj type is key-cert */
303 if(strcmp(type, "key-cert") == 0){
304 result_from_import_key = import_key(arg);
305 }else{
306 result_from_import_key = 1;
307 }
308 if(result_from_import_key == 1){/* no PGP problem */
309 result_from_RIPupd = send_object_db(arg, NULL, "ADD");
310 if(result_from_RIPupd == 0){/* if there was no problem */
311 AK_add_to_ack(ack_file_name, "\nNew OK [%s] %s\n",
312 o->type->getName(), get_search_key(o, o->type->getName(), arg));
313 NT_write_all_ntfs(NULL, arg, tmpdir, ntfy_hash, forw_hash, cross_hash, credentials.from);
314
315 }else{
316 AK_add_to_ack(ack_file_name, "\nNew FAILED: [%s] %s\nReferential integrity failure\n",
317 o->type->getName(), get_search_key(o, o->type->getName(), arg));
318 }
319 result_from_RIPupd = 0;
320 }else{/* there was a problem with PGP key import */
321 AK_add_to_ack(ack_file_name, "\nNew FAILED: [%s] %s\nPGP key problem\n",
322 o->type->getName(), get_search_key(o, o->type->getName(), arg));
323 }
324 }else{
325 /* auth failed ! */
326 if(tracing) {
327 printf("TRACING: Auth failed\n");
328 }
329
330 ER_perror(0, result, "");
331 AK_add_to_ack(ack_file_name, "\nNew FAILED: [%s] %s\nAuth failed\n",
332 o->type->getName(), get_search_key(o, o->type->getName(), arg));
333 NT_write_all_frwds(NULL, arg, tmpdir, ntfy_hash, forw_hash, cross_hash, credentials.from);
334 return UP_AUF; /* Auth failed */
335 }
336 }
337 }
338 }
339 }else{/* even if obj doesn't parse properly, it may be a legacy object
340 which the user wants to delete... */
341 if(tracing){
342 printf("TRACING: Object didn't parse\n");
343 }
344 AK_add_to_ack(ack_file_name, "\nUpdate FAILED: Syntax error in object\n");
345 //////////////////////////////////
346 if(o->attrs.head() != NULL){
347 for(attr = o->attrs.head(); attr; attr = o->attrs.next(attr)){
348 if(attr->len > 0){
349 value = (char*)malloc(attr->len);
350 strncpy(value, (char *)(arg+attr->offset) ,
351 attr->len - 1);
352 value[attr->len - 1] = '\0';
353 AK_add_to_ack(ack_file_name, "%s\n", value);
354 if(!attr->errors.empty()){
355 AK_add_to_ack_string(ack_file_name, attr->errors);
356 }
357 free(value);
358 }else{
359 if(!attr->errors.empty()){
360 AK_add_to_ack_string(ack_file_name, attr->errors);
361 }
362 }
363 }
364 }
365 if(o->has_error){
366 AK_add_to_ack_string(ack_file_name, o->errors);
367 }
368 AK_add_to_ack(ack_file_name, "\n");
369 //////////////////////////////////
370 return UP_NIY; /* Not implemented yet */
371 }
372 }
373
374
375 /* A temporary function to test if there is a PGP signed portion in the file */
376 int scan_for_PGP(const char * filename){
/* [<][>][^][v][top][bottom][index][help] */
377
378 FILE *file;
379 char *line;
380
381 line = (char *)malloc(1024);
382 if((file = fopen(filename, "r")) == NULL){
383 printf("Couldn't open the file %s: %s\n", filename, strerror(errno));
384 exit(1);
385 }
386 while(fgets(line, 1024, file) != NULL){
387 if(strstr(line, "-----BEGIN PGP") == line){/* yes, we have a PGP signed portion, so return true */
388 fclose(file);
389 free(line);
390 return 1;
391 }
392 }
393 fclose(file);
394 free(line);
395 return 0; /* no, we din't have any PGP signed portions */
396 }
397
398
399
400
401
402 /* processes the objects in the given file */
403 void process_file(char * filename, credentials_struct credentials,
/* [<][>][^][v][top][bottom][index][help] */
404 GHashTable * AUTO_NIC_hdl_hash, char * ack_file_name,
405 GHashTable * ntfy_hash, GHashTable * forw_hash, GHashTable * cross_hash){
406
407 FILE * input_file;
408 GSList *list_of_objects = NULL, *list_of_objects2 = NULL;
409 GSList *next = NULL;
410 int object_count = 0;
411 char *object = NULL;
412 char *line;
413 int result = 0;
414 struct VerifySignObject vSO, *pvSO;
415 //char keyring[100] = "/home/engin/.gnupg/pubring.gpg";
416
417
418 /* allocate space for pgp_struct, it will be set to pgp key ID when we encounter a pgp signed message */
419 credentials.pgp_struct == (char *)malloc(10);
420
421 line = (char *)malloc(1024);
422
423 /* if we have PGP signed portions in the message */
424 if(scan_for_PGP(filename)){
425 strcpy(vSO.outputPath, "/tmp");
426 strcpy(vSO.iDocSigFilename, filename);
427 strcpy(vSO.iSigFilename, "");
428 strcpy(vSO.keyRing, pgp_public_key_ring/*keyring*/);
429
430 PA_VerifySignature(&vSO);
431
432 pvSO = vSO.next;
433 while (pvSO != NULL) {
434 printf("isValid: %d\n", pvSO->isValid);
435 printf("key ID: %x\n", pvSO->keyID);
436 printf("oStream is %s\n", pvSO->oStream);
437
438
439 if(pvSO->isValid == 1){/* if this PGP signed portion is valid, read it */
440 if((input_file = fopen( pvSO->oStream/*filename*/, "r")) == NULL){
441 printf("Couldn't open the file %s: %s\n", filename, strerror(errno));
442 exit(1);
443 }
444 AK_add_to_ack(ack_file_name, "\n*** Beginning of PGP signed part from key ID %X\n", pvSO->keyID);
445 sprintf(credentials.pgp_struct, "%.8X", pvSO->keyID);
446 printf("DEBUG: credentials.pgp_struct=[%s]\n", credentials.pgp_struct);
447 while(fgets(line, 1024, input_file) != NULL){
448 /* first, if it is a pasword, save it, but do not regard it as an attrib */
449 if(strstr(line, "password:") == line){
450 if(tracing){
451 printf("DEBUG: This is a password\n");
452 }
453 credentials.password_list = g_slist_append(credentials.password_list,
454 g_strstrip(strdup(line + strlen("password:"))));
455 continue;
456 }
457 /* if the length of the line read is 2, then this is an empty line ("\n\r")*/
458 if(strlen(line) == 2){
459 if(object != NULL){
460 list_of_objects = g_slist_append(list_of_objects, object);
461 object = NULL;
462 }
463 }else{
464 /* if the line contains only the EOL sequence "\n\r" */
465 if(object == NULL && strlen(line) != 2){
466 object = (char *)malloc(strlen(line));
467 object = strdup(line);
468 }
469 else{
470 object = (char *)realloc(object, strlen(object) + strlen(line));
471 object = strcat(object, line);
472 }
473 }
474
475 }
476 fclose(input_file);
477
478 /* now, if at the very and of the input file there wasn't an
479 empty line, we have to add the remaining object in the 'object'
480 variable */
481 if(object != NULL){
482 //cout << "The object was" << endl << object << endl;
483 list_of_objects = g_slist_append(list_of_objects, object);
484 object = NULL;
485 }
486
487
488
489 if(tracing) {
490 printf("TRACING: Will process the objects in the list\n");
491 }
492 next = list_of_objects;
493 object_count = 0;
494 for( next = list_of_objects; next != NULL ; next = g_slist_next(next) ){
495 object_count++;
496
497 if(tracing) {
498 cout << "TRACING: Got an object from the list" << endl;
499 cout << (char *)next->data << endl;
500 }
501
502 if(has_ref_to_AUTO_nic_hdl((char *)next->data)){/* defer the processing */
503 if(tracing) {
504 printf("TRACING: this object has a ref to an AUTO NIC hdl\n");
505 }
506 list_of_objects2 = g_slist_append(list_of_objects2, strdup((char *)next->data));
507 }else{
508 result = 0;
509 result = process_object((char *)next->data, credentials, AUTO_NIC_hdl_hash, ack_file_name,
510 ntfy_hash, forw_hash, cross_hash);
511 }
512 }
513
514 if(tracing) {
515 printf("TRACING: list_of_objects2 has %d entries\n", g_slist_length(list_of_objects2));
516 }
517
518 if(tracing) {
519 printf("TRACING: will start to process the second list\n");
520 }
521
522 for( next = list_of_objects2; next != NULL ; next = g_slist_next(next) ){
523 if(tracing) {
524 printf("TRACING: Will process object: %s\n", (char *)next->data);
525 }
526 result = process_object((char *)next->data, credentials, AUTO_NIC_hdl_hash, ack_file_name,
527 ntfy_hash, forw_hash, cross_hash);
528 }
529 /* empty the object lists (this must be done by properly freeing the memory taken by them!) */
530 list_of_objects = NULL;
531 list_of_objects2 = NULL;
532 AK_add_to_ack(ack_file_name, "\n*** End of PGP signed part from key ID %X\n", pvSO->keyID);
533
534 }else{
535 AK_add_to_ack(ack_file_name, "\n*** Ignoring PGP signed part from key ID %X", pvSO->keyID);
536 AK_add_to_ack(ack_file_name, "\n*** Bad signature or key is not in public key ring or other error\n\n");
537 }
538
539 pvSO = pvSO->next;
540 /* empty out credentials.pgp_struct for the next loop */
541 strcpy(credentials.pgp_struct,"");
542 }
543
544 }
545 else{/* the file doesn't contain PGP signed portions */
546 if((input_file = fopen(filename, "r")) == NULL){
547 printf("Couldn't open the file %s: %s\n", filename, strerror(errno));
548 exit(1);
549 }
550
551
552 while(fgets(line, 1024, input_file) != NULL){
553 /* first, if it is a pasword, save it, but do not regard it as an attrib */
554 if(strstr(line, "password:") == line){
555 if(tracing){
556 printf("DEBUG: This is a password\n");
557 }
558 credentials.password_list = g_slist_append(credentials.password_list,
559 g_strstrip(strdup(line + strlen("password:"))));
560 continue;
561 }
562 /* if the length of the line read is 2, then this is an empty line ("\n\r")*/
563 if(strlen(line) == 2){
564 if(object != NULL){
565 list_of_objects = g_slist_append(list_of_objects, object);
566 object = NULL;
567 }
568 }else{
569 /* if the line contains only the EOL sequence "\n\r" */
570 if(object == NULL && strlen(line) != 2){
571 object = (char *)malloc(strlen(line));
572 object = strdup(line);
573 }
574 else{
575 object = (char *)realloc(object, strlen(object) + strlen(line));
576 object = strcat(object, line);
577 }
578 }
579
580 }
581 fclose(input_file);
582
583 /* now, if at the very and of the input file there wasn't an
584 empty line, we have to add the remaining object in the 'object'
585 variable */
586 if(object != NULL){
587 //cout << "The object was" << endl << object << endl;
588 list_of_objects = g_slist_append(list_of_objects, object);
589 object = NULL;
590 }
591
592
593
594 if(tracing) {
595 printf("TRACING: Will process the objects in the list\n");
596 }
597 next = list_of_objects;
598 object_count = 0;
599 for( next = list_of_objects; next != NULL ; next = g_slist_next(next) ){
600 object_count++;
601
602 if(tracing) {
603 cout << "TRACING: Got an object from the list" << endl;
604 cout << (char *)next->data << endl;
605 }
606
607 if(has_ref_to_AUTO_nic_hdl((char *)next->data)){/* defer the processing */
608 if(tracing) {
609 printf("TRACING: this object has a ref to an AUTO NIC hdl\n");
610 }
611 list_of_objects2 = g_slist_append(list_of_objects2, strdup((char *)next->data));
612 }else{
613 result = 0;
614 result = process_object((char *)next->data, credentials, AUTO_NIC_hdl_hash, ack_file_name,
615 ntfy_hash, forw_hash, cross_hash);
616 }
617 }
618
619 if(tracing) {
620 printf("TRACING: list_of_objects2 has %d entries\n", g_slist_length(list_of_objects2));
621 }
622
623 if(tracing) {
624 printf("TRACING: will start to process the second list\n");
625 }
626
627 for( next = list_of_objects2; next != NULL ; next = g_slist_next(next) ){
628 if(tracing) {
629 printf("TRACING: Will process object: %s\n", (char *)next->data);
630 }
631 result = process_object((char *)next->data, credentials, AUTO_NIC_hdl_hash, ack_file_name,
632 ntfy_hash, forw_hash, cross_hash);
633 }
634
635 }
636
637 }/* process_file */
638
639
640
641
642
643
644 /* Generates a unique file name and returns the full path of the filename
645 for storing notification message. */
646
647 char * generate_upd_file(){
/* [<][>][^][v][top][bottom][index][help] */
648
649 char * name;
650
651 /* allocate space for name. 32 should be enough for PID */
652 name = (char*)malloc(strlen("/tmp/dbupdate-tmp.") + strlen("notify") +32 );
653
654 sprintf(name, "/tmp/dbupdate-tmp.%i", getpid());
655
656
657 return name;
658
659 }
660
661
662
663
664
665 /* main */
666 void main(int argc, char **argv, char **envp){
/* [<][>][^][v][top][bottom][index][help] */
667 //init_and_set_options(argc, argv, envp);
668
669 int count = 0;
670 int i,j;
671
672 char ** temp_vector;
673 char * temp;
674 char * temp_upd_file = NULL;
675 char *input_file_name = NULL;
676 GHashTable *AUTO_NIC_hdl_hash;
677 credentials_struct credentials;
678
679
680 GHashTable *ntfy_hash, *forw_hash, *cross_hash;
681
682
683 char *mail_command_line, * ack_file_name;
684 char *config_file_name = NULL;
685
686
687 /* for using MM module */
688 int retcode;
689 MM_header *mail_header = NULL;
690 MM_xmp_list *part_list;
691 MM_xmp *partptr;
692 long debug = 0;
693
694 /* optarg & optind are necessary to use getopt(3C) */
695 extern char *optarg;
696 extern int optind;
697
698
699 /* create notification hashes */
700 ntfy_hash = g_hash_table_new(g_str_hash, g_str_equal);
701 forw_hash = g_hash_table_new(g_str_hash, g_str_equal);
702
703
704 credentials.password_list = NULL;
705 credentials.from = NULL;
706 int ch;
707 char * to_address = NULL;
708
709 AUTO_NIC_hdl_hash = g_hash_table_new(g_str_hash, g_str_equal);
710 error_init(argc, argv);
711
712
713
714
715 while ((ch = getopt(argc, argv, "MtTf:c:")) != -1){
716 switch(ch) {
717 case 'M':
718 reading_from_mail = 1;
719 break;
720 case 'f':
721 input_file_name = strdup(optarg);
722 break;
723 case 'c':
724 config_file_name = strdup(optarg);
725 break;
726 case 't':
727 tracing = 1;
728 break;
729 case 'T':
730 test_mode = 1;
731 break;
732 case '?':
733 default:
734 printf("Unknown option\n");exit(1);
735 }
736 }
737
738
739 /* config stuff */
740 ca_populateDictionary(dictionary, VARS);
741 /* if -c flag is given, use the named file as config file, otherwise use
742 default filename */
743 if( config_file_name != NULL){
744 ca_readConfig(config_file_name, confVars, VARS);
745 }else{
746 ca_readConfig("dbupdate.conf", confVars, VARS);
747 }
748
749 tmpdir = ca_get_tmpdir;
750 tmpdir = g_strstrip(tmpdir);
751 mailcmd = ca_get_mailcmd;
752 mailcmd = g_strstrip(mailcmd);
753 notitxt = ca_get_notitxt;
754 mailtxt = ca_get_mailtxt;
755 crosslog = ca_get_crosslog;
756 fwtxt = ca_get_fwtxt;
757 humailbox = ca_get_humailbox;
758 humailbox = g_strstrip(humailbox);
759 overridecryptedpw = ca_get_overridecryptedpw;
760 overridecryptedpw = g_strstrip(overridecryptedpw);
761 acklog = ca_get_acklog;
762 acklog = g_strstrip(acklog);
763 notiflog = ca_get_notiflog;
764 notiflog = g_strstrip(notiflog);
765 notimailtxt = ca_get_notimailtxt;
766 forwlog = ca_get_forwlog;
767 forwlog = g_strstrip(forwlog);
768 fwmailtxt = ca_get_fwmailtxt;
769 country = ca_get_country;
770 pgppath = ca_get_pgppath;
771 pgppath = g_strstrip(pgppath);
772 pgp_public_key_ring = (char *)malloc(strlen(pgppath) + strlen("/pubring.gpg") + 2);
773 sprintf(pgp_public_key_ring ,"%s/pubring.gpg", pgppath);
774 if(test_mode != 1){/* if it is not already set to 1 (from command line), read from config */
775 test_mode = ca_get_testmode;
776 }
777 /* construct country array from country string variable */
778
779 temp_vector = g_strsplit(country, "\n", 0);
780 for(i=0, j=0; temp_vector[i] != NULL; i++){
781 temp_vector[i] == g_strstrip(temp_vector[i]);
782 if(strlen(temp_vector[i]) > 0){
783 countries[j] = strdup(temp_vector[i]);
784 g_strup(countries[j]);
785 printf("DEBUG: got a country country[%i] =.%s.,\n", j, countries[j]);
786 j++;
787 }
788 }
789 countries[j] = NULL; /* mark the end of array */
790 printf("DEBUG: countries[%i] = NULL\n", j);
791
792 #if 0
793 //test
794 tmpdir =strdup("/home/engin/REIMP/ncc/RIP/bin/dbupdate");
795 mailcmd=strdup("/usr/lib/sendmail -fbit-bucket -t");
796 notitxt=strdup(" Dear Colleague,
797
798 This is to notify you that some object(s) in the RIPE database
799 which you either maintain or are listed as to-be-notified have
800 been added, deleted or changed.
801
802 The objects below are the old and new entries for these objects
803 in the database. In case of DELETIONS, the deleted object is
804 displayed. NOOPs are not reported.");
805 mailtxt=strdup("");
806 crosslog=strdup("./crosslog");
807 fwtxt=strdup("Dear Maintainer,
808
809 This is to notify you that some objects in which you are mentioned as
810 a maintainer were requested to be changed, but *failed* the proper
811 authorisation for any of the mentioned maintainers.
812 Please contact the sender of these changes about changes that need
813 to be made to the following objects.
814 ");
815 humailbox=strdup("bit-bucket@ripe.net");
816 overridecryptedpw=strdup("ren5C38li6ADw");
817 acklog=strdup("./acklog");
818 notiflog=strdup("./notiflog");
819 notimailtxt=strdup("The update causing these changes had the following mail headers:
820
821 - From: $FROM
822 - Cc: $CC
823 - Subject: $SUBJECT
824 - Date: $MDATE
825 - Msg-Id: $MSGID
826
827 RIPE Database Notification Department");
828 forwlog=strdup("./forwlog");
829 fwmailtxt=strdup("The mail message causing these failures had the following mail headers:
830
831 - From: $FROM
832 - Cc: $CC
833 - Subject: $SUBJECT
834 - Date: $MDATE
835 - Msg-Id: $MSGID
836
837 RIPE Database Maintainer Forwarding Department");
838 pgppath=strdup("/home/engin/.gnupg");
839 pgp_public_key_ring =strdup("/home/engin/.gnupg/pubring.gpg");
840 country = strdup("NL\nEU");
841 temp_vector = g_strsplit(country, "\n", 0);
842 for(i=0, j=0; temp_vector[i] != NULL; i++){
843 temp_vector[i] == g_strstrip(temp_vector[i]);
844 if(strlen(temp_vector[i]) > 0){
845 countries[j] = strdup(temp_vector[i]);
846 g_strup(countries[j]);
847 printf("DEBUG: got a country country[%i] =.%s.,\n", j, countries[j]);
848 j++;
849 }
850 }
851 countries[j] = NULL; /* mark the end of array */
852
853 //end of test, delete later
854 #endif
855
856 printf("TMPDIR is: [%s]\n", tmpdir);
857 printf("MAILCMD is: [%s]\n", mailcmd);
858 printf("NOTITXT is: [%s]\n", notitxt);
859 printf("CROSSLOG is: [%s]\n", crosslog);
860 printf("FWTXT is: [%s]\n", fwtxt);
861 printf("HUMAILBOX is: [%s]\n", humailbox);
862 printf("OVERRIDECRYPTEDPW is: [%s]\n", overridecryptedpw);
863 printf("ACKLOG is: [%s]\n", acklog);
864 printf("NOTIFLOG is: [%s]\n", notiflog);
865 printf("FORWLOG is: [%s]\n", forwlog);
866 printf("NOTIMAILTXT is: [%s]\n", notimailtxt);
867 printf("FWMAILTXT is: [%s]\n", fwmailtxt);
868 printf("COUNTRY is: [%s]\n", country);
869 printf("PGPPATH is: [%s]\n", pgppath);
870
871 printf("TESTMODE is: [%i]\n", test_mode);
872 /* end of config stuff */
873
874
875
876 /* initialize the parser */
877 schema.initialize();
878
879
880 /* Generate a name for temporary file for storing acks (AK_ack_file_name_generate
881 also creates it) */
882 ack_file_name = AK_ack_file_name_generate(tmpdir, ACK_FILE_PREFIX);
883
884
885 /* Allocate memory for the header */
886 mail_header = (MM_header *)malloc(sizeof(MM_header));
887
888 /* Initialize the list of extracted MIME parts */
889 part_list = (MM_xmp_list *)malloc(sizeof(MM_xmp_list));
890 MM_xmp_list_init (part_list);
891
892
893 if(reading_from_mail){
894 if(input_file_name != NULL){
895 if((retcode = MM_decode(input_file_name, mail_header, part_list, 1, 0)) != 0){
896 printf("DEBUG: MM_decode returned %i\n", retcode);
897 exit(retcode);
898 }
899
900 }else{/* input_file_name == NULL */
901 temp_upd_file = generate_upd_file();
902 MM_store("-", temp_upd_file, 0);
903 if((retcode = MM_decode(temp_upd_file, mail_header, part_list, 1, 0)) != 0){
904 printf("DEBUG: MM_decode returned %i\n", retcode);
905 exit(retcode);
906 }
907
908 }
909 unlink(temp_upd_file);
910 printf ("Mail headers:\n\n");
911 printf ("From - [%s]",mail_header->from);
912 /* some MAIL-FROM's in mntner auths contain "From: " string too,
913 so we have to have it in credential.from */
914 temp = (char *)malloc(strlen(mail_header->from) + strlen("From: ") + 1);
915 sprintf(temp, "From: %s", mail_header->from);
916 temp[strlen(temp) - 4] = '\0'; /* cut two '\r\n's at the end */
917 credentials.from = temp;
918 printf ("credentials.from = [%s]\n", credentials.from );
919 mail_header->subject[strlen(mail_header->subject) - 4] = '\0';
920 printf ("Subject - [%s]",mail_header->subject);
921 printf ("Date - [%s]",mail_header->date);
922 printf ("Message-ID - [%s]",mail_header->message_id);
923 printf ("Reply-To - [%s]",mail_header->reply_to);
924 printf ("Cc - [%s]",mail_header->cc);
925 to_address = find_to_address(credentials.from);
926 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);
927 if(credentials.from != NULL){
928 AK_add_to_ack(ack_file_name, "\n[%s]\n", credentials.from);
929 }
930
931 partptr = part_list->head;
932 while (partptr != NULL){
933
934 printf("-----------------------------------------\n");
935 printf ("Section: %s\n",partptr->number);
936 printf ("Content-type: %s\n",partptr->type);
937 if (partptr->supported){
938 printf ("Supported\n");
939 printf ("Filename is [%s]\n", partptr->file);
940 process_file(partptr->file, credentials,
941 AUTO_NIC_hdl_hash, ack_file_name,
942 ntfy_hash, forw_hash, cross_hash);
943 }
944 else
945 printf ("Unsupported\n");
946 printf ("\n\n");
947 partptr = partptr->next;
948 }
949
950
951 /* Clean up the temporary files */
952 MM_cleanup(part_list, 0);
953
954
955 }else{/* not reading from the mail message */
956 if(input_file_name != NULL){
957 process_file(input_file_name, credentials,
958 AUTO_NIC_hdl_hash, ack_file_name,
959 ntfy_hash, forw_hash, cross_hash);
960 }
961
962 }
963
964
965 if(reading_from_mail && to_address != NULL){
966 AK_send_ack(ack_file_name, to_address, mailcmd);
967 }
968 AK_log_ack(ack_file_name, acklog);
969 AK_delete_ack(ack_file_name);
970
971 NT_send_ntfy_list(ntfy_hash, mailcmd);
972 NT_log_ntfy_list(ntfy_hash, notiflog);
973 NT_delete_ntfy_list(ntfy_hash);
974
975 NT_send_ntfy_list(forw_hash, mailcmd);
976 NT_log_ntfy_list(forw_hash, forwlog);
977 //NT_delete_ntfy_list(forw_hash);
978
979
980
981 if(tracing) {
982 printf("TRACING: END\n");
983 }
984
985
986 }