Imported Upstream version 2.5.1
[ossec-hids.git] / src / config / syscheck-config.c
1 /* @(#) $Id$ */
2
3 /* Copyright (C) 2009 Trend Micro Inc.
4  * All right reserved.
5  *
6  * This program is a free software; you can redistribute it
7  * and/or modify it under the terms of the GNU General Public
8  * License (version 2) as published by the FSF - Free Software
9  * Foundation
10  */
11
12
13 #include "shared.h"
14
15 #include "syscheck-config.h"
16
17
18
19 int dump_syscheck_entry(config *syscheck, char *entry, int vals, int reg, char *restrictfile)
20 {
21     int pl = 0;
22     
23     if(reg == 1)
24     {
25         #ifdef WIN32
26         if(syscheck->registry == NULL)
27         {
28             os_calloc(2, sizeof(char *), syscheck->registry);
29             syscheck->registry[pl + 1] = NULL;
30             os_strdup(entry, syscheck->registry[pl]);        
31         }
32         else
33         {
34             while(syscheck->registry[pl] != NULL)
35             {
36                 pl++;
37             }
38             os_realloc(syscheck->registry, (pl +2) * sizeof(char *), 
39                         syscheck->registry);
40             syscheck->registry[pl + 1] = NULL;
41             os_strdup(entry, syscheck->registry[pl]);
42         }
43         #endif
44         
45     }
46
47     
48     else
49     {
50         if(syscheck->dir == NULL)
51         {
52             os_calloc(2, sizeof(char *), syscheck->dir);
53             syscheck->dir[pl + 1] = NULL;
54             os_strdup(entry, syscheck->dir[pl]);
55
56             os_calloc(2, sizeof(int), syscheck->opts);
57             syscheck->opts[pl + 1] = 0;
58             syscheck->opts[pl] = vals;
59             
60             os_calloc(2, sizeof(OSMatch *), syscheck->filerestrict);
61             syscheck->filerestrict[pl] = NULL;
62             syscheck->filerestrict[pl + 1] = NULL;
63         }
64         else
65         {
66             while(syscheck->dir[pl] != NULL)
67             {
68                 pl++;
69             }
70             os_realloc(syscheck->dir, (pl +2) * sizeof(char *), 
71                        syscheck->dir);
72             syscheck->dir[pl + 1] = NULL;
73             os_strdup(entry, syscheck->dir[pl]);
74
75             os_realloc(syscheck->opts, (pl +2) * sizeof(int), 
76                        syscheck->opts);
77             syscheck->opts[pl + 1] = 0;
78             syscheck->opts[pl] = vals;         
79
80             os_realloc(syscheck->filerestrict, (pl +2) * sizeof(char *), 
81                        syscheck->filerestrict);
82             syscheck->filerestrict[pl] = NULL;
83             syscheck->filerestrict[pl + 1] = NULL;
84         }
85         if(restrictfile)
86         {
87             os_calloc(1, sizeof(OSMatch), syscheck->filerestrict[pl]);
88             if(!OSMatch_Compile(restrictfile, syscheck->filerestrict[pl], 0))
89             {
90                 OSMatch *ptm;
91
92                 ptm = syscheck->filerestrict[pl];
93
94                 merror(REGEX_COMPILE, ARGV0, restrictfile,
95                        ptm->error);
96                 free(syscheck->filerestrict[pl]);
97                 syscheck->filerestrict[pl] = NULL;
98             }
99         }
100     }
101
102     return(1);
103 }
104
105
106
107 /* Read Windows registry configuration */
108 #ifdef WIN32
109 int read_reg(config *syscheck, char *entries)
110 {
111     int i;
112     char **entry;
113     char *tmp_str;
114
115     
116     /* Getting each entry separately */
117     entry = OS_StrBreak(',', entries, MAX_DIR_SIZE); /* Max number */
118
119
120     /* entry can not be null */
121     if(entry == NULL)
122     {
123         return(0);
124     }
125
126
127     /* Doing it for each Entry */
128     while(*entry)
129     {
130         char *tmp_entry;
131
132         tmp_entry = *entry;
133
134         /* Removing spaces at the beginning */
135         while(*tmp_entry == ' ')
136         {
137             tmp_entry++;
138         }
139
140         /* Removing spaces at the end */
141         tmp_str = strchr(tmp_entry, ' ');
142         if(tmp_str)
143         {
144             tmp_str++;
145
146             /* Checking if it is really at the end */
147             if((*tmp_str == '\0') || (*tmp_str == ' '))
148             {
149                 tmp_str--;
150                 *tmp_str = '\0';
151             }
152         }
153
154
155         /* Adding entries - looking for the last available */
156         i = 0;
157         while(syscheck->registry && syscheck->registry[i])
158         {
159             int str_len_i;
160             int str_len_dir;
161             
162             str_len_dir = strlen(tmp_entry);
163             str_len_i = strlen(syscheck->registry[i]);
164             
165             if(str_len_dir > str_len_i)
166             {
167                 str_len_dir = str_len_i;
168             }
169
170             /* Duplicated entry */
171             if(strcmp(syscheck->registry[i], tmp_entry) == 0)
172             {
173                 merror(SK_DUP, ARGV0, tmp_entry);
174                 return(1);
175             }
176             i++;
177         }
178         
179         /* Adding new entry */
180         dump_syscheck_entry(syscheck, tmp_entry, 0, 1, NULL);
181         
182         
183         /* Next entry */
184         entry++;    
185     }
186     
187     return(1);
188 }
189 #endif /* For read_reg */
190
191
192
193
194 /* Read directories attributes */            
195 int read_attr(config *syscheck, char *dirs, char **g_attrs, char **g_values)
196 {
197     char *xml_check_all = "check_all";
198     char *xml_check_sum = "check_sum";
199     char *xml_check_sha1sum = "check_sha1sum";
200     char *xml_check_md5sum = "check_md5sum";
201     char *xml_check_size = "check_size";
202     char *xml_check_owner = "check_owner";
203     char *xml_check_group = "check_group";
204     char *xml_check_perm = "check_perm";
205     char *xml_real_time = "realtime";
206     char *xml_report_changes = "report_changes";
207     char *xml_restrict = "restrict";
208
209     char *restrictfile = NULL;
210     char **dir;
211     char *tmp_str;
212     dir = OS_StrBreak(',', dirs, MAX_DIR_SIZE); /* Max number */
213
214     /* Dir can not be null */
215     if(dir == NULL)
216     {
217         return(0);
218     }
219
220
221     /* Doing it for each directory */
222     while(*dir)
223     {
224         int i = 0;
225         int opts = 0;
226         char *tmp_dir;
227
228         char **attrs = NULL;
229         char **values = NULL;
230         
231         tmp_dir = *dir;
232         restrictfile = NULL;
233
234         /* Removing spaces at the beginning */
235         while(*tmp_dir == ' ')
236         {
237             tmp_dir++;
238         }
239
240         /* Removing spaces at the end */
241         tmp_str = strchr(tmp_dir, ' ');
242         if(tmp_str)
243         {
244             tmp_str++;
245
246             /* Checking if it is really at the end */
247             if((*tmp_str == '\0') || (*tmp_str == ' '))
248             {
249                 tmp_str--;
250                 *tmp_str = '\0';
251             }
252         }
253
254
255         /* Getting the options */
256         if(!g_attrs || !g_values)
257         {
258             merror(SYSCHECK_NO_OPT, ARGV0, dirs);
259             return(0);
260         }
261
262         attrs = g_attrs;
263         values = g_values;
264
265         while(*attrs && *values)
266         {
267             /* Checking all */
268             if(strcmp(*attrs, xml_check_all) == 0)
269             {
270                 if(strcmp(*values, "yes") == 0)
271                 {
272                     opts|=CHECK_MD5SUM;
273                     opts|=CHECK_SHA1SUM;
274                     opts|=CHECK_PERM;
275                     opts|=CHECK_SIZE;
276                     opts|=CHECK_OWNER;
277                     opts|=CHECK_GROUP;
278                 }
279                 else if(strcmp(*values, "no") == 0)
280                 {
281                 }
282                 else
283                 {
284                     merror(SK_INV_OPT, ARGV0, *values, *attrs);
285                     return(0);
286                 }
287             }
288             /* Checking sum */
289             else if(strcmp(*attrs, xml_check_sum) == 0)
290             {
291                 if(strcmp(*values, "yes") == 0)
292                 {
293                     opts|=CHECK_MD5SUM;
294                     opts|=CHECK_SHA1SUM;
295                 }
296                 else if(strcmp(*values, "no") == 0)
297                 {
298                 }
299                 else
300                 {
301                     merror(SK_INV_OPT, ARGV0, *values, *attrs);
302                     return(0);
303                 }
304             }
305             /* Checking md5sum */
306             else if(strcmp(*attrs, xml_check_md5sum) == 0)
307             {
308                 if(strcmp(*values, "yes") == 0)
309                 {
310                     opts|=CHECK_MD5SUM;
311                 }
312                 else if(strcmp(*values, "no") == 0)
313                 {
314                 }
315                 else
316                 {
317                     merror(SK_INV_OPT, ARGV0, *values, *attrs);
318                     return(0);
319                 }
320             }
321             /* Checking sha1sum */
322             else if(strcmp(*attrs, xml_check_sha1sum) == 0)
323             {
324                 if(strcmp(*values, "yes") == 0)
325                 {
326                     opts|=CHECK_SHA1SUM;
327                 }
328                 else if(strcmp(*values, "no") == 0)
329                 {
330                 }
331                 else
332                 {
333                     merror(SK_INV_OPT, ARGV0, *values, *attrs);
334                     return(0);
335                 }
336             }
337             /* Checking permission */
338             else if(strcmp(*attrs, xml_check_perm) == 0)
339             {
340                 if(strcmp(*values, "yes") == 0)
341                 {
342                     opts|=CHECK_PERM;
343                 }
344                 else if(strcmp(*values, "no") == 0)
345                 {
346                 }
347                 else
348                 {
349                     merror(SK_INV_OPT, ARGV0, *values, *attrs);
350                     return(0);
351                 }
352             }
353             /* Checking size */
354             else if(strcmp(*attrs, xml_check_size) == 0)
355             {
356                 if(strcmp(*values, "yes") == 0)
357                 {
358                     opts|=CHECK_SIZE;
359                 }
360                 else if(strcmp(*values, "no") == 0)
361                 {
362                 }
363                 else
364                 {
365                     merror(SK_INV_OPT, ARGV0, *values, *attrs);
366                     return(0);
367                 }
368             }
369             /* Checking owner */
370             else if(strcmp(*attrs, xml_check_owner) == 0)
371             {
372                 if(strcmp(*values, "yes") == 0)
373                 {
374                     opts|=CHECK_OWNER;
375                 }
376                 else if(strcmp(*values, "no") == 0)
377                 {
378                 }
379                 else
380                 {
381                     merror(SK_INV_OPT, ARGV0, *values, *attrs);
382                     return(0);
383                 }
384             }
385             /* Checking group */
386             else if(strcmp(*attrs, xml_check_group) == 0)
387             {
388                 if(strcmp(*values, "yes") == 0)
389                 {
390                     opts|=CHECK_GROUP;
391                 }
392                 else if(strcmp(*values, "no") == 0)
393                 {
394                 }
395                 else
396                 {
397                     merror(SK_INV_OPT, ARGV0, *values, *attrs);
398                     return(0);
399                 }
400             }
401             else if(strcmp(*attrs, xml_real_time) == 0)
402             {
403                 if(strcmp(*values, "yes") == 0)
404                 {
405                     opts|=CHECK_REALTIME;
406                 }
407                 else if(strcmp(*values, "no") == 0)
408                 {
409                 }
410                 else
411                 {
412                     merror(SK_INV_OPT, ARGV0, *values, *attrs);
413                     return(0);
414                 }
415             }
416             else if(strcmp(*attrs, xml_report_changes) == 0)
417             {
418                 if(strcmp(*values, "yes") == 0)
419                 {
420                     opts|=CHECK_SEECHANGES;
421                 }
422                 else if(strcmp(*values, "no") == 0)
423                 {
424                 }
425                 else
426                 {
427                     merror(SK_INV_OPT, ARGV0, *values, *attrs);
428                     return(0);
429                 }
430             }
431             else if(strcmp(*attrs, xml_restrict) == 0)
432             {
433                 os_strdup(*values, restrictfile);
434             }
435             else
436             {
437                 merror(SK_INV_ATTR, ARGV0, *attrs);
438                 return(0);
439             }
440             attrs++; values++;
441         }
442
443
444         /* You must have something set */
445         if(opts == 0)
446         {
447             merror(SYSCHECK_NO_OPT, ARGV0, dirs);
448             if(restrictfile) free(restrictfile);
449             return(0);
450         }
451         
452         
453         /* Adding directory - looking for the last available */
454         i = 0;
455         while(syscheck->dir && syscheck->dir[i])
456         {
457             int str_len_i;
458             int str_len_dir;
459             
460             str_len_dir = strlen(tmp_dir);
461             str_len_i = strlen(syscheck->dir[i]);
462             
463             if(str_len_dir > str_len_i)
464             {
465                 str_len_dir = str_len_i;
466             }
467
468             /* Duplicate entry */
469             if(strcmp(syscheck->dir[i], tmp_dir) == 0)
470             {
471                 merror(SK_DUP, ARGV0, tmp_dir);
472                 return(1);
473             }
474
475             i++;
476         }
477
478
479         /* Checking for glob. */
480         #ifndef WIN32
481         if(strchr(tmp_dir, '*') ||
482            strchr(tmp_dir, '?') ||
483            strchr(tmp_dir, '['))
484         {
485             int gindex = 0;
486             glob_t g;
487
488             if(glob(tmp_dir, 0, NULL, &g) != 0)
489             {
490                 merror(GLOB_ERROR, ARGV0, tmp_dir);
491                 return(1);
492             }
493
494             if(g.gl_pathv[0] == NULL)
495             {
496                 merror(GLOB_NFOUND, ARGV0, tmp_dir);
497                 return(1);
498             }
499             
500             while(g.gl_pathv[gindex])
501             {
502                 dump_syscheck_entry(syscheck, g.gl_pathv[gindex], opts, 0, restrictfile);
503                 gindex++;
504             }
505             
506             globfree(&g);
507         }
508
509         else
510         {
511             dump_syscheck_entry(syscheck, tmp_dir, opts, 0, restrictfile);
512         }
513         #else
514         dump_syscheck_entry(syscheck, tmp_dir, opts, 0, restrictfile);
515         #endif
516
517         if(restrictfile)
518         {
519             free(restrictfile);
520             restrictfile = NULL;
521         }
522         
523         
524         /* Next entry */
525         dir++;    
526     }
527     
528     return(1);
529 }
530
531
532
533 int Read_Syscheck(XML_NODE node, void *configp, void *mailp)
534 {
535     int i = 0;
536
537     /* XML Definitions */
538     char *xml_directories = "directories";
539     char *xml_registry = "windows_registry";
540     char *xml_time = "frequency";
541     char *xml_scanday = "scan_day";
542     char *xml_scantime = "scan_time";
543     char *xml_ignore = "ignore";
544     char *xml_registry_ignore = "registry_ignore";
545     char *xml_auto_ignore = "auto_ignore";
546     char *xml_alert_new_files = "alert_new_files";
547     char *xml_disabled = "disabled";
548     char *xml_scan_on_start = "scan_on_start";
549
550     /* Configuration example 
551     <directories check_all="yes">/etc,/usr/bin</directories>
552     <directories check_owner="yes" check_group="yes" check_perm="yes" 
553     check_sum="yes">/var/log</directories>
554     */
555
556     config *syscheck;
557
558     syscheck = (config *)configp;
559     
560     
561     while(node[i])
562     {
563         if(!node[i]->element)
564         {
565             merror(XML_ELEMNULL, ARGV0);
566             return(OS_INVALID);
567         }
568         else if(!node[i]->content)
569         {
570             merror(XML_VALUENULL, ARGV0, node[i]->element);
571             return(OS_INVALID);
572         }
573
574         /* Getting directories */
575         else if(strcmp(node[i]->element,xml_directories) == 0)
576         {
577             char dirs[OS_MAXSTR];
578             
579             #ifdef WIN32
580             ExpandEnvironmentStrings(node[i]->content, dirs, sizeof(dirs) -1);
581             #else
582             strncpy(dirs, node[i]->content, sizeof(dirs) -1);
583             #endif
584             
585             if(!read_attr(syscheck,
586                         dirs, 
587                         node[i]->attributes, 
588                         node[i]->values))
589             {
590                 return(OS_INVALID);
591             }
592         }
593         /* Getting windows registry */
594         else if(strcmp(node[i]->element,xml_registry) == 0)
595         {
596             #ifdef WIN32
597             if(!read_reg(syscheck, node[i]->content))
598             {
599                 return(OS_INVALID);
600             }
601             #endif
602         }
603         /* Getting frequency */
604         else if(strcmp(node[i]->element,xml_time) == 0)
605         {        
606             if(!OS_StrIsNum(node[i]->content))
607             {
608                 merror(XML_VALUEERR,ARGV0,node[i]->element,node[i]->content);
609                 return(OS_INVALID);
610             }
611
612             syscheck->time = atoi(node[i]->content);
613         }
614         /* Getting scan time */
615         else if(strcmp(node[i]->element,xml_scantime) == 0)
616         {
617             syscheck->scan_time = OS_IsValidUniqueTime(node[i]->content);
618             if(!syscheck->scan_time)
619             {
620                 merror(XML_VALUEERR,ARGV0,node[i]->element,node[i]->content);
621                 return(OS_INVALID);
622             }
623         }
624
625         /* Getting scan day */
626         else if(strcmp(node[i]->element,xml_scanday) == 0)
627         {
628             syscheck->scan_day = OS_IsValidDay(node[i]->content);
629             if(!syscheck->scan_day)
630             {
631                 merror(XML_VALUEERR,ARGV0,node[i]->element,node[i]->content);
632                 return(OS_INVALID);
633             }
634         }
635     
636         /* Getting if xml_scan_on_start. */
637         else if(strcmp(node[i]->element, xml_scan_on_start) == 0)
638         {
639             if(strcmp(node[i]->content, "yes") == 0)
640                 syscheck->scan_on_start = 1;
641             else if(strcmp(node[i]->content, "no") == 0)
642                 syscheck->scan_on_start = 0;
643             else
644             {
645                 merror(XML_VALUEERR,ARGV0, node[i]->element, node[i]->content);
646                 return(OS_INVALID);
647             }
648         }
649         
650         /* Getting if disabled. */
651         else if(strcmp(node[i]->element,xml_disabled) == 0)
652         {
653             if(strcmp(node[i]->content, "yes") == 0)
654                 syscheck->disabled = 1;
655             else if(strcmp(node[i]->content, "no") == 0)
656                 syscheck->disabled = 0;
657             else
658             {
659                 merror(XML_VALUEERR,ARGV0,node[i]->element,node[i]->content);
660                 return(OS_INVALID);
661             }
662         }
663         
664         /* Getting file/dir ignore */
665         else if(strcmp(node[i]->element,xml_ignore) == 0)
666         {
667             int ign_size = 0;
668
669             /* For Windows, we attempt to expand environment variables. */
670             #ifdef WIN32
671             char *new_ig = NULL;
672             os_calloc(2048, sizeof(char), new_ig);
673             
674             ExpandEnvironmentStrings(node[i]->content, new_ig, 2047);        
675
676             free(node[i]->content);
677             node[i]->content = new_ig;
678             #endif
679             
680             /* Adding if regex */
681             if(node[i]->attributes && node[i]->values)
682             {
683                 if(node[i]->attributes[0] && node[i]->values[0] &&
684                    (strcmp(node[i]->attributes[0], "type") == 0) && 
685                    (strcmp(node[i]->values[0], "sregex") == 0))
686                 {
687                     OSMatch *mt_pt;
688                     
689                     if(!syscheck->ignore_regex)
690                     {
691                         os_calloc(2, sizeof(OSMatch *),syscheck->ignore_regex);
692                         syscheck->ignore_regex[0] = NULL;
693                         syscheck->ignore_regex[1] = NULL;
694                     }
695                     else
696                     {
697                         while(syscheck->ignore_regex[ign_size] != NULL)
698                             ign_size++;
699
700                         os_realloc(syscheck->ignore_regex,
701                                 sizeof(OSMatch *)*(ign_size +2),
702                                 syscheck->ignore_regex);
703                         syscheck->ignore_regex[ign_size +1] = NULL;
704                     }
705                     os_calloc(1, sizeof(OSMatch), 
706                             syscheck->ignore_regex[ign_size]);
707
708                     if(!OSMatch_Compile(node[i]->content,
709                                         syscheck->ignore_regex[ign_size], 0))
710                     {
711                         mt_pt = (OSMatch *)syscheck->ignore_regex[ign_size];
712                         merror(REGEX_COMPILE, ARGV0, node[i]->content,
713                               mt_pt->error);
714                         return(0);
715                     }
716                 }
717                 else
718                 {
719                     merror(SK_INV_ATTR, ARGV0, node[i]->attributes[0]);
720                     return(OS_INVALID);
721                 }
722             }
723
724             /* Adding if simple entry -- checking for duplicates */
725             else if(!os_IsStrOnArray(node[i]->content, syscheck->ignore))
726             {
727                 if(!syscheck->ignore)
728                 {
729                     os_calloc(2, sizeof(char *), syscheck->ignore);
730                     syscheck->ignore[0] = NULL;
731                     syscheck->ignore[1] = NULL;
732                 }
733                 else
734                 {
735                     while(syscheck->ignore[ign_size] != NULL)
736                         ign_size++;
737
738                     os_realloc(syscheck->ignore, 
739                             sizeof(char *)*(ign_size +2),
740                             syscheck->ignore);
741                     syscheck->ignore[ign_size +1] = NULL;
742                 }
743                 os_strdup(node[i]->content,syscheck->ignore[ign_size]);
744             }
745         }
746
747         /* Getting registry ignore list */
748         else if(strcmp(node[i]->element,xml_registry_ignore) == 0)
749         {
750             #ifdef WIN32
751             int ign_size = 0;
752
753             /* Adding if regex */
754             if(node[i]->attributes && node[i]->values)
755             {
756                 if(node[i]->attributes[0] && node[i]->values[0] &&
757                    (strcmp(node[i]->attributes[0], "type") == 0) &&
758                    (strcmp(node[i]->values[0], "sregex") == 0))
759                 {
760                     OSMatch *mt_pt;
761
762                     if(!syscheck->registry_ignore_regex)
763                     {
764                         os_calloc(2, sizeof(OSMatch *),
765                                      syscheck->registry_ignore_regex);
766                         syscheck->registry_ignore_regex[0] = NULL;
767                         syscheck->registry_ignore_regex[1] = NULL;
768                     }
769                     else
770                     {
771                         while(syscheck->registry_ignore_regex[ign_size] !=NULL)
772                             ign_size++;
773
774                         os_realloc(syscheck->registry_ignore_regex,
775                                 sizeof(OSMatch *)*(ign_size +2),
776                                 syscheck->registry_ignore_regex);
777                         syscheck->registry_ignore_regex[ign_size +1] = NULL;
778                     }
779                     
780                     os_calloc(1, sizeof(OSMatch),
781                             syscheck->registry_ignore_regex[ign_size]);
782
783                     if(!OSMatch_Compile(node[i]->content,
784                                 syscheck->registry_ignore_regex[ign_size], 0))
785                     {
786                         mt_pt = (OSMatch *)
787                                 syscheck->registry_ignore_regex[ign_size];
788                         merror(REGEX_COMPILE, ARGV0, node[i]->content,
789                              mt_pt->error);
790                         return(0);
791                     }
792                 }
793                 else
794                 {
795                     merror(SK_INV_ATTR, ARGV0, node[i]->attributes[0]);
796                     return(OS_INVALID);
797                 }
798             }
799             /* We do not add duplicated entries */
800             else if(!os_IsStrOnArray(node[i]->content, 
801                      syscheck->registry_ignore))
802             {
803                 if(!syscheck->registry_ignore)
804                 {
805                     os_calloc(2, sizeof(char *), syscheck->registry_ignore);
806                     syscheck->registry_ignore[0] = NULL;
807                     syscheck->registry_ignore[1] = NULL;
808                 }
809                 else
810                 {
811                     while(syscheck->registry_ignore[ign_size] != NULL)
812                         ign_size++;
813
814                     os_realloc(syscheck->registry_ignore,
815                             sizeof(char *)*(ign_size +2),
816                             syscheck->registry_ignore);
817                     syscheck->registry_ignore[ign_size +1] = NULL;
818                 }
819                 os_strdup(node[i]->content,syscheck->registry_ignore[ign_size]);
820             }
821             #endif
822         }
823         else if(strcmp(node[i]->element,xml_auto_ignore) == 0)
824         {
825             /* auto_ignore is not read here. */
826         }
827         else if(strcmp(node[i]->element,xml_alert_new_files) == 0)
828         {
829             /* alert_new_files option is not read here. */
830         }
831         else
832         {
833             merror(XML_INVELEM, ARGV0, node[i]->element);
834             return(OS_INVALID);
835         }
836         i++;
837     } 
838     
839     return(0);
840 }