Browse code

clamonacc - reorganize/restructure onaccess layout into component pieces for easier maintenance, future design reworks, and general conceptualization of code flow

Mickey Sola authored on 2019/02/21 08:31:11
Showing 31 changed files
... ...
@@ -36,20 +36,20 @@ clamonacc_SOURCES = \
36 36
     $(top_srcdir)/shared/clamdcom.c \
37 37
     $(top_srcdir)/shared/clamdcom.h \
38 38
     clamonacc.c \
39
-    onaccess_client.c \
40
-    onaccess_client.h \
41
-    onaccess_proto.c \
42
-    onaccess_proto.h \
43
-    onaccess_ddd.c \
44
-    onaccess_ddd.h \
45
-    onaccess_fan.c \
46
-    onaccess_fan.h \
47
-    onaccess_hash.c \
48
-    onaccess_hash.h \
49
-    onaccess_others.c \
50
-    onaccess_others.h \
51
-    onaccess_scth.c \
52
-    onaccess_scth.h
39
+    ./client/onaccess_client.c \
40
+    ./client/onaccess_client.h \
41
+    ./client/onaccess_proto.c \
42
+    ./client/onaccess_proto.h \
43
+    ./inotif/onaccess_ddd.c \
44
+    ./inotif/onaccess_ddd.h \
45
+    ./fanotif/onaccess_fan.c \
46
+    ./fanotif/onaccess_fan.h \
47
+    ./inotif/onaccess_hash.c \
48
+    ./inotif/onaccess_hash.h \
49
+    ./misc/onaccess_others.c \
50
+    ./misc/onaccess_others.h \
51
+    ./scan/onaccess_scth.c \
52
+    ./scan/onaccess_scth.h
53 53
 
54 54
 AM_CFLAGS=@WERR_CFLAGS@
55 55
 endif
... ...
@@ -203,11 +203,14 @@ am__clamonacc_SOURCES_DIST = $(top_srcdir)/shared/output.c \
203 203
 	$(top_srcdir)/shared/misc.h $(top_srcdir)/shared/getopt.c \
204 204
 	$(top_srcdir)/shared/getopt.h $(top_srcdir)/shared/actions.c \
205 205
 	$(top_srcdir)/shared/actions.h $(top_srcdir)/shared/clamdcom.c \
206
-	$(top_srcdir)/shared/clamdcom.h clamonacc.c onaccess_client.c \
207
-	onaccess_client.h onaccess_proto.c onaccess_proto.h \
208
-	onaccess_ddd.c onaccess_ddd.h onaccess_fan.c onaccess_fan.h \
209
-	onaccess_hash.c onaccess_hash.h onaccess_others.c \
210
-	onaccess_others.h onaccess_scth.c onaccess_scth.h
206
+	$(top_srcdir)/shared/clamdcom.h clamonacc.c \
207
+	./client/onaccess_client.c ./client/onaccess_client.h \
208
+	./client/onaccess_proto.c ./client/onaccess_proto.h \
209
+	./inotif/onaccess_ddd.c ./inotif/onaccess_ddd.h \
210
+	./fanotif/onaccess_fan.c ./fanotif/onaccess_fan.h \
211
+	./inotif/onaccess_hash.c ./inotif/onaccess_hash.h \
212
+	./misc/onaccess_others.c ./misc/onaccess_others.h \
213
+	./scan/onaccess_scth.c ./scan/onaccess_scth.h
211 214
 @BUILD_CLAMD_TRUE@am_clamonacc_OBJECTS = output.$(OBJEXT) \
212 215
 @BUILD_CLAMD_TRUE@	optparser.$(OBJEXT) misc.$(OBJEXT) \
213 216
 @BUILD_CLAMD_TRUE@	getopt.$(OBJEXT) actions.$(OBJEXT) \
... ...
@@ -238,9 +241,8 @@ am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
238 238
 am__v_at_0 = @
239 239
 am__v_at_1 = 
240 240
 DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) -I$(top_builddir)/libclammspack
241
-depcomp = $(SHELL) $(top_srcdir)/config/depcomp
242
-am__depfiles_maybe = depfiles
243
-am__mv = mv -f
241
+depcomp =
242
+am__depfiles_maybe =
244 243
 COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
245 244
 	$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
246 245
 LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
... ...
@@ -285,7 +287,7 @@ am__define_uniq_tagged_files = \
285 285
   done | $(am__uniquify_input)`
286 286
 ETAGS = etags
287 287
 CTAGS = ctags
288
-am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/config/depcomp
288
+am__DIST_COMMON = $(srcdir)/Makefile.in
289 289
 DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
290 290
 ACLOCAL = @ACLOCAL@
291 291
 AMTAR = @AMTAR@
... ...
@@ -531,20 +533,20 @@ top_srcdir = @top_srcdir@
531 531
 @BUILD_CLAMD_TRUE@    $(top_srcdir)/shared/clamdcom.c \
532 532
 @BUILD_CLAMD_TRUE@    $(top_srcdir)/shared/clamdcom.h \
533 533
 @BUILD_CLAMD_TRUE@    clamonacc.c \
534
-@BUILD_CLAMD_TRUE@    onaccess_client.c \
535
-@BUILD_CLAMD_TRUE@    onaccess_client.h \
536
-@BUILD_CLAMD_TRUE@    onaccess_proto.c \
537
-@BUILD_CLAMD_TRUE@    onaccess_proto.h \
538
-@BUILD_CLAMD_TRUE@    onaccess_ddd.c \
539
-@BUILD_CLAMD_TRUE@    onaccess_ddd.h \
540
-@BUILD_CLAMD_TRUE@    onaccess_fan.c \
541
-@BUILD_CLAMD_TRUE@    onaccess_fan.h \
542
-@BUILD_CLAMD_TRUE@    onaccess_hash.c \
543
-@BUILD_CLAMD_TRUE@    onaccess_hash.h \
544
-@BUILD_CLAMD_TRUE@    onaccess_others.c \
545
-@BUILD_CLAMD_TRUE@    onaccess_others.h \
546
-@BUILD_CLAMD_TRUE@    onaccess_scth.c \
547
-@BUILD_CLAMD_TRUE@    onaccess_scth.h
534
+@BUILD_CLAMD_TRUE@    ./client/onaccess_client.c \
535
+@BUILD_CLAMD_TRUE@    ./client/onaccess_client.h \
536
+@BUILD_CLAMD_TRUE@    ./client/onaccess_proto.c \
537
+@BUILD_CLAMD_TRUE@    ./client/onaccess_proto.h \
538
+@BUILD_CLAMD_TRUE@    ./inotif/onaccess_ddd.c \
539
+@BUILD_CLAMD_TRUE@    ./inotif/onaccess_ddd.h \
540
+@BUILD_CLAMD_TRUE@    ./fanotif/onaccess_fan.c \
541
+@BUILD_CLAMD_TRUE@    ./fanotif/onaccess_fan.h \
542
+@BUILD_CLAMD_TRUE@    ./inotif/onaccess_hash.c \
543
+@BUILD_CLAMD_TRUE@    ./inotif/onaccess_hash.h \
544
+@BUILD_CLAMD_TRUE@    ./misc/onaccess_others.c \
545
+@BUILD_CLAMD_TRUE@    ./misc/onaccess_others.h \
546
+@BUILD_CLAMD_TRUE@    ./scan/onaccess_scth.c \
547
+@BUILD_CLAMD_TRUE@    ./scan/onaccess_scth.h
548 548
 
549 549
 @BUILD_CLAMD_TRUE@AM_CFLAGS = @WERR_CFLAGS@
550 550
 AM_CPPFLAGS = -I$(top_srcdir) -I$(top_srcdir)/clamd -I$(top_srcdir)/shared -I$(top_srcdir)/libclamav @SSL_CPPFLAGS@ @CLAMONACC_CPPFLAGS@ @JSON_CPPFLAGS@ @PCRE_CPPFLAGS@
... ...
@@ -563,9 +565,9 @@ $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am  $(am__confi
563 563
 	      exit 1;; \
564 564
 	  esac; \
565 565
 	done; \
566
-	echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign clamonacc/Makefile'; \
566
+	echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign --ignore-deps clamonacc/Makefile'; \
567 567
 	$(am__cd) $(top_srcdir) && \
568
-	  $(AUTOMAKE) --foreign clamonacc/Makefile
568
+	  $(AUTOMAKE) --foreign --ignore-deps clamonacc/Makefile
569 569
 Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
570 570
 	@case '$?' in \
571 571
 	  *config.status*) \
... ...
@@ -659,125 +661,92 @@ mostlyclean-compile:
659 659
 distclean-compile:
660 660
 	-rm -f *.tab.c
661 661
 
662
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/actions.Po@am__quote@
663
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/clamdcom.Po@am__quote@
664
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/clamonacc.Po@am__quote@
665
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/getopt.Po@am__quote@
666
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/misc.Po@am__quote@
667
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/onaccess_client.Po@am__quote@
668
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/onaccess_ddd.Po@am__quote@
669
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/onaccess_fan.Po@am__quote@
670
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/onaccess_hash.Po@am__quote@
671
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/onaccess_others.Po@am__quote@
672
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/onaccess_proto.Po@am__quote@
673
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/onaccess_scth.Po@am__quote@
674
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/optparser.Po@am__quote@
675
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/output.Po@am__quote@
676
-
677 662
 .c.o:
678
-@am__fastdepCC_TRUE@	$(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
679
-@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
680
-@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
681
-@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
682
-@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $<
663
+	$(AM_V_CC)$(COMPILE) -c -o $@ $<
683 664
 
684 665
 .c.obj:
685
-@am__fastdepCC_TRUE@	$(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
686
-@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
687
-@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
688
-@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
689
-@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
666
+	$(AM_V_CC)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
690 667
 
691 668
 .c.lo:
692
-@am__fastdepCC_TRUE@	$(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
693
-@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
694
-@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
695
-@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
696
-@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $<
669
+	$(AM_V_CC)$(LTCOMPILE) -c -o $@ $<
697 670
 
698 671
 output.o: $(top_srcdir)/shared/output.c
699
-@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT output.o -MD -MP -MF $(DEPDIR)/output.Tpo -c -o output.o `test -f '$(top_srcdir)/shared/output.c' || echo '$(srcdir)/'`$(top_srcdir)/shared/output.c
700
-@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/output.Tpo $(DEPDIR)/output.Po
701
-@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='$(top_srcdir)/shared/output.c' object='output.o' libtool=no @AMDEPBACKSLASH@
702
-@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
703
-@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o output.o `test -f '$(top_srcdir)/shared/output.c' || echo '$(srcdir)/'`$(top_srcdir)/shared/output.c
672
+	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o output.o `test -f '$(top_srcdir)/shared/output.c' || echo '$(srcdir)/'`$(top_srcdir)/shared/output.c
704 673
 
705 674
 output.obj: $(top_srcdir)/shared/output.c
706
-@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT output.obj -MD -MP -MF $(DEPDIR)/output.Tpo -c -o output.obj `if test -f '$(top_srcdir)/shared/output.c'; then $(CYGPATH_W) '$(top_srcdir)/shared/output.c'; else $(CYGPATH_W) '$(srcdir)/$(top_srcdir)/shared/output.c'; fi`
707
-@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/output.Tpo $(DEPDIR)/output.Po
708
-@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='$(top_srcdir)/shared/output.c' object='output.obj' libtool=no @AMDEPBACKSLASH@
709
-@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
710
-@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o output.obj `if test -f '$(top_srcdir)/shared/output.c'; then $(CYGPATH_W) '$(top_srcdir)/shared/output.c'; else $(CYGPATH_W) '$(srcdir)/$(top_srcdir)/shared/output.c'; fi`
675
+	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o output.obj `if test -f '$(top_srcdir)/shared/output.c'; then $(CYGPATH_W) '$(top_srcdir)/shared/output.c'; else $(CYGPATH_W) '$(srcdir)/$(top_srcdir)/shared/output.c'; fi`
711 676
 
712 677
 optparser.o: $(top_srcdir)/shared/optparser.c
713
-@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT optparser.o -MD -MP -MF $(DEPDIR)/optparser.Tpo -c -o optparser.o `test -f '$(top_srcdir)/shared/optparser.c' || echo '$(srcdir)/'`$(top_srcdir)/shared/optparser.c
714
-@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/optparser.Tpo $(DEPDIR)/optparser.Po
715
-@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='$(top_srcdir)/shared/optparser.c' object='optparser.o' libtool=no @AMDEPBACKSLASH@
716
-@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
717
-@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o optparser.o `test -f '$(top_srcdir)/shared/optparser.c' || echo '$(srcdir)/'`$(top_srcdir)/shared/optparser.c
678
+	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o optparser.o `test -f '$(top_srcdir)/shared/optparser.c' || echo '$(srcdir)/'`$(top_srcdir)/shared/optparser.c
718 679
 
719 680
 optparser.obj: $(top_srcdir)/shared/optparser.c
720
-@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT optparser.obj -MD -MP -MF $(DEPDIR)/optparser.Tpo -c -o optparser.obj `if test -f '$(top_srcdir)/shared/optparser.c'; then $(CYGPATH_W) '$(top_srcdir)/shared/optparser.c'; else $(CYGPATH_W) '$(srcdir)/$(top_srcdir)/shared/optparser.c'; fi`
721
-@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/optparser.Tpo $(DEPDIR)/optparser.Po
722
-@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='$(top_srcdir)/shared/optparser.c' object='optparser.obj' libtool=no @AMDEPBACKSLASH@
723
-@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
724
-@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o optparser.obj `if test -f '$(top_srcdir)/shared/optparser.c'; then $(CYGPATH_W) '$(top_srcdir)/shared/optparser.c'; else $(CYGPATH_W) '$(srcdir)/$(top_srcdir)/shared/optparser.c'; fi`
681
+	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o optparser.obj `if test -f '$(top_srcdir)/shared/optparser.c'; then $(CYGPATH_W) '$(top_srcdir)/shared/optparser.c'; else $(CYGPATH_W) '$(srcdir)/$(top_srcdir)/shared/optparser.c'; fi`
725 682
 
726 683
 misc.o: $(top_srcdir)/shared/misc.c
727
-@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT misc.o -MD -MP -MF $(DEPDIR)/misc.Tpo -c -o misc.o `test -f '$(top_srcdir)/shared/misc.c' || echo '$(srcdir)/'`$(top_srcdir)/shared/misc.c
728
-@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/misc.Tpo $(DEPDIR)/misc.Po
729
-@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='$(top_srcdir)/shared/misc.c' object='misc.o' libtool=no @AMDEPBACKSLASH@
730
-@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
731
-@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o misc.o `test -f '$(top_srcdir)/shared/misc.c' || echo '$(srcdir)/'`$(top_srcdir)/shared/misc.c
684
+	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o misc.o `test -f '$(top_srcdir)/shared/misc.c' || echo '$(srcdir)/'`$(top_srcdir)/shared/misc.c
732 685
 
733 686
 misc.obj: $(top_srcdir)/shared/misc.c
734
-@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT misc.obj -MD -MP -MF $(DEPDIR)/misc.Tpo -c -o misc.obj `if test -f '$(top_srcdir)/shared/misc.c'; then $(CYGPATH_W) '$(top_srcdir)/shared/misc.c'; else $(CYGPATH_W) '$(srcdir)/$(top_srcdir)/shared/misc.c'; fi`
735
-@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/misc.Tpo $(DEPDIR)/misc.Po
736
-@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='$(top_srcdir)/shared/misc.c' object='misc.obj' libtool=no @AMDEPBACKSLASH@
737
-@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
738
-@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o misc.obj `if test -f '$(top_srcdir)/shared/misc.c'; then $(CYGPATH_W) '$(top_srcdir)/shared/misc.c'; else $(CYGPATH_W) '$(srcdir)/$(top_srcdir)/shared/misc.c'; fi`
687
+	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o misc.obj `if test -f '$(top_srcdir)/shared/misc.c'; then $(CYGPATH_W) '$(top_srcdir)/shared/misc.c'; else $(CYGPATH_W) '$(srcdir)/$(top_srcdir)/shared/misc.c'; fi`
739 688
 
740 689
 getopt.o: $(top_srcdir)/shared/getopt.c
741
-@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT getopt.o -MD -MP -MF $(DEPDIR)/getopt.Tpo -c -o getopt.o `test -f '$(top_srcdir)/shared/getopt.c' || echo '$(srcdir)/'`$(top_srcdir)/shared/getopt.c
742
-@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/getopt.Tpo $(DEPDIR)/getopt.Po
743
-@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='$(top_srcdir)/shared/getopt.c' object='getopt.o' libtool=no @AMDEPBACKSLASH@
744
-@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
745
-@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o getopt.o `test -f '$(top_srcdir)/shared/getopt.c' || echo '$(srcdir)/'`$(top_srcdir)/shared/getopt.c
690
+	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o getopt.o `test -f '$(top_srcdir)/shared/getopt.c' || echo '$(srcdir)/'`$(top_srcdir)/shared/getopt.c
746 691
 
747 692
 getopt.obj: $(top_srcdir)/shared/getopt.c
748
-@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT getopt.obj -MD -MP -MF $(DEPDIR)/getopt.Tpo -c -o getopt.obj `if test -f '$(top_srcdir)/shared/getopt.c'; then $(CYGPATH_W) '$(top_srcdir)/shared/getopt.c'; else $(CYGPATH_W) '$(srcdir)/$(top_srcdir)/shared/getopt.c'; fi`
749
-@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/getopt.Tpo $(DEPDIR)/getopt.Po
750
-@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='$(top_srcdir)/shared/getopt.c' object='getopt.obj' libtool=no @AMDEPBACKSLASH@
751
-@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
752
-@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o getopt.obj `if test -f '$(top_srcdir)/shared/getopt.c'; then $(CYGPATH_W) '$(top_srcdir)/shared/getopt.c'; else $(CYGPATH_W) '$(srcdir)/$(top_srcdir)/shared/getopt.c'; fi`
693
+	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o getopt.obj `if test -f '$(top_srcdir)/shared/getopt.c'; then $(CYGPATH_W) '$(top_srcdir)/shared/getopt.c'; else $(CYGPATH_W) '$(srcdir)/$(top_srcdir)/shared/getopt.c'; fi`
753 694
 
754 695
 actions.o: $(top_srcdir)/shared/actions.c
755
-@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT actions.o -MD -MP -MF $(DEPDIR)/actions.Tpo -c -o actions.o `test -f '$(top_srcdir)/shared/actions.c' || echo '$(srcdir)/'`$(top_srcdir)/shared/actions.c
756
-@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/actions.Tpo $(DEPDIR)/actions.Po
757
-@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='$(top_srcdir)/shared/actions.c' object='actions.o' libtool=no @AMDEPBACKSLASH@
758
-@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
759
-@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o actions.o `test -f '$(top_srcdir)/shared/actions.c' || echo '$(srcdir)/'`$(top_srcdir)/shared/actions.c
696
+	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o actions.o `test -f '$(top_srcdir)/shared/actions.c' || echo '$(srcdir)/'`$(top_srcdir)/shared/actions.c
760 697
 
761 698
 actions.obj: $(top_srcdir)/shared/actions.c
762
-@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT actions.obj -MD -MP -MF $(DEPDIR)/actions.Tpo -c -o actions.obj `if test -f '$(top_srcdir)/shared/actions.c'; then $(CYGPATH_W) '$(top_srcdir)/shared/actions.c'; else $(CYGPATH_W) '$(srcdir)/$(top_srcdir)/shared/actions.c'; fi`
763
-@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/actions.Tpo $(DEPDIR)/actions.Po
764
-@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='$(top_srcdir)/shared/actions.c' object='actions.obj' libtool=no @AMDEPBACKSLASH@
765
-@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
766
-@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o actions.obj `if test -f '$(top_srcdir)/shared/actions.c'; then $(CYGPATH_W) '$(top_srcdir)/shared/actions.c'; else $(CYGPATH_W) '$(srcdir)/$(top_srcdir)/shared/actions.c'; fi`
699
+	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o actions.obj `if test -f '$(top_srcdir)/shared/actions.c'; then $(CYGPATH_W) '$(top_srcdir)/shared/actions.c'; else $(CYGPATH_W) '$(srcdir)/$(top_srcdir)/shared/actions.c'; fi`
767 700
 
768 701
 clamdcom.o: $(top_srcdir)/shared/clamdcom.c
769
-@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT clamdcom.o -MD -MP -MF $(DEPDIR)/clamdcom.Tpo -c -o clamdcom.o `test -f '$(top_srcdir)/shared/clamdcom.c' || echo '$(srcdir)/'`$(top_srcdir)/shared/clamdcom.c
770
-@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/clamdcom.Tpo $(DEPDIR)/clamdcom.Po
771
-@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='$(top_srcdir)/shared/clamdcom.c' object='clamdcom.o' libtool=no @AMDEPBACKSLASH@
772
-@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
773
-@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o clamdcom.o `test -f '$(top_srcdir)/shared/clamdcom.c' || echo '$(srcdir)/'`$(top_srcdir)/shared/clamdcom.c
702
+	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o clamdcom.o `test -f '$(top_srcdir)/shared/clamdcom.c' || echo '$(srcdir)/'`$(top_srcdir)/shared/clamdcom.c
774 703
 
775 704
 clamdcom.obj: $(top_srcdir)/shared/clamdcom.c
776
-@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT clamdcom.obj -MD -MP -MF $(DEPDIR)/clamdcom.Tpo -c -o clamdcom.obj `if test -f '$(top_srcdir)/shared/clamdcom.c'; then $(CYGPATH_W) '$(top_srcdir)/shared/clamdcom.c'; else $(CYGPATH_W) '$(srcdir)/$(top_srcdir)/shared/clamdcom.c'; fi`
777
-@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/clamdcom.Tpo $(DEPDIR)/clamdcom.Po
778
-@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='$(top_srcdir)/shared/clamdcom.c' object='clamdcom.obj' libtool=no @AMDEPBACKSLASH@
779
-@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
780
-@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o clamdcom.obj `if test -f '$(top_srcdir)/shared/clamdcom.c'; then $(CYGPATH_W) '$(top_srcdir)/shared/clamdcom.c'; else $(CYGPATH_W) '$(srcdir)/$(top_srcdir)/shared/clamdcom.c'; fi`
705
+	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o clamdcom.obj `if test -f '$(top_srcdir)/shared/clamdcom.c'; then $(CYGPATH_W) '$(top_srcdir)/shared/clamdcom.c'; else $(CYGPATH_W) '$(srcdir)/$(top_srcdir)/shared/clamdcom.c'; fi`
706
+
707
+onaccess_client.o: ./client/onaccess_client.c
708
+	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o onaccess_client.o `test -f './client/onaccess_client.c' || echo '$(srcdir)/'`./client/onaccess_client.c
709
+
710
+onaccess_client.obj: ./client/onaccess_client.c
711
+	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o onaccess_client.obj `if test -f './client/onaccess_client.c'; then $(CYGPATH_W) './client/onaccess_client.c'; else $(CYGPATH_W) '$(srcdir)/./client/onaccess_client.c'; fi`
712
+
713
+onaccess_proto.o: ./client/onaccess_proto.c
714
+	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o onaccess_proto.o `test -f './client/onaccess_proto.c' || echo '$(srcdir)/'`./client/onaccess_proto.c
715
+
716
+onaccess_proto.obj: ./client/onaccess_proto.c
717
+	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o onaccess_proto.obj `if test -f './client/onaccess_proto.c'; then $(CYGPATH_W) './client/onaccess_proto.c'; else $(CYGPATH_W) '$(srcdir)/./client/onaccess_proto.c'; fi`
718
+
719
+onaccess_ddd.o: ./inotif/onaccess_ddd.c
720
+	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o onaccess_ddd.o `test -f './inotif/onaccess_ddd.c' || echo '$(srcdir)/'`./inotif/onaccess_ddd.c
721
+
722
+onaccess_ddd.obj: ./inotif/onaccess_ddd.c
723
+	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o onaccess_ddd.obj `if test -f './inotif/onaccess_ddd.c'; then $(CYGPATH_W) './inotif/onaccess_ddd.c'; else $(CYGPATH_W) '$(srcdir)/./inotif/onaccess_ddd.c'; fi`
724
+
725
+onaccess_fan.o: ./fanotif/onaccess_fan.c
726
+	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o onaccess_fan.o `test -f './fanotif/onaccess_fan.c' || echo '$(srcdir)/'`./fanotif/onaccess_fan.c
727
+
728
+onaccess_fan.obj: ./fanotif/onaccess_fan.c
729
+	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o onaccess_fan.obj `if test -f './fanotif/onaccess_fan.c'; then $(CYGPATH_W) './fanotif/onaccess_fan.c'; else $(CYGPATH_W) '$(srcdir)/./fanotif/onaccess_fan.c'; fi`
730
+
731
+onaccess_hash.o: ./inotif/onaccess_hash.c
732
+	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o onaccess_hash.o `test -f './inotif/onaccess_hash.c' || echo '$(srcdir)/'`./inotif/onaccess_hash.c
733
+
734
+onaccess_hash.obj: ./inotif/onaccess_hash.c
735
+	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o onaccess_hash.obj `if test -f './inotif/onaccess_hash.c'; then $(CYGPATH_W) './inotif/onaccess_hash.c'; else $(CYGPATH_W) '$(srcdir)/./inotif/onaccess_hash.c'; fi`
736
+
737
+onaccess_others.o: ./misc/onaccess_others.c
738
+	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o onaccess_others.o `test -f './misc/onaccess_others.c' || echo '$(srcdir)/'`./misc/onaccess_others.c
739
+
740
+onaccess_others.obj: ./misc/onaccess_others.c
741
+	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o onaccess_others.obj `if test -f './misc/onaccess_others.c'; then $(CYGPATH_W) './misc/onaccess_others.c'; else $(CYGPATH_W) '$(srcdir)/./misc/onaccess_others.c'; fi`
742
+
743
+onaccess_scth.o: ./scan/onaccess_scth.c
744
+	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o onaccess_scth.o `test -f './scan/onaccess_scth.c' || echo '$(srcdir)/'`./scan/onaccess_scth.c
745
+
746
+onaccess_scth.obj: ./scan/onaccess_scth.c
747
+	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o onaccess_scth.obj `if test -f './scan/onaccess_scth.c'; then $(CYGPATH_W) './scan/onaccess_scth.c'; else $(CYGPATH_W) '$(srcdir)/./scan/onaccess_scth.c'; fi`
781 748
 
782 749
 mostlyclean-libtool:
783 750
 	-rm -f *.lo
... ...
@@ -910,7 +879,6 @@ clean: clean-am
910 910
 clean-am: clean-binPROGRAMS clean-generic clean-libtool mostlyclean-am
911 911
 
912 912
 distclean: distclean-am
913
-	-rm -rf ./$(DEPDIR)
914 913
 	-rm -f Makefile
915 914
 distclean-am: clean-am distclean-compile distclean-generic \
916 915
 	distclean-tags
... ...
@@ -956,7 +924,6 @@ install-ps-am:
956 956
 installcheck-am: installcheck-binPROGRAMS
957 957
 
958 958
 maintainer-clean: maintainer-clean-am
959
-	-rm -rf ./$(DEPDIR)
960 959
 	-rm -f Makefile
961 960
 maintainer-clean-am: distclean-am maintainer-clean-generic
962 961
 
... ...
@@ -43,7 +43,7 @@
43 43
 #include "shared/optparser.h"
44 44
 #include "shared/actions.h"
45 45
 
46
-#include "onaccess_client.h"
46
+#include "./client/onaccess_client.h"
47 47
 
48 48
 void help(void);
49 49
 
... ...
@@ -117,7 +117,7 @@ int main(int argc, char **argv)
117 117
 	    optfree(clamdopts);
118 118
 	    exit(2);
119 119
 	}
120
-    } else 
120
+    } else
121 121
 	logg_file = NULL;
122 122
 
123 123
 
124 124
new file mode 100644
... ...
@@ -0,0 +1,322 @@
0
+/*
1
+ *  Copyright (C) 2015-2018 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
2
+ *  Copyright (C) 2009 Sourcefire, Inc.
3
+ *
4
+ *  Authors: Tomasz Kojm, aCaB, Mickey Sola
5
+ *
6
+ *  This program is free software; you can redistribute it and/or modify
7
+ *  it under the terms of the GNU General Public License version 2 as
8
+ *  published by the Free Software Foundation.
9
+ *
10
+ *  This program is distributed in the hope that it will be useful,
11
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
+ *  GNU General Public License for more details.
14
+ *
15
+ *  You should have received a copy of the GNU General Public License
16
+ *  along with this program; if not, write to the Free Software
17
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
18
+ *  MA 02110-1301, USA.
19
+ */
20
+
21
+#if HAVE_CONFIG_H
22
+#include "clamav-config.h"
23
+#endif
24
+
25
+#include <stdio.h>
26
+#include <stdlib.h>
27
+#ifdef	HAVE_UNISTD_H
28
+#include <unistd.h>
29
+#endif
30
+#include <string.h>
31
+#include <sys/types.h>
32
+#include <sys/stat.h>
33
+#ifdef HAVE_SYS_LIMITS_H
34
+#include <sys/limits.h>
35
+#endif
36
+#ifdef HAVE_SYS_SELECT_H
37
+#include <sys/select.h>
38
+#endif
39
+#include <sys/socket.h>
40
+#include <sys/un.h>
41
+#include <netinet/in.h>
42
+#include <arpa/inet.h>
43
+#include <netdb.h>
44
+#include <utime.h>
45
+#include <errno.h>
46
+#include <dirent.h>
47
+#include <fcntl.h>
48
+
49
+#ifdef HAVE_SYS_UIO_H
50
+#include <sys/uio.h>
51
+#endif
52
+
53
+#include "libclamav/clamav.h"
54
+#include "shared/optparser.h"
55
+#include "shared/output.h"
56
+#include "shared/misc.h"
57
+#include "shared/actions.h"
58
+#include "shared/clamdcom.h"
59
+
60
+#include "libclamav/str.h"
61
+#include "libclamav/others.h"
62
+
63
+#include "onaccess_client.h"
64
+#include "onaccess_proto.h"
65
+
66
+unsigned long int maxstream;
67
+struct sockaddr_un nixsock;
68
+extern struct optstruct *clamdopts;
69
+
70
+/* Inits the communication layer
71
+ * Returns 0 if clamd is local, non zero if clamd is remote */
72
+static int isremote(const struct optstruct *opts) {
73
+    int s, ret;
74
+    const struct optstruct *opt;
75
+    char *ipaddr, port[10];
76
+    struct addrinfo hints, *info, *p;
77
+    int res;
78
+
79
+    UNUSEDPARAM(opts);
80
+
81
+#ifndef _WIN32
82
+    if((opt = optget(clamdopts, "LocalSocket"))->enabled) {
83
+        memset((void *)&nixsock, 0, sizeof(nixsock));
84
+        nixsock.sun_family = AF_UNIX;
85
+        strncpy(nixsock.sun_path, opt->strarg, sizeof(nixsock.sun_path));
86
+        nixsock.sun_path[sizeof(nixsock.sun_path)-1]='\0';
87
+        return 0;
88
+    }
89
+#endif
90
+    if(!(opt = optget(clamdopts, "TCPSocket"))->enabled)
91
+        return 0;
92
+
93
+    snprintf(port, sizeof(port), "%lld", optget(clamdopts, "TCPSocket")->numarg);
94
+
95
+    opt = optget(clamdopts, "TCPAddr");
96
+    while (opt) {
97
+        ipaddr = NULL;
98
+        if (opt->strarg)
99
+            ipaddr = (!strcmp(opt->strarg, "any") ? NULL : opt->strarg);
100
+
101
+        memset(&hints, 0x00, sizeof(struct addrinfo));
102
+        hints.ai_family = AF_UNSPEC;
103
+        hints.ai_socktype = SOCK_STREAM;
104
+        hints.ai_flags = AI_PASSIVE;
105
+
106
+        if ((res = getaddrinfo(ipaddr, port, &hints, &info))) {
107
+            logg("!Can't lookup clamd hostname: %s\n", gai_strerror(res));
108
+            opt = opt->nextarg;
109
+            continue;
110
+        }
111
+
112
+        for (p = info; p != NULL; p = p->ai_next) {
113
+            if((s = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) < 0) {
114
+                logg("isremote: socket() returning: %s.\n", strerror(errno));
115
+                continue;
116
+            }
117
+
118
+            switch (p->ai_family) {
119
+            case AF_INET:
120
+                ((struct sockaddr_in *)(p->ai_addr))->sin_port = htons(INADDR_ANY);
121
+                break;
122
+            case AF_INET6:
123
+                ((struct sockaddr_in6 *)(p->ai_addr))->sin6_port = htons(INADDR_ANY);
124
+                break;
125
+            default:
126
+                break;
127
+            }
128
+
129
+            ret = bind(s, p->ai_addr, p->ai_addrlen);
130
+            if (ret) {
131
+                if (errno == EADDRINUSE) {
132
+                    /* 
133
+                     * If we can't bind, then either we're attempting to listen on an IP that isn't
134
+                     * ours or that clamd is already listening on.
135
+                     */
136
+                    closesocket(s);
137
+                    freeaddrinfo(info);
138
+                    return 0;
139
+                }
140
+
141
+                closesocket(s);
142
+                freeaddrinfo(info);
143
+                return 1;
144
+            }
145
+
146
+            closesocket(s);
147
+        }
148
+
149
+        freeaddrinfo(info);
150
+
151
+        opt = opt->nextarg;
152
+    }
153
+
154
+    return 0;
155
+}
156
+
157
+
158
+/* Turns a relative path into an absolute one
159
+ * Returns a pointer to the path (which must be 
160
+ * freed by the caller) or NULL on error */
161
+static char *makeabs(const char *basepath) {
162
+    int namelen;
163
+    char *ret;
164
+
165
+    if(!(ret = malloc(PATH_MAX + 1))) {
166
+	logg("^Can't make room for fullpath.\n");
167
+	return NULL;
168
+    }
169
+    if(!cli_is_abspath(basepath)) {
170
+	if(!getcwd(ret, PATH_MAX)) {
171
+	    logg("^Can't get absolute pathname of current working directory.\n");
172
+	    free(ret);
173
+	    return NULL;
174
+	}
175
+	if(*basepath == '\\') {
176
+	    namelen = 2;
177
+	    basepath++;
178
+	} else
179
+	namelen = strlen(ret);
180
+	snprintf(&ret[namelen], PATH_MAX - namelen, PATHSEP"%s", basepath);
181
+    } else {
182
+	strncpy(ret, basepath, PATH_MAX);
183
+    }
184
+    ret[PATH_MAX] = '\0';
185
+    return ret;
186
+}
187
+
188
+/* Recursively scans a path with the given scantype
189
+ * Returns non zero for serious errors, zero otherwise */
190
+static int client_scan(const char *file, int scantype, int *infected, int *err, int maxlevel, int session, int flags) {
191
+    int ret;
192
+    char *fullpath = makeabs(file);
193
+
194
+    if(!fullpath)
195
+	return 0;
196
+    if (!session)
197
+	ret = serial_client_scan(fullpath, scantype, infected, err, maxlevel, flags);
198
+    else
199
+	ret = parallel_client_scan(fullpath, scantype, infected, err, maxlevel, flags);
200
+    free(fullpath);
201
+    return ret;
202
+}
203
+
204
+int get_clamd_version(const struct optstruct *opts)
205
+{
206
+    char *buff;
207
+    int len, sockd;
208
+    struct RCVLN rcv;
209
+
210
+    isremote(opts);
211
+    if((sockd = dconnect()) < 0) return 2;
212
+    recvlninit(&rcv, sockd);
213
+
214
+    if(sendln(sockd, "zVERSION", 9)) {
215
+        closesocket(sockd);
216
+        return 2;
217
+    }
218
+
219
+    while((len = recvln(&rcv, &buff, NULL))) {
220
+        if(len == -1) {
221
+            logg("!Error occurred while receiving version information.\n");
222
+            break;
223
+        }
224
+        printf("%s\n", buff);
225
+    }
226
+
227
+    closesocket(sockd);
228
+    return 0;
229
+}
230
+
231
+int reload_clamd_database(const struct optstruct *opts)
232
+{
233
+    char *buff;
234
+    int len, sockd;
235
+    struct RCVLN rcv;
236
+
237
+    isremote(opts);
238
+    if((sockd = dconnect()) < 0) return 2;
239
+    recvlninit(&rcv, sockd);
240
+
241
+    if(sendln(sockd, "zRELOAD", 8)) {
242
+        closesocket(sockd);
243
+        return 2;
244
+    }
245
+
246
+    if(!(len = recvln(&rcv, &buff, NULL)) || len < 10 || memcmp(buff, "RELOADING", 9)) {
247
+        logg("!Clamd did not reload the database\n");
248
+        closesocket(sockd);
249
+        return 2;
250
+    }
251
+    closesocket(sockd);
252
+    return 0;
253
+}
254
+
255
+int client(const struct optstruct *opts, int *infected, int *err)
256
+{
257
+    int remote, scantype, session = 0, errors = 0, scandash = 0, maxrec, flags = 0;
258
+    const char *fname;
259
+
260
+    scandash = (opts->filename && opts->filename[0] && !strcmp(opts->filename[0], "-") && !optget(opts, "file-list")->enabled && !opts->filename[1]);
261
+    remote = isremote(opts) | optget(opts, "stream")->enabled;
262
+#ifdef HAVE_FD_PASSING
263
+    if(!remote && optget(clamdopts, "LocalSocket")->enabled && (optget(opts, "fdpass")->enabled || scandash)) {
264
+        scantype = FILDES;
265
+        session = optget(opts, "multiscan")->enabled;
266
+    } else 
267
+#endif
268
+        if(remote || scandash) {
269
+            scantype = STREAM;
270
+            session = optget(opts, "multiscan")->enabled;
271
+        } 
272
+        else if(optget(opts, "multiscan")->enabled) scantype = MULTI;
273
+        else if(optget(opts, "allmatch")->enabled) scantype = ALLMATCH;
274
+        else scantype = CONT;
275
+
276
+    maxrec = optget(clamdopts, "MaxDirectoryRecursion")->numarg;
277
+    maxstream = optget(clamdopts, "StreamMaxLength")->numarg;
278
+    if (optget(clamdopts, "FollowDirectorySymlinks")->enabled)
279
+        flags |= CLI_FTW_FOLLOW_DIR_SYMLINK;
280
+    if (optget(clamdopts, "FollowFileSymlinks")->enabled)
281
+        flags |= CLI_FTW_FOLLOW_FILE_SYMLINK;
282
+    flags |= CLI_FTW_TRIM_SLASHES;
283
+
284
+    *infected = 0;
285
+
286
+    if(scandash) {
287
+        int sockd, ret;
288
+        STATBUF sb;
289
+        if(FSTAT(0, &sb) < 0) {
290
+            logg("client.c: fstat failed for file name \"%s\", with %s\n.", 
291
+                    opts->filename[0], strerror(errno));
292
+            return 2;
293
+        }
294
+        if((sb.st_mode & S_IFMT) != S_IFREG) scantype = STREAM;
295
+        if((sockd = dconnect()) >= 0 && (ret = dsresult(sockd, scantype, NULL, &ret, NULL)) >= 0)
296
+            *infected = ret;
297
+        else
298
+            errors = 1;
299
+        if(sockd >= 0) closesocket(sockd);
300
+    } else if(opts->filename || optget(opts, "file-list")->enabled) {
301
+        if(opts->filename && optget(opts, "file-list")->enabled)
302
+            logg("^Only scanning files from --file-list (files passed at cmdline are ignored)\n");
303
+
304
+        while((fname = filelist(opts, NULL))) {
305
+            if(!strcmp(fname, "-")) {
306
+                logg("!Scanning from standard input requires \"-\" to be the only file argument\n");
307
+                continue;
308
+            }
309
+            errors += client_scan(fname, scantype, infected, err, maxrec, session, flags);
310
+            /* this may be too strict
311
+               if(errors >= 10) {
312
+               logg("!Too many errors\n");
313
+               break;
314
+               }
315
+               */
316
+        }
317
+    } else {
318
+        errors = client_scan("", scantype, infected, err, maxrec, session, flags);
319
+    }
320
+    return *infected ? 1 : (errors ? 2 : 0);
321
+}
0 322
new file mode 100644
... ...
@@ -0,0 +1,40 @@
0
+/*
1
+ *  Copyright (C) 2015-2019 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
2
+ *  Copyright (C) 2009 Sourcefire, Inc.
3
+ *
4
+ *  Authors: Tomasz Kojm, aCaB
5
+ *
6
+ *  This program is free software; you can redistribute it and/or modify
7
+ *  it under the terms of the GNU General Public License version 2 as
8
+ *  published by the Free Software Foundation.
9
+ *
10
+ *  This program is distributed in the hope that it will be useful,
11
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
+ *  GNU General Public License for more details.
14
+ *
15
+ *  You should have received a copy of the GNU General Public License
16
+ *  along with this program; if not, write to the Free Software
17
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
18
+ *  MA 02110-1301, USA.
19
+ */
20
+
21
+#ifndef __ONAS_CLIENT_H
22
+#define __ONAS_CLIENT_H
23
+
24
+#include "shared/optparser.h"
25
+
26
+enum {
27
+    CONT,
28
+    MULTI,
29
+    STREAM,
30
+    FILDES,
31
+    ALLMATCH,
32
+    MAX_SCANTYPE = ALLMATCH
33
+};
34
+
35
+int client(const struct optstruct *opts, int *infected, int *err);
36
+int get_clamd_version(const struct optstruct *opts);
37
+int reload_clamd_database(const struct optstruct *opts);
38
+
39
+#endif
0 40
new file mode 100644
... ...
@@ -0,0 +1,691 @@
0
+/*
1
+ *  Copyright (C) 2015 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
2
+ *  Copyright (C) 2009 Sourcefire, Inc.
3
+ *
4
+ *  Authors: Tomasz Kojm, aCaB
5
+ *
6
+ *  This program is free software; you can redistribute it and/or modify
7
+ *  it under the terms of the GNU General Public License version 2 as
8
+ *  published by the Free Software Foundation.
9
+ *
10
+ *  This program is distributed in the hope that it will be useful,
11
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
+ *  GNU General Public License for more details.
14
+ *
15
+ *  You should have received a copy of the GNU General Public License
16
+ *  along with this program; if not, write to the Free Software
17
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
18
+ *  MA 02110-1301, USA.
19
+ */
20
+
21
+#if HAVE_CONFIG_H
22
+#include "clamav-config.h"
23
+#endif
24
+
25
+#if defined(C_SOLARIS)
26
+#ifndef __EXTENSIONS__
27
+#define __EXTENSIONS__
28
+#endif
29
+#endif
30
+
31
+/* must be first because it may define _XOPEN_SOURCE */
32
+#include "shared/fdpassing.h"
33
+#include <stdio.h>
34
+#ifdef HAVE_UNISTD_H
35
+#include <unistd.h>
36
+#endif
37
+#include <string.h>
38
+#include <errno.h>
39
+#include <stdlib.h>
40
+#include <sys/types.h>
41
+#include <sys/stat.h>
42
+#include <fcntl.h>
43
+#include <sys/types.h>
44
+#ifdef HAVE_SYS_SELECT_H
45
+#include <sys/select.h>
46
+#endif
47
+#ifndef _WIN32
48
+#include <arpa/inet.h>
49
+#include <sys/socket.h>
50
+#include <sys/un.h>
51
+#include <netdb.h>
52
+#endif
53
+
54
+#include "libclamav/clamav.h"
55
+#include "libclamav/others.h"
56
+#include "shared/actions.h"
57
+#include "shared/output.h"
58
+#include "shared/misc.h"
59
+#include "shared/clamdcom.h"
60
+
61
+#include "onaccess_proto.h"
62
+#include "onaccess_client.h"
63
+
64
+extern unsigned long int maxstream;
65
+int printinfected;
66
+extern struct optstruct *clamdopts;
67
+#ifndef _WIN32
68
+extern struct sockaddr_un nixsock;
69
+#endif
70
+
71
+static const char *scancmd[] = { "CONTSCAN", "MULTISCAN", "INSTREAM", "FILDES", "ALLMATCHSCAN" };
72
+
73
+/* Connects to clamd 
74
+ * Returns a FD or -1 on error */
75
+int dconnect() {
76
+    int sockd, res;
77
+    const struct optstruct *opt;
78
+    struct addrinfo hints, *info, *p;
79
+    char port[10];
80
+    char *ipaddr;
81
+
82
+#ifndef _WIN32
83
+    opt = optget(clamdopts, "LocalSocket");
84
+    if (opt->enabled) {
85
+        if ((sockd = socket(AF_UNIX, SOCK_STREAM, 0)) >= 0) {
86
+            if (connect(sockd, (struct sockaddr *)&nixsock, sizeof(nixsock)) == 0)
87
+                return sockd;
88
+            else {
89
+                logg("!Could not connect to clamd on LocalSocket %s: %s\n", opt->strarg, strerror(errno));
90
+                close(sockd);
91
+            }
92
+        }
93
+    }
94
+#endif
95
+
96
+    snprintf(port, sizeof(port), "%lld", optget(clamdopts, "TCPSocket")->numarg);
97
+
98
+    opt = optget(clamdopts, "TCPAddr");
99
+    while (opt) {
100
+        if (opt->enabled) {
101
+            ipaddr = NULL;
102
+            if (opt->strarg)
103
+                ipaddr = (!strcmp(opt->strarg, "any") ? NULL : opt->strarg);
104
+
105
+            memset(&hints, 0x00, sizeof(struct addrinfo));
106
+            hints.ai_family = AF_UNSPEC;
107
+            hints.ai_socktype = SOCK_STREAM;
108
+
109
+            if ((res = getaddrinfo(ipaddr, port, &hints, &info))) {
110
+                logg("!Could not lookup %s: %s\n", ipaddr ? ipaddr : "", gai_strerror(res));
111
+                opt = opt->nextarg;
112
+                continue;
113
+            }
114
+
115
+            for (p = info; p != NULL; p = p->ai_next) {
116
+                if((sockd = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) < 0) {
117
+                    logg("!Can't create the socket: %s\n", strerror(errno));
118
+                    continue;
119
+                }
120
+
121
+                if(connect(sockd, p->ai_addr, p->ai_addrlen) < 0) {
122
+                    logg("!Could not connect to clamd on %s: %s\n", opt->strarg, strerror(errno));
123
+                    closesocket(sockd);
124
+                    continue;
125
+                }
126
+
127
+                freeaddrinfo(info);
128
+                return sockd;
129
+            }
130
+
131
+            freeaddrinfo(info);
132
+        }
133
+        opt = opt->nextarg;
134
+    }
135
+
136
+    return -1;
137
+}
138
+
139
+/* Issues an INSTREAM command to clamd and streams the given file
140
+ * Returns >0 on success, 0 soft fail, -1 hard fail */
141
+static int send_stream(int sockd, const char *filename) {
142
+    uint32_t buf[BUFSIZ/sizeof(uint32_t)];
143
+    int fd, len;
144
+    unsigned long int todo = maxstream;
145
+
146
+    if(filename) {
147
+	if((fd = safe_open(filename, O_RDONLY | O_BINARY))<0) {
148
+	    logg("~%s: Access denied. ERROR\n", filename);
149
+	    return 0;
150
+	}
151
+    } else fd = 0;
152
+
153
+    if(sendln(sockd, "zINSTREAM", 10)) {
154
+	close(fd);
155
+	return -1;
156
+    }
157
+
158
+    while((len = read(fd, &buf[1], sizeof(buf) - sizeof(uint32_t))) > 0) {
159
+	if((unsigned int)len > todo) len = todo;
160
+	buf[0] = htonl(len);
161
+	if(sendln(sockd, (const char *)buf, len+sizeof(uint32_t))) {
162
+	    close(fd);
163
+	    return -1;
164
+	}
165
+	todo -= len;
166
+	if(!todo) {
167
+	    len = 0;
168
+	    break;
169
+	}
170
+    }
171
+    close(fd);
172
+    if(len) {
173
+	logg("!Failed to read from %s.\n", filename ? filename : "STDIN");
174
+	return 0;
175
+    }
176
+    *buf=0;
177
+    sendln(sockd, (const char *)buf, 4);
178
+    return 1;
179
+}
180
+
181
+#ifdef HAVE_FD_PASSING
182
+/* Issues a FILDES command and pass a FD to clamd
183
+ * Returns >0 on success, 0 soft fail, -1 hard fail */
184
+static int send_fdpass(int sockd, const char *filename) {
185
+    struct iovec iov[1];
186
+    struct msghdr msg;
187
+    struct cmsghdr *cmsg;
188
+    unsigned char fdbuf[CMSG_SPACE(sizeof(int))];
189
+    char dummy[]="";
190
+    int fd;
191
+
192
+    if(filename) {
193
+	if((fd = open(filename, O_RDONLY))<0) {
194
+	    logg("~%s: Access denied. ERROR\n", filename);
195
+	    return 0;
196
+	}
197
+    } else fd = 0;
198
+    if(sendln(sockd, "zFILDES", 8)) {
199
+      close(fd);
200
+      return -1;
201
+    }
202
+
203
+    iov[0].iov_base = dummy;
204
+    iov[0].iov_len = 1;
205
+    memset(&msg, 0, sizeof(msg));
206
+    msg.msg_control = fdbuf;
207
+    msg.msg_iov = iov;
208
+    msg.msg_iovlen = 1;
209
+    msg.msg_controllen = CMSG_LEN(sizeof(int));
210
+    cmsg = CMSG_FIRSTHDR(&msg);
211
+    cmsg->cmsg_len = CMSG_LEN(sizeof(int));
212
+    cmsg->cmsg_level = SOL_SOCKET;
213
+    cmsg->cmsg_type = SCM_RIGHTS;
214
+    *(int *)CMSG_DATA(cmsg) = fd;
215
+    if(sendmsg(sockd, &msg, 0) == -1) {
216
+	logg("!FD send failed: %s\n", strerror(errno));
217
+	close(fd);
218
+	return -1;
219
+    }
220
+    close(fd);
221
+    return 1;
222
+}
223
+#endif
224
+
225
+/* 0: scan, 1: skip */
226
+static int chkpath(const char *path)
227
+{
228
+	const struct optstruct *opt;
229
+
230
+   if((opt = optget(clamdopts, "ExcludePath"))->enabled) {
231
+	while(opt) {
232
+	    if(match_regex(path, opt->strarg) == 1) {
233
+                if (printinfected != 1)
234
+                    logg("~%s: Excluded\n", path);
235
+		return 1;
236
+	    }
237
+	    opt = opt->nextarg;
238
+	}
239
+    }
240
+    return 0;
241
+}
242
+
243
+static int ftw_chkpath(const char *path, struct cli_ftw_cbdata *data)
244
+{
245
+    UNUSEDPARAM(data);
246
+    return chkpath(path);
247
+}
248
+
249
+/* Sends a proper scan request to clamd and parses its replies
250
+ * This is used only in non IDSESSION mode
251
+ * Returns the number of infected files or -1 on error
252
+ * NOTE: filename may be NULL for STREAM scantype. */
253
+int dsresult(int sockd, int scantype, const char *filename, int *printok, int *errors) {
254
+    int infected = 0, len = 0, beenthere = 0;
255
+    char *bol, *eol;
256
+    struct RCVLN rcv;
257
+    STATBUF sb;
258
+
259
+    if(filename && chkpath(filename))
260
+	return 0;
261
+    recvlninit(&rcv, sockd);
262
+
263
+    switch(scantype) {
264
+    case MULTI:
265
+    case CONT:
266
+    case ALLMATCH:
267
+    if (!filename) {
268
+	logg("Filename cannot be NULL for MULTISCAN or CONTSCAN.\n");
269
+	return -1;
270
+    }
271
+    len = strlen(filename) + strlen(scancmd[scantype]) + 3;
272
+    if (!(bol = malloc(len))) {
273
+	logg("!Cannot allocate a command buffer: %s\n", strerror(errno));
274
+	return -1;
275
+    }
276
+    sprintf(bol, "z%s %s", scancmd[scantype], filename);
277
+    if(sendln(sockd, bol, len)) {
278
+	free(bol);
279
+	return -1;
280
+    }
281
+    free(bol);
282
+    break;
283
+
284
+    case STREAM:
285
+        /* NULL filename safe in send_stream() */
286
+	len = send_stream(sockd, filename);
287
+	break;
288
+#ifdef HAVE_FD_PASSING
289
+    case FILDES:
290
+        /* NULL filename safe in send_fdpass() */
291
+	len = send_fdpass(sockd, filename);
292
+	break;
293
+#endif
294
+    }
295
+
296
+    if(len <=0) {
297
+	*printok = 0;
298
+	if(errors)
299
+	    (*errors)++;
300
+	return len;
301
+    }
302
+
303
+    while((len = recvln(&rcv, &bol, &eol))) {
304
+	if(len == -1) return -1;
305
+	beenthere = 1;
306
+	if(!filename) logg("~%s\n", bol);
307
+	if(len > 7) {
308
+	    char *colon = strrchr(bol, ':');
309
+	    if(colon && colon[1] != ' ') {
310
+		char *br;
311
+		*colon = 0;
312
+		br = strrchr(bol, '(');
313
+		if(br)
314
+		    *br = 0;
315
+		colon = strrchr(bol, ':');
316
+	    }
317
+	    if(!colon) {
318
+		char * unkco = "UNKNOWN COMMAND";
319
+		if (!strncmp(bol, unkco, sizeof(unkco) - 1))
320
+		    logg("clamd replied \"UNKNOWN COMMAND\". Command was %s\n", 
321
+			 (scantype < 0 || scantype > MAX_SCANTYPE) ? "unidentified" :
322
+			                                             scancmd[scantype]);
323
+		else
324
+		    logg("Failed to parse reply: \"%s\"\n", bol);
325
+		return -1;
326
+	    } else if(!memcmp(eol - 7, " FOUND", 6)) {
327
+                static char last_filename[PATH_MAX+1] = {'\0'};
328
+		*(eol - 7) = 0;
329
+		*printok = 0;
330
+                if (scantype != ALLMATCH) {
331
+                    infected++;
332
+                } else {
333
+                    if (filename != NULL && strcmp(filename, last_filename)) {
334
+                        infected++;
335
+                        strncpy(last_filename, filename, PATH_MAX);
336
+                        last_filename[PATH_MAX] = '\0';
337
+                    }
338
+                }
339
+		if(filename) {
340
+		    if(scantype >= STREAM) {
341
+			logg("~%s%s FOUND\n", filename, colon);
342
+			if(action) action(filename);
343
+		    } else {
344
+			logg("~%s FOUND\n", bol);
345
+			*colon = '\0';
346
+			if(action)
347
+			    action(bol);
348
+		    }
349
+		}
350
+	    } else if(!memcmp(eol-7, " ERROR", 6)) {
351
+		if(errors)
352
+		    (*errors)++;
353
+		*printok = 0;
354
+		if(filename) {
355
+		    if(scantype >= STREAM)
356
+			logg("~%s%s\n", filename, colon);
357
+		    else
358
+			logg("~%s\n", bol);
359
+		}
360
+	    }
361
+	}
362
+    }
363
+    if(!beenthere) {
364
+        if (!filename) {
365
+	    logg("STDIN: noreply from clamd\n.");
366
+	    return -1;
367
+	}
368
+        if(CLAMSTAT(filename, &sb) == -1) {
369
+	    logg("~%s: stat() failed with %s, clamd may not be responding\n",
370
+		 filename, strerror(errno));
371
+	    return -1;
372
+	}
373
+	if(!S_ISDIR(sb.st_mode)) {
374
+	    logg("~%s: no reply from clamd\n", filename);
375
+	    return -1;
376
+	}
377
+    }
378
+    return infected;
379
+}
380
+
381
+/* Used by serial_callback() */
382
+struct client_serial_data {
383
+    int infected;
384
+    int scantype;
385
+    int printok;
386
+    int files;
387
+    int errors;
388
+};
389
+
390
+/* FTW callback for scanning in non IDSESSION mode
391
+ * Returns SUCCESS or BREAK on success, CL_EXXX on error */
392
+static int serial_callback(STATBUF *sb, char *filename, const char *path, enum cli_ftw_reason reason, struct cli_ftw_cbdata *data) {
393
+    struct client_serial_data *c = (struct client_serial_data *)data->data;
394
+    int sockd, ret;
395
+    const char *f = filename;
396
+
397
+    UNUSEDPARAM(sb);
398
+
399
+    if(chkpath(path))
400
+	return CL_SUCCESS;
401
+    c->files++;
402
+    switch(reason) {
403
+    case error_stat:
404
+	logg("!Can't access file %s\n", path);
405
+	c->errors++;
406
+	return CL_SUCCESS;
407
+    case error_mem:
408
+	logg("!Memory allocation failed in ftw\n");
409
+	c->errors++;
410
+	return CL_EMEM;
411
+    case warning_skipped_dir:
412
+	logg("^Directory recursion limit reached\n");
413
+    case warning_skipped_link:
414
+	return CL_SUCCESS;
415
+    case warning_skipped_special:
416
+	logg("^%s: Not supported file type\n", path);
417
+	c->errors++;
418
+	return CL_SUCCESS;
419
+    case visit_directory_toplev:
420
+	if(c->scantype >= STREAM)
421
+	    return CL_SUCCESS;
422
+	f = path;
423
+	filename = NULL;
424
+    case visit_file:
425
+	break;
426
+    }
427
+
428
+    if((sockd = dconnect()) < 0) {
429
+	if(filename) free(filename);
430
+	c->errors++;
431
+	return CL_EOPEN;
432
+    }
433
+    ret = dsresult(sockd, c->scantype, f, &c->printok, &c->errors);
434
+    if(filename) free(filename);
435
+    closesocket(sockd);
436
+    if(ret < 0) {
437
+	c->errors++;
438
+	return CL_EOPEN;
439
+    }
440
+    c->infected += ret;
441
+    if(reason == visit_directory_toplev)
442
+	return CL_BREAK;
443
+    return CL_SUCCESS;
444
+}
445
+
446
+/* Non-IDSESSION handler
447
+ * Returns non zero for serious errors, zero otherwise */
448
+int serial_client_scan(char *file, int scantype, int *infected, int *err, int maxlevel, int flags) {
449
+    struct cli_ftw_cbdata data;
450
+    struct client_serial_data cdata;
451
+    int ftw;
452
+
453
+    cdata.infected = 0;
454
+    cdata.files = 0;
455
+    cdata.errors = 0;
456
+    cdata.printok = printinfected^1;
457
+    cdata.scantype = scantype;
458
+    data.data = &cdata;
459
+
460
+    ftw = cli_ftw(file, flags, maxlevel ? maxlevel : INT_MAX, serial_callback, &data, ftw_chkpath);
461
+    *infected += cdata.infected;
462
+    *err += cdata.errors;
463
+
464
+    if(!cdata.errors && (ftw == CL_SUCCESS || ftw == CL_BREAK)) {
465
+	if(cdata.printok)
466
+	    logg("~%s: OK\n", file);
467
+	return 0;
468
+    } else if(!cdata.files) {
469
+	logg("~%s: No files scanned\n", file);
470
+	return 0;
471
+    }
472
+    return 1;
473
+}
474
+
475
+/* Used in IDSESSION mode */
476
+struct client_parallel_data {
477
+    int infected;
478
+    int files;
479
+    int errors;
480
+    int scantype;
481
+    int sockd;
482
+    int lastid;
483
+    int printok;
484
+    struct SCANID {
485
+	unsigned int id;
486
+	const char *file;
487
+	struct SCANID *next;
488
+    } *ids;
489
+};
490
+
491
+/* Sends a proper scan request to clamd and parses its replies
492
+ * This is used only in IDSESSION mode
493
+ * Returns 0 on success, 1 on hard failures, 2 on len == 0 (bb#1717) */
494
+static int dspresult(struct client_parallel_data *c) {
495
+    const char *filename;
496
+    char *bol, *eol;
497
+    unsigned int rid;
498
+    int len;
499
+    struct SCANID **id = NULL;
500
+    struct RCVLN rcv;
501
+
502
+    recvlninit(&rcv, c->sockd);
503
+    do {
504
+	len = recvln(&rcv, &bol, &eol);
505
+	if(len < 0) return 1;
506
+	if(!len) return 2;
507
+	if((rid = atoi(bol))) {
508
+	    id = &c->ids;
509
+	    while(*id) {
510
+		if((*id)->id == rid) break;
511
+		id = &((*id)->next);
512
+	    }
513
+	    if(!*id) id = NULL;
514
+	}
515
+	if(!id) {
516
+	    logg("!Bogus session id from clamd\n");
517
+	    return 1;
518
+	}
519
+	filename = (*id)->file;
520
+	if(len > 7) {
521
+	    char *colon = strrchr(bol, ':');
522
+	    if(!colon) {
523
+		logg("!Failed to parse reply\n");
524
+		free((void *)filename);
525
+		return 1;
526
+	    } else if(!memcmp(eol - 7, " FOUND", 6)) {
527
+		c->infected++;
528
+		c->printok = 0;
529
+		logg("~%s%s\n", filename, colon);
530
+		if(action) action(filename);
531
+	    } else if(!memcmp(eol-7, " ERROR", 6)) {
532
+		c->errors++;
533
+		c->printok = 0;
534
+		logg("~%s%s\n", filename, colon);
535
+	    }
536
+	}
537
+	free((void *)filename);
538
+	bol = (char *)*id;
539
+	*id = (*id)->next;
540
+	free(bol);
541
+    } while(rcv.cur != rcv.buf); /* clamd sends whole lines, so, on partial lines, we just assume
542
+				    more data can be recv()'d with close to zero latency */
543
+    return 0;
544
+}
545
+
546
+/* FTW callback for scanning in IDSESSION mode
547
+ * Returns SUCCESS on success, CL_EXXX or BREAK on error */
548
+static int parallel_callback(STATBUF *sb, char *filename, const char *path, enum cli_ftw_reason reason, struct cli_ftw_cbdata *data) {
549
+    struct client_parallel_data *c = (struct client_parallel_data *)data->data;
550
+    struct SCANID *cid;
551
+    int res = CL_CLEAN;
552
+
553
+    UNUSEDPARAM(sb);
554
+
555
+    if(chkpath(path))
556
+	return CL_SUCCESS;
557
+    c->files++;
558
+    switch(reason) {
559
+    case error_stat:
560
+	logg("!Can't access file %s\n", path);
561
+	c->errors++;
562
+	return CL_SUCCESS;
563
+    case error_mem:
564
+	logg("!Memory allocation failed in ftw\n");
565
+	c->errors++;
566
+	return CL_EMEM;
567
+    case warning_skipped_dir:
568
+	logg("^Directory recursion limit reached\n");
569
+	return CL_SUCCESS;
570
+    case warning_skipped_special:
571
+	logg("^%s: Not supported file type\n", path);
572
+	c->errors++;
573
+    case warning_skipped_link:
574
+    case visit_directory_toplev:
575
+	return CL_SUCCESS;
576
+    case visit_file:
577
+	break;
578
+    }
579
+
580
+    while(1) {
581
+	/* consume all the available input to let some of the clamd
582
+	 * threads blocked on send() to be dead.
583
+	 * by doing so we shouldn't deadlock on the next recv() */
584
+	fd_set rfds, wfds;
585
+	FD_ZERO(&rfds);
586
+	FD_SET(c->sockd, &rfds);
587
+	FD_ZERO(&wfds);
588
+	FD_SET(c->sockd, &wfds);
589
+	if(select(c->sockd + 1, &rfds, &wfds, NULL, NULL) < 0) {
590
+	    if(errno == EINTR) continue;
591
+	    free(filename);
592
+	    logg("!select() failed during session: %s\n", strerror(errno));
593
+	    return CL_BREAK;
594
+	}
595
+	if(FD_ISSET(c->sockd, &rfds)) {
596
+	    if(dspresult(c)) {
597
+		free(filename);
598
+		return CL_BREAK;
599
+	    } else continue;
600
+	}
601
+	if(FD_ISSET(c->sockd, &wfds)) break;
602
+    }
603
+
604
+    cid = (struct SCANID *)malloc(sizeof(struct SCANID));
605
+    if(!cid) {
606
+	free(filename);
607
+	logg("!Failed to allocate scanid entry: %s\n", strerror(errno));
608
+	return CL_BREAK;
609
+    }
610
+    cid->id = ++c->lastid;
611
+    cid->file = filename;
612
+    cid->next = c->ids;
613
+    c->ids = cid;
614
+
615
+    switch(c->scantype) {
616
+#ifdef HAVE_FD_PASSING
617
+    case FILDES:
618
+	res = send_fdpass(c->sockd, filename);
619
+	break;
620
+#endif
621
+    case STREAM:
622
+	res = send_stream(c->sockd, filename);
623
+	break;
624
+    }
625
+    if(res <= 0) {
626
+	c->printok = 0;
627
+	c->errors++;
628
+	c->ids = cid->next;
629
+	c->lastid--;
630
+	free(cid);
631
+	free(filename);
632
+	return res ? CL_BREAK : CL_SUCCESS;
633
+    }
634
+    return CL_SUCCESS;
635
+}
636
+
637
+/* IDSESSION handler
638
+ * Returns non zero for serious errors, zero otherwise */
639
+int parallel_client_scan(char *file, int scantype, int *infected, int *err, int maxlevel, int flags) {
640
+    struct cli_ftw_cbdata data;
641
+    struct client_parallel_data cdata;
642
+    int ftw;
643
+
644
+    if((cdata.sockd = dconnect()) < 0)
645
+	return 1;
646
+
647
+    if(sendln(cdata.sockd, "zIDSESSION", 11)) {
648
+	closesocket(cdata.sockd);
649
+	return 1;
650
+    }
651
+
652
+    cdata.infected = 0;
653
+    cdata.files = 0;
654
+    cdata.errors = 0;
655
+    cdata.scantype = scantype;
656
+    cdata.lastid = 0;
657
+    cdata.ids = NULL;
658
+    cdata.printok = printinfected^1;
659
+    data.data = &cdata;
660
+
661
+    ftw = cli_ftw(file, flags, maxlevel ? maxlevel : INT_MAX, parallel_callback, &data, ftw_chkpath);
662
+
663
+    if(ftw != CL_SUCCESS) {
664
+	*err += cdata.errors;
665
+	*infected += cdata.infected;
666
+	closesocket(cdata.sockd);
667
+	return 1;
668
+    }
669
+
670
+    sendln(cdata.sockd, "zEND", 5);
671
+    while(cdata.ids && !dspresult(&cdata));
672
+    closesocket(cdata.sockd);
673
+
674
+    *infected += cdata.infected;
675
+    *err += cdata.errors;
676
+
677
+    if(cdata.ids) {
678
+	logg("!Clamd closed the connection before scanning all files.\n");
679
+	return 1;
680
+    }
681
+    if(cdata.errors)
682
+	return 1;
683
+
684
+    if(!cdata.files)
685
+	return 0;
686
+
687
+    if(cdata.printok)
688
+	logg("~%s: OK\n", file);
689
+    return 0;
690
+}
0 691
new file mode 100644
... ...
@@ -0,0 +1,30 @@
0
+/*
1
+ *  Copyright (C) 2015 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
2
+ *  Copyright (C) 2009 Sourcefire, Inc.
3
+ *
4
+ *  Authors: Tomasz Kojm, aCaB
5
+ *
6
+ *  This program is free software; you can redistribute it and/or modify
7
+ *  it under the terms of the GNU General Public License version 2 as
8
+ *  published by the Free Software Foundation.
9
+ *
10
+ *  This program is distributed in the hope that it will be useful,
11
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
+ *  GNU General Public License for more details.
14
+ *
15
+ *  You should have received a copy of the GNU General Public License
16
+ *  along with this program; if not, write to the Free Software
17
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
18
+ *  MA 02110-1301, USA.
19
+ */
20
+
21
+#ifndef ONAS_PROTO_H
22
+#define ONAS_PROTO_H
23
+#include "shared/misc.h"
24
+
25
+int dconnect(void);
26
+int serial_client_scan(char *file, int scantype, int *infected, int *err, int maxlevel, int flags);
27
+int parallel_client_scan(char *file, int scantype, int *infected, int *err, int maxlevel, int flags);
28
+int dsresult(int sockd, int scantype, const char *filename, int *printok, int *errors);
29
+#endif
0 30
new file mode 100644
... ...
@@ -0,0 +1,306 @@
0
+/*
1
+ *  Copyright (C) 2013-2019 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
2
+ *  Copyright (C) 2011-2013 Sourcefire, Inc.
3
+ *
4
+ *  Authors: Tomasz Kojm, Mickey Sola
5
+ *
6
+ *  This program is free software; you can redistribute it and/or modify
7
+ *  it under the terms of the GNU General Public License version 2 as
8
+ *  published by the Free Software Foundation.
9
+ *
10
+ *  This program is distributed in the hope that it will be useful,
11
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
+ *  GNU General Public License for more details.
14
+ *
15
+ *  You should have received a copy of the GNU General Public License
16
+ *  along with this program; if not, write to the Free Software
17
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
18
+ *  MA 02110-1301, USA.
19
+ */
20
+
21
+#if HAVE_CONFIG_H
22
+#include "clamav-config.h"
23
+#endif
24
+
25
+#if defined(FANOTIFY)
26
+
27
+#include <stdio.h>
28
+#include <unistd.h>
29
+#include <sys/types.h>
30
+#include <sys/stat.h>
31
+#include <fcntl.h>
32
+#include <signal.h>
33
+#include <pthread.h>
34
+#include <string.h>
35
+#include <errno.h>
36
+#include <time.h>
37
+
38
+#include <sys/fanotify.h>
39
+
40
+#include "libclamav/clamav.h"
41
+#include "libclamav/scanners.h"
42
+
43
+#include "shared/optparser.h"
44
+#include "shared/output.h"
45
+
46
+#include "../misc/onaccess_others.h"
47
+#include "clamd/server.h"
48
+
49
+#include "onaccess_fan.h"
50
+#include "../inotif/onaccess_hash.h"
51
+#include "../inotif/onaccess_ddd.h"
52
+
53
+static pthread_t ddd_pid;
54
+static int onas_fan_fd;
55
+
56
+static void onas_fan_exit(int sig)
57
+{
58
+    logg("*ScanOnAccess: onas_fan_exit(), signal %d\n", sig);
59
+
60
+    close(onas_fan_fd);
61
+
62
+    if (ddd_pid > 0) {
63
+        pthread_kill(ddd_pid, SIGUSR1);
64
+        pthread_join(ddd_pid, NULL);
65
+    }
66
+
67
+    pthread_exit(NULL);
68
+    logg("ScanOnAccess: stopped\n");
69
+}
70
+
71
+static int onas_fan_scanfile(int fan_fd, const char *fname, struct fanotify_event_metadata *fmd, int scan, int extinfo, struct thrarg *tharg)
72
+{
73
+    struct fanotify_response res;
74
+    const char *virname = NULL;
75
+    int ret             = 0;
76
+
77
+    res.fd       = fmd->fd;
78
+    res.response = FAN_ALLOW;
79
+
80
+    if (scan) {
81
+        if (onas_scan(fname, fmd->fd, &virname, tharg->engine, tharg->options, extinfo) == CL_VIRUS) {
82
+            /* TODO : FIXME? virusaction forks. This could be extraordinarily problematic, lead to deadlocks,
83
+             * or at the very least lead to extreme memory consumption. Leaving disabled for now.*/
84
+            //virusaction(fname, virname, tharg->opts);
85
+            res.response = FAN_DENY;
86
+        }
87
+    }
88
+
89
+    if (fmd->mask & FAN_ALL_PERM_EVENTS) {
90
+        ret = write(fan_fd, &res, sizeof(res));
91
+        if (ret == -1)
92
+            logg("!ScanOnAccess: Internal error (can't write to fanotify)\n");
93
+    }
94
+
95
+    return ret;
96
+}
97
+
98
+void *onas_fan_th(void *arg)
99
+{
100
+    struct thrarg *tharg = (struct thrarg *)arg;
101
+    sigset_t sigset;
102
+    struct sigaction act;
103
+    const struct optstruct *pt;
104
+    short int scan;
105
+    unsigned int sizelimit = 0, extinfo;
106
+    STATBUF sb;
107
+    uint64_t fan_mask = FAN_EVENT_ON_CHILD | FAN_CLOSE;
108
+    fd_set rfds;
109
+    char buf[4096];
110
+    ssize_t bread;
111
+    struct fanotify_event_metadata *fmd;
112
+    char fname[1024];
113
+    int ret, len, check;
114
+    char err[128];
115
+
116
+    pthread_attr_t ddd_attr;
117
+    struct ddd_thrarg *ddd_tharg = NULL;
118
+
119
+    ddd_pid = 0;
120
+
121
+    /* ignore all signals except SIGUSR1 */
122
+    sigfillset(&sigset);
123
+    sigdelset(&sigset, SIGUSR1);
124
+    /* The behavior of a process is undefined after it ignores a
125
+     * SIGFPE, SIGILL, SIGSEGV, or SIGBUS signal */
126
+    sigdelset(&sigset, SIGFPE);
127
+    sigdelset(&sigset, SIGILL);
128
+    sigdelset(&sigset, SIGSEGV);
129
+#ifdef SIGBUS
130
+    sigdelset(&sigset, SIGBUS);
131
+#endif
132
+    pthread_sigmask(SIG_SETMASK, &sigset, NULL);
133
+    memset(&act, 0, sizeof(struct sigaction));
134
+    act.sa_handler = onas_fan_exit;
135
+    sigfillset(&(act.sa_mask));
136
+    sigaction(SIGUSR1, &act, NULL);
137
+    sigaction(SIGSEGV, &act, NULL);
138
+
139
+    /* Initialize fanotify */
140
+    onas_fan_fd = fanotify_init(FAN_CLASS_CONTENT | FAN_UNLIMITED_QUEUE | FAN_UNLIMITED_MARKS, O_LARGEFILE | O_RDONLY);
141
+    if (onas_fan_fd < 0) {
142
+        logg("!ScanOnAccess: fanotify_init failed: %s\n", cli_strerror(errno, err, sizeof(err)));
143
+        if (errno == EPERM)
144
+            logg("ScanOnAccess: clamd must be started by root\n");
145
+        return NULL;
146
+    }
147
+
148
+    if (!tharg) {
149
+        logg("!Unable to start on-access scanner. Bad thread args.\n");
150
+        return NULL;
151
+    }
152
+
153
+    if (optget(tharg->opts, "OnAccessPrevention")->enabled && !optget(tharg->opts, "OnAccessMountPath")->enabled) {
154
+        logg("ScanOnAccess: preventing access attempts on malicious files.\n");
155
+        fan_mask |= FAN_ACCESS_PERM | FAN_OPEN_PERM;
156
+    } else {
157
+        logg("ScanOnAccess: notifying only for access attempts.\n");
158
+        fan_mask |= FAN_ACCESS | FAN_OPEN;
159
+    }
160
+
161
+    if ((pt = optget(tharg->opts, "OnAccessMountPath"))->enabled) {
162
+        while (pt) {
163
+            if (fanotify_mark(onas_fan_fd, FAN_MARK_ADD | FAN_MARK_MOUNT, fan_mask, onas_fan_fd, pt->strarg) != 0) {
164
+                logg("!ScanOnAccess: Can't include mountpoint '%s'\n", pt->strarg);
165
+                return NULL;
166
+            } else
167
+                logg("ScanOnAccess: Protecting '%s' and rest of mount.\n", pt->strarg);
168
+            pt = (struct optstruct *)pt->nextarg;
169
+        }
170
+
171
+    } else if (!optget(tharg->opts, "OnAccessDisableDDD")->enabled) {
172
+        int thread_started = 1;
173
+        do {
174
+            if (pthread_attr_init(&ddd_attr)) break;
175
+            pthread_attr_setdetachstate(&ddd_attr, PTHREAD_CREATE_JOINABLE);
176
+
177
+            /* Allocate memory for arguments. Thread is responsible for freeing it. */
178
+            if (!(ddd_tharg = (struct ddd_thrarg *)calloc(sizeof(struct ddd_thrarg), 1))) break;
179
+            if (!(ddd_tharg->options = (struct cl_scan_options *)calloc(sizeof(struct cl_scan_options), 1))) break;
180
+
181
+            (void)memcpy(ddd_tharg->options, tharg->options, sizeof(struct cl_scan_options));
182
+            ddd_tharg->fan_fd   = onas_fan_fd;
183
+            ddd_tharg->fan_mask = fan_mask;
184
+            ddd_tharg->opts     = tharg->opts;
185
+            ddd_tharg->engine   = tharg->engine;
186
+
187
+            thread_started = pthread_create(&ddd_pid, &ddd_attr, onas_ddd_th, ddd_tharg);
188
+        } while (0);
189
+
190
+        if (0 != thread_started) {
191
+            /* Failed to create thread. Free anything we may have allocated. */
192
+            logg("!Unable to start dynamic directory determination.\n");
193
+            if (NULL != ddd_tharg) {
194
+                if (NULL != ddd_tharg->options) {
195
+                    free(ddd_tharg->options);
196
+                    ddd_tharg->options = NULL;
197
+                }
198
+                free(ddd_tharg);
199
+                ddd_tharg = NULL;
200
+            }
201
+        }
202
+
203
+    } else {
204
+        if ((pt = optget(tharg->opts, "OnAccessIncludePath"))->enabled) {
205
+            while (pt) {
206
+                if (fanotify_mark(onas_fan_fd, FAN_MARK_ADD, fan_mask, onas_fan_fd, pt->strarg) != 0) {
207
+                    logg("!ScanOnAccess: Can't include path '%s'\n", pt->strarg);
208
+                    return NULL;
209
+                } else
210
+                    logg("ScanOnAccess: Protecting directory '%s'\n", pt->strarg);
211
+                pt = (struct optstruct *)pt->nextarg;
212
+            }
213
+        } else {
214
+            logg("!ScanOnAccess: Please specify at least one path with OnAccessIncludePath\n");
215
+            return NULL;
216
+        }
217
+    }
218
+
219
+    /* Load other options. */
220
+    sizelimit = optget(tharg->opts, "OnAccessMaxFileSize")->numarg;
221
+    if (sizelimit)
222
+        logg("ScanOnAccess: Max file size limited to %u bytes\n", sizelimit);
223
+    else
224
+        logg("ScanOnAccess: File size limit disabled\n");
225
+
226
+    extinfo = optget(tharg->opts, "ExtendedDetectionInfo")->enabled;
227
+
228
+    FD_ZERO(&rfds);
229
+    FD_SET(onas_fan_fd, &rfds);
230
+    do {
231
+        if (reload) sleep(1);
232
+        ret = select(onas_fan_fd + 1, &rfds, NULL, NULL, NULL);
233
+    } while ((ret == -1 && errno == EINTR) || reload);
234
+
235
+    time_t start = time(NULL) - 30;
236
+    while (((bread = read(onas_fan_fd, buf, sizeof(buf))) > 0) || errno == EOVERFLOW) {
237
+
238
+        if (errno == EOVERFLOW) {
239
+            if (time(NULL) - start >= 30) {
240
+                logg("!ScanOnAccess: Internal error (failed to read data) ... %s\n", strerror(errno));
241
+                logg("!ScanOnAccess: File too large for fanotify ... recovering and continuing scans...\n");
242
+                start = time(NULL);
243
+            }
244
+
245
+            errno = 0;
246
+            continue;
247
+        }
248
+
249
+        fmd = (struct fanotify_event_metadata *)buf;
250
+        while (FAN_EVENT_OK(fmd, bread)) {
251
+            scan = 1;
252
+            if (fmd->fd >= 0) {
253
+                sprintf(fname, "/proc/self/fd/%d", fmd->fd);
254
+                len = readlink(fname, fname, sizeof(fname) - 1);
255
+                if (len == -1) {
256
+                    close(fmd->fd);
257
+                    logg("!ScanOnAccess: Internal error (readlink() failed)\n");
258
+                    return NULL;
259
+                }
260
+                fname[len] = 0;
261
+
262
+                if ((check = onas_fan_checkowner(fmd->pid, tharg->opts))) {
263
+                    scan = 0;
264
+/* TODO: Re-enable OnAccessExtraScanning once the thread resource consumption issue is resolved. */
265
+#if 0
266
+			if ((check != CHK_SELF) || !(optget(tharg->opts, "OnAccessExtraScanning")->enabled)) {
267
+#else
268
+                    if (check != CHK_SELF) {
269
+#endif
270
+                    logg("*ScanOnAccess: %s skipped (excluded UID)\n", fname);
271
+                }
272
+            }
273
+
274
+            if (sizelimit) {
275
+                if (FSTAT(fmd->fd, &sb) != 0 || sb.st_size > sizelimit) {
276
+                    scan = 0;
277
+                    /* logg("*ScanOnAccess: %s skipped (size > %d)\n", fname, sizelimit); */
278
+                }
279
+            }
280
+
281
+            if (onas_fan_scanfile(onas_fan_fd, fname, fmd, scan, extinfo, tharg) == -1) {
282
+                close(fmd->fd);
283
+                return NULL;
284
+            }
285
+
286
+            if (close(fmd->fd) == -1) {
287
+                printf("!ScanOnAccess: Internal error (close(%d) failed)\n", fmd->fd);
288
+                close(fmd->fd);
289
+                return NULL;
290
+            }
291
+        }
292
+        fmd = FAN_EVENT_NEXT(fmd, bread);
293
+    }
294
+    do {
295
+        if (reload) sleep(1);
296
+        ret = select(onas_fan_fd + 1, &rfds, NULL, NULL, NULL);
297
+    } while ((ret == -1 && errno == EINTR) || reload);
298
+}
299
+
300
+if (bread < 0)
301
+    logg("!ScanOnAccess: Internal error (failed to read data) ... %s\n", strerror(errno));
302
+
303
+return NULL;
304
+}
305
+#endif
0 306
new file mode 100644
... ...
@@ -0,0 +1,27 @@
0
+/*
1
+ *  Copyright (C) 2013-2019 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
2
+ *  Copyright (C) 2011-2013 Sourcefire, Inc.
3
+ *
4
+ *  Authors: Tomasz Kojm
5
+ *
6
+ *  This program is free software; you can redistribute it and/or modify
7
+ *  it under the terms of the GNU General Public License version 2 as
8
+ *  published by the Free Software Foundation.
9
+ *
10
+ *  This program is distributed in the hope that it will be useful,
11
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
+ *  GNU General Public License for more details.
14
+ *
15
+ *  You should have received a copy of the GNU General Public License
16
+ *  along with this program; if not, write to the Free Software
17
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
18
+ *  MA 02110-1301, USA.
19
+ */
20
+
21
+#ifndef __FAN_H
22
+#define __FAN_H
23
+
24
+void *onas_fan_th(void *arg);
25
+
26
+#endif
0 27
new file mode 100644
... ...
@@ -0,0 +1,609 @@
0
+/*
1
+ *  Copyright (C) 2015-2019 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
2
+ *
3
+ *  Authors: Mickey Sola
4
+ *
5
+ *  This program is free software; you can redistribute it and/or modify
6
+ *  it under the terms of the GNU General Public License version 2 as
7
+ *  published by the Free Software Foundation.
8
+ *
9
+ *  This program is distributed in the hope that it will be useful,
10
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
+ *  GNU General Public License for more details.
13
+ *
14
+ *  You should have received a copy of the GNU General Public License
15
+ *  along with this program; if not, write to the Free Software
16
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
17
+ *  MA 02110-1301, USA.
18
+ */
19
+
20
+#if HAVE_CONFIG_H
21
+#include "clamav-config.h"
22
+#endif
23
+
24
+#if defined(FANOTIFY)
25
+
26
+#include <stdio.h>
27
+#include <stdlib.h>
28
+#include <unistd.h>
29
+#include <sys/types.h>
30
+#include <sys/stat.h>
31
+#include <fcntl.h>
32
+#include <signal.h>
33
+#include <pthread.h>
34
+#include <string.h>
35
+#include <errno.h>
36
+#include <stdbool.h>
37
+
38
+#include <sys/fanotify.h>
39
+#include <sys/inotify.h>
40
+
41
+#include "../fanotif/onaccess_fan.h"
42
+#include "onaccess_hash.h"
43
+#include "onaccess_ddd.h"
44
+#include "../scan/onaccess_scth.h"
45
+
46
+#include "libclamav/clamav.h"
47
+#include "libclamav/scanners.h"
48
+
49
+#include "shared/optparser.h"
50
+#include "shared/output.h"
51
+
52
+#include "clamd/server.h"
53
+#include "clamd/others.h"
54
+#include "clamd/scanner.h"
55
+
56
+static int onas_ddd_init_ht(uint32_t ht_size);
57
+static int onas_ddd_init_wdlt(uint64_t nwatches);
58
+static int onas_ddd_grow_wdlt();
59
+
60
+static int onas_ddd_watch(const char *pathname, int fan_fd, uint64_t fan_mask, int in_fd, uint64_t in_mask);
61
+static int onas_ddd_watch_hierarchy(const char *pathname, size_t len, int fd, uint64_t mask, uint32_t type);
62
+static int onas_ddd_unwatch(const char *pathname, int fan_fd, int in_fd);
63
+static int onas_ddd_unwatch_hierarchy(const char *pathname, size_t len, int fd, uint32_t type);
64
+
65
+static void onas_ddd_handle_in_moved_to(struct ddd_thrarg *tharg, const char *path, const char *child_path, const struct inotify_event *event, int wd, uint64_t in_mask);
66
+static void onas_ddd_handle_in_create(struct ddd_thrarg *tharg, const char *path, const char *child_path, const struct inotify_event *event, int wd, uint64_t in_mask);
67
+static void onas_ddd_handle_in_moved_from(struct ddd_thrarg *tharg, const char *path, const char *child_path, const struct inotify_event *event, int wd);
68
+static void onas_ddd_handle_in_delete(struct ddd_thrarg *tharg, const char *path, const char *child_path, const struct inotify_event *event, int wd);
69
+static void onas_ddd_handle_extra_scanning(struct ddd_thrarg *tharg, const char *pathname, int extra_options);
70
+
71
+static void onas_ddd_exit(int sig);
72
+
73
+/* TODO: Unglobalize these. */
74
+static struct onas_ht *ddd_ht;
75
+static char **wdlt;
76
+static uint32_t wdlt_len;
77
+static int onas_in_fd;
78
+
79
+static int onas_ddd_init_ht(uint32_t ht_size)
80
+{
81
+
82
+    if (ht_size <= 0)
83
+        ht_size = ONAS_DEFAULT_HT_SIZE;
84
+
85
+    return onas_ht_init(&ddd_ht, ht_size);
86
+}
87
+
88
+static int onas_ddd_init_wdlt(uint64_t nwatches)
89
+{
90
+
91
+    if (nwatches <= 0) return CL_EARG;
92
+
93
+    wdlt = (char **)cli_calloc(nwatches << 1, sizeof(char *));
94
+    if (!wdlt) return CL_EMEM;
95
+
96
+    wdlt_len = nwatches << 1;
97
+
98
+    return CL_SUCCESS;
99
+}
100
+
101
+static int onas_ddd_grow_wdlt()
102
+{
103
+
104
+    char **ptr = NULL;
105
+
106
+    ptr = (char **)cli_realloc(wdlt, wdlt_len << 1);
107
+    if (ptr) {
108
+        wdlt = ptr;
109
+        memset(&ptr[wdlt_len], 0, sizeof(char *) * (wdlt_len - 1));
110
+    } else {
111
+        return CL_EMEM;
112
+    }
113
+
114
+    wdlt_len <<= 1;
115
+
116
+    return CL_SUCCESS;
117
+}
118
+
119
+/* TODO: Support configuration for changing/setting number of inotify watches. */
120
+int onas_ddd_init(uint64_t nwatches, size_t ht_size)
121
+{
122
+
123
+    const char *nwatch_file = "/proc/sys/fs/inotify/max_user_watches";
124
+    int nwfd                = 0;
125
+    int ret                 = 0;
126
+    char nwatch_str[MAX_WATCH_LEN];
127
+    char *p  = NULL;
128
+    nwatches = 0;
129
+
130
+    nwfd = open(nwatch_file, O_RDONLY);
131
+    if (nwfd < 0) return CL_EOPEN;
132
+
133
+    ret = read(nwfd, nwatch_str, MAX_WATCH_LEN);
134
+    close(nwfd);
135
+    if (ret < 0) return CL_EREAD;
136
+
137
+    nwatches = strtol(nwatch_str, &p, 10);
138
+
139
+    ret = onas_ddd_init_wdlt(nwatches);
140
+    if (ret) return ret;
141
+
142
+    ret = onas_ddd_init_ht(ht_size);
143
+    if (ret) return ret;
144
+
145
+    return CL_SUCCESS;
146
+}
147
+
148
+static int onas_ddd_watch(const char *pathname, int fan_fd, uint64_t fan_mask, int in_fd, uint64_t in_mask)
149
+{
150
+    if (!pathname || fan_fd <= 0 || in_fd <= 0) return CL_ENULLARG;
151
+
152
+    int ret    = CL_SUCCESS;
153
+    size_t len = strlen(pathname);
154
+
155
+    ret = onas_ddd_watch_hierarchy(pathname, len, in_fd, in_mask, ONAS_IN);
156
+    if (ret) return ret;
157
+
158
+    ret = onas_ddd_watch_hierarchy(pathname, len, fan_fd, fan_mask, ONAS_FAN);
159
+    if (ret) return ret;
160
+
161
+    return CL_SUCCESS;
162
+}
163
+
164
+static int onas_ddd_watch_hierarchy(const char *pathname, size_t len, int fd, uint64_t mask, uint32_t type)
165
+{
166
+
167
+    if (!pathname || fd <= 0 || !type) return CL_ENULLARG;
168
+
169
+    if (type == (ONAS_IN | ONAS_FAN)) return CL_EARG;
170
+
171
+    struct onas_hnode *hnode  = NULL;
172
+    struct onas_element *elem = NULL;
173
+    int wd                    = 0;
174
+
175
+    if (onas_ht_get(ddd_ht, pathname, len, &elem) != CL_SUCCESS) return CL_EARG;
176
+
177
+    hnode = elem->data;
178
+
179
+    if (type & ONAS_IN) {
180
+        wd = inotify_add_watch(fd, pathname, (uint32_t)mask);
181
+
182
+        if (wd < 0) return CL_EARG;
183
+
184
+        if ((uint32_t)wd >= wdlt_len) {
185
+            onas_ddd_grow_wdlt();
186
+        }
187
+
188
+        /* Link the hash node to the watch descriptor lookup table */
189
+        hnode->wd = wd;
190
+        wdlt[wd]  = hnode->pathname;
191
+
192
+        hnode->watched |= ONAS_INWATCH;
193
+    } else if (type & ONAS_FAN) {
194
+        if (fanotify_mark(fd, FAN_MARK_ADD, mask, AT_FDCWD, hnode->pathname) < 0) return CL_EARG;
195
+        hnode->watched |= ONAS_FANWATCH;
196
+    } else {
197
+        return CL_EARG;
198
+    }
199
+
200
+    struct onas_lnode *curr = hnode->childhead;
201
+
202
+    while (curr->next != hnode->childtail) {
203
+        curr = curr->next;
204
+
205
+        size_t size      = len + strlen(curr->dirname) + 2;
206
+        char *child_path = (char *)cli_malloc(size);
207
+        if (child_path == NULL)
208
+            return CL_EMEM;
209
+        if (hnode->pathname[len - 1] == '/')
210
+            snprintf(child_path, --size, "%s%s", hnode->pathname, curr->dirname);
211
+        else
212
+            snprintf(child_path, size, "%s/%s", hnode->pathname, curr->dirname);
213
+
214
+        if (onas_ddd_watch_hierarchy(child_path, strlen(child_path), fd, mask, type)) {
215
+            return CL_EARG;
216
+        }
217
+        free(child_path);
218
+    }
219
+
220
+    return CL_SUCCESS;
221
+}
222
+
223
+static int onas_ddd_unwatch(const char *pathname, int fan_fd, int in_fd)
224
+{
225
+    if (!pathname || fan_fd <= 0 || in_fd <= 0) return CL_ENULLARG;
226
+
227
+    int ret    = CL_SUCCESS;
228
+    size_t len = strlen(pathname);
229
+
230
+    ret = onas_ddd_unwatch_hierarchy(pathname, len, in_fd, ONAS_IN);
231
+    if (ret) return ret;
232
+
233
+    ret = onas_ddd_unwatch_hierarchy(pathname, len, fan_fd, ONAS_FAN);
234
+    if (ret) return ret;
235
+
236
+    return CL_SUCCESS;
237
+}
238
+
239
+static int onas_ddd_unwatch_hierarchy(const char *pathname, size_t len, int fd, uint32_t type)
240
+{
241
+
242
+    if (!pathname || fd <= 0 || !type) return CL_ENULLARG;
243
+
244
+    if (type == (ONAS_IN | ONAS_FAN)) return CL_EARG;
245
+
246
+    struct onas_hnode *hnode  = NULL;
247
+    struct onas_element *elem = NULL;
248
+    int wd                    = 0;
249
+
250
+    if (onas_ht_get(ddd_ht, pathname, len, &elem)) return CL_EARG;
251
+
252
+    hnode = elem->data;
253
+
254
+    if (type & ONAS_IN) {
255
+        wd = hnode->wd;
256
+
257
+        if (!inotify_rm_watch(fd, wd)) return CL_EARG;
258
+
259
+        /* Unlink the hash node from the watch descriptor lookup table */
260
+        hnode->wd = 0;
261
+        wdlt[wd]  = NULL;
262
+
263
+        hnode->watched = ONAS_STOPWATCH;
264
+    } else if (type & ONAS_FAN) {
265
+        if (fanotify_mark(fd, FAN_MARK_REMOVE, 0, AT_FDCWD, hnode->pathname) < 0) return CL_EARG;
266
+        hnode->watched = ONAS_STOPWATCH;
267
+    } else {
268
+        return CL_EARG;
269
+    }
270
+
271
+    struct onas_lnode *curr = hnode->childhead;
272
+
273
+    while (curr->next != hnode->childtail) {
274
+        curr = curr->next;
275
+
276
+        size_t size      = len + strlen(curr->dirname) + 2;
277
+        char *child_path = (char *)cli_malloc(size);
278
+        if (child_path == NULL)
279
+            return CL_EMEM;
280
+        if (hnode->pathname[len - 1] == '/')
281
+            snprintf(child_path, --size, "%s%s", hnode->pathname, curr->dirname);
282
+        else
283
+            snprintf(child_path, size, "%s/%s", hnode->pathname, curr->dirname);
284
+
285
+        onas_ddd_unwatch_hierarchy(child_path, strlen(child_path), fd, type);
286
+        free(child_path);
287
+    }
288
+
289
+    return CL_SUCCESS;
290
+}
291
+
292
+void *onas_ddd_th(void *arg)
293
+{
294
+    struct ddd_thrarg *tharg = (struct ddd_thrarg *)arg;
295
+    sigset_t sigset;
296
+    struct sigaction act;
297
+    const struct optstruct *pt;
298
+    uint64_t in_mask = IN_ONLYDIR | IN_MOVE | IN_DELETE | IN_CREATE;
299
+    fd_set rfds;
300
+    char buf[4096];
301
+    ssize_t bread;
302
+    const struct inotify_event *event;
303
+    int ret, len;
304
+
305
+    /* ignore all signals except SIGUSR1 */
306
+    sigfillset(&sigset);
307
+    sigdelset(&sigset, SIGUSR1);
308
+    /* The behavior of a process is undefined after it ignores a
309
+	 * SIGFPE, SIGILL, SIGSEGV, or SIGBUS signal */
310
+    sigdelset(&sigset, SIGFPE);
311
+    sigdelset(&sigset, SIGILL);
312
+    sigdelset(&sigset, SIGSEGV);
313
+#ifdef SIGBUS
314
+    sigdelset(&sigset, SIGBUS);
315
+#endif
316
+    pthread_sigmask(SIG_SETMASK, &sigset, NULL);
317
+    memset(&act, 0, sizeof(struct sigaction));
318
+    act.sa_handler = onas_ddd_exit;
319
+    sigfillset(&(act.sa_mask));
320
+    sigaction(SIGUSR1, &act, NULL);
321
+    sigaction(SIGSEGV, &act, NULL);
322
+
323
+    onas_in_fd = inotify_init1(IN_NONBLOCK);
324
+    if (onas_in_fd == -1) {
325
+        logg("!ScanOnAccess: Could not init inotify.");
326
+        return NULL;
327
+    }
328
+
329
+    ret = onas_ddd_init(0, ONAS_DEFAULT_HT_SIZE);
330
+    if (ret) {
331
+        logg("!ScanOnAccess: Failed to initialize 3D. \n");
332
+        return NULL;
333
+    }
334
+
335
+    /* Add provided paths recursively. */
336
+    if ((pt = optget(tharg->opts, "OnAccessIncludePath"))->enabled) {
337
+        while (pt) {
338
+            if (!strcmp(pt->strarg, "/")) {
339
+                logg("!ScanOnAccess: Not including path '%s' while DDD is enabled\n", pt->strarg);
340
+                logg("!ScanOnAccess: Please use the OnAccessMountPath option to watch '%s'\n", pt->strarg);
341
+                pt = (struct optstruct *)pt->nextarg;
342
+                continue;
343
+            }
344
+            if (onas_ht_get(ddd_ht, pt->strarg, strlen(pt->strarg), NULL) != CL_SUCCESS) {
345
+                if (onas_ht_add_hierarchy(ddd_ht, pt->strarg)) {
346
+                    logg("!ScanOnAccess: Can't include path '%s'\n", pt->strarg);
347
+                    return NULL;
348
+                } else
349
+                    logg("ScanOnAccess: Protecting directory '%s' (and all sub-directories)\n", pt->strarg);
350
+            }
351
+
352
+            pt = (struct optstruct *)pt->nextarg;
353
+        }
354
+    } else {
355
+        logg("!ScanOnAccess: Please specify at least one path with OnAccessIncludePath\n");
356
+        return NULL;
357
+    }
358
+
359
+    /* Remove provided paths recursively. */
360
+    if ((pt = optget(tharg->opts, "OnAccessExcludePath"))->enabled) {
361
+        while (pt) {
362
+            size_t ptlen = strlen(pt->strarg);
363
+            if (onas_ht_get(ddd_ht, pt->strarg, ptlen, NULL) == CL_SUCCESS) {
364
+                if (onas_ht_rm_hierarchy(ddd_ht, pt->strarg, ptlen, 0)) {
365
+                    logg("!ScanOnAccess: Can't exclude path '%s'\n", pt->strarg);
366
+                    return NULL;
367
+                } else
368
+                    logg("ScanOnAccess: Excluding  directory '%s' (and all sub-directories)\n", pt->strarg);
369
+            }
370
+
371
+            pt = (struct optstruct *)pt->nextarg;
372
+        }
373
+    }
374
+
375
+    /* Watch provided paths recursively */
376
+    if ((pt = optget(tharg->opts, "OnAccessIncludePath"))->enabled) {
377
+        while (pt) {
378
+            size_t ptlen = strlen(pt->strarg);
379
+            if (onas_ht_get(ddd_ht, pt->strarg, ptlen, NULL) == CL_SUCCESS) {
380
+                if (onas_ddd_watch(pt->strarg, tharg->fan_fd, tharg->fan_mask, onas_in_fd, in_mask)) {
381
+                    logg("!ScanOnAccess: Could not watch path '%s', %s\n", pt->strarg, strerror(errno));
382
+                    if (errno == EINVAL && optget(tharg->opts, "OnAccessPrevention")->enabled) {
383
+                        logg("!ScanOnAccess: When using the OnAccessPrevention option, please ensure your kernel\n\t\t\twas compiled with CONFIG_FANOTIFY_ACCESS_PERMISSIONS set to Y\n");
384
+
385
+                        kill(getpid(), SIGTERM);
386
+                    }
387
+                    return NULL;
388
+                }
389
+            }
390
+            pt = (struct optstruct *)pt->nextarg;
391
+        }
392
+    }
393
+
394
+    /* TODO: Re-enable OnAccessExtraScanning once the thread resource consumption issue is resolved. */
395
+#if 0
396
+	if(optget(tharg->opts, "OnAccessExtraScanning")->enabled) {
397
+		logg("ScanOnAccess: Extra scanning and notifications enabled.\n");
398
+}
399
+#endif
400
+
401
+    FD_ZERO(&rfds);
402
+    FD_SET(onas_in_fd, &rfds);
403
+
404
+    while (1) {
405
+        do {
406
+            ret = select(onas_in_fd + 1, &rfds, NULL, NULL, NULL);
407
+        } while (ret == -1 && errno == EINTR);
408
+
409
+        while ((bread = read(onas_in_fd, buf, sizeof(buf))) > 0) {
410
+
411
+            /* Handle events. */
412
+            int wd;
413
+            char *p           = buf;
414
+            const char *path  = NULL;
415
+            const char *child = NULL;
416
+            for (; p < buf + bread; p += sizeof(struct inotify_event) + event->len) {
417
+
418
+                event = (const struct inotify_event *)p;
419
+                wd    = event->wd;
420
+                path  = wdlt[wd];
421
+                child = event->name;
422
+
423
+                len              = strlen(path);
424
+                size_t size      = strlen(child) + len + 2;
425
+                char *child_path = (char *)cli_malloc(size);
426
+                if (child_path == NULL)
427
+                    return NULL;
428
+
429
+                if (path[len - 1] == '/')
430
+                    snprintf(child_path, --size, "%s%s", path, child);
431
+                else
432
+                    snprintf(child_path, size, "%s/%s", path, child);
433
+
434
+                if (event->mask & IN_DELETE) {
435
+                    onas_ddd_handle_in_delete(tharg, path, child_path, event, wd);
436
+
437
+                } else if (event->mask & IN_MOVED_FROM) {
438
+                    onas_ddd_handle_in_moved_from(tharg, path, child_path, event, wd);
439
+
440
+                } else if (event->mask & IN_CREATE) {
441
+                    onas_ddd_handle_in_create(tharg, path, child_path, event, wd, in_mask);
442
+
443
+                } else if (event->mask & IN_MOVED_TO) {
444
+                    onas_ddd_handle_in_moved_to(tharg, path, child_path, event, wd, in_mask);
445
+                }
446
+            }
447
+        }
448
+    }
449
+
450
+    return NULL;
451
+}
452
+
453
+static void onas_ddd_handle_in_delete(struct ddd_thrarg *tharg,
454
+                                      const char *path, const char *child_path, const struct inotify_event *event, int wd)
455
+{
456
+
457
+    struct stat s;
458
+    if (stat(child_path, &s) == 0 && S_ISREG(s.st_mode)) return;
459
+    if (!(event->mask & IN_ISDIR)) return;
460
+
461
+    logg("*ddd: DELETE - Removing %s from %s with wd:%d\n", child_path, path, wd);
462
+    onas_ddd_unwatch(child_path, tharg->fan_fd, onas_in_fd);
463
+    onas_ht_rm_hierarchy(ddd_ht, child_path, strlen(child_path), 0);
464
+
465
+    return;
466
+}
467
+
468
+static void onas_ddd_handle_in_moved_from(struct ddd_thrarg *tharg,
469
+                                          const char *path, const char *child_path, const struct inotify_event *event, int wd)
470
+{
471
+
472
+    struct stat s;
473
+    if (stat(child_path, &s) == 0 && S_ISREG(s.st_mode)) return;
474
+    if (!(event->mask & IN_ISDIR)) return;
475
+
476
+    logg("*ddd: MOVED_FROM - Removing %s from %s with wd:%d\n", child_path, path, wd);
477
+    onas_ddd_unwatch(child_path, tharg->fan_fd, onas_in_fd);
478
+    onas_ht_rm_hierarchy(ddd_ht, child_path, strlen(child_path), 0);
479
+
480
+    return;
481
+}
482
+
483
+static void onas_ddd_handle_in_create(struct ddd_thrarg *tharg,
484
+                                      const char *path, const char *child_path, const struct inotify_event *event, int wd, uint64_t in_mask)
485
+{
486
+
487
+    struct stat s;
488
+
489
+    /* TODO: Re-enable OnAccessExtraScanning once the thread resource consumption issue is resolved. */
490
+#if 0
491
+	if (optget(tharg->opts, "OnAccessExtraScanning")->enabled) {
492
+		if(stat(child_path, &s) == 0 && S_ISREG(s.st_mode)) {
493
+			onas_ddd_handle_extra_scanning(tharg, child_path, ONAS_SCTH_ISFILE);
494
+
495
+		} else if(stat(child_path, &s) == 0 && S_ISDIR(s.st_mode)) {
496
+			logg("*ddd: CREATE - Adding %s to %s with wd:%d\n", child_path, path, wd);
497
+			onas_ht_add_hierarchy(ddd_ht, child_path);
498
+			onas_ddd_watch(child_path, tharg->fan_fd, tharg->fan_mask, onas_in_fd, in_mask);
499
+
500
+			onas_ddd_handle_extra_scanning(tharg, child_path, ONAS_SCTH_ISDIR);
501
+		}
502
+	}
503
+	else
504
+#endif
505
+    {
506
+        if (stat(child_path, &s) == 0 && S_ISREG(s.st_mode)) return;
507
+        if (!(event->mask & IN_ISDIR)) return;
508
+
509
+        logg("*ddd: MOVED_TO - Adding %s to %s with wd:%d\n", child_path, path, wd);
510
+        onas_ht_add_hierarchy(ddd_ht, child_path);
511
+        onas_ddd_watch(child_path, tharg->fan_fd, tharg->fan_mask, onas_in_fd, in_mask);
512
+    }
513
+
514
+    return;
515
+}
516
+
517
+static void onas_ddd_handle_in_moved_to(struct ddd_thrarg *tharg,
518
+                                        const char *path, const char *child_path, const struct inotify_event *event, int wd, uint64_t in_mask)
519
+{
520
+
521
+    struct stat s;
522
+    /* TODO: Re-enable OnAccessExtraScanning once the thread resource consumption issue is resolved. */
523
+#if 0
524
+	if (optget(tharg->opts, "OnAccessExtraScanning")->enabled) {
525
+		if(stat(child_path, &s) == 0 && S_ISREG(s.st_mode)) {
526
+			onas_ddd_handle_extra_scanning(tharg, child_path, ONAS_SCTH_ISFILE);
527
+
528
+		} else if(stat(child_path, &s) == 0 && S_ISDIR(s.st_mode)) {
529
+			logg("*ddd: MOVED_TO - Adding %s to %s with wd:%d\n", child_path, path, wd);
530
+			onas_ht_add_hierarchy(ddd_ht, child_path);
531
+			onas_ddd_watch(child_path, tharg->fan_fd, tharg->fan_mask, onas_in_fd, in_mask);
532
+
533
+			onas_ddd_handle_extra_scanning(tharg, child_path, ONAS_SCTH_ISDIR);
534
+		}
535
+	}
536
+	else
537
+#endif
538
+    {
539
+        if (stat(child_path, &s) == 0 && S_ISREG(s.st_mode)) return;
540
+        if (!(event->mask & IN_ISDIR)) return;
541
+
542
+        logg("*ddd: MOVED_TO - Adding %s to %s with wd:%d\n", child_path, path, wd);
543
+        onas_ht_add_hierarchy(ddd_ht, child_path);
544
+        onas_ddd_watch(child_path, tharg->fan_fd, tharg->fan_mask, onas_in_fd, in_mask);
545
+    }
546
+
547
+    return;
548
+}
549
+
550
+static void onas_ddd_handle_extra_scanning(struct ddd_thrarg *tharg, const char *pathname, int extra_options)
551
+{
552
+
553
+    int thread_started             = 1;
554
+    struct scth_thrarg *scth_tharg = NULL;
555
+    pthread_attr_t scth_attr;
556
+    pthread_t scth_pid = 0;
557
+
558
+    do {
559
+        if (pthread_attr_init(&scth_attr)) break;
560
+        pthread_attr_setdetachstate(&scth_attr, PTHREAD_CREATE_JOINABLE);
561
+
562
+        /* Allocate memory for arguments. Thread is responsible for freeing it. */
563
+        if (!(scth_tharg = (struct scth_thrarg *)calloc(sizeof(struct scth_thrarg), 1))) break;
564
+        if (!(scth_tharg->options = (struct cl_scan_options *)calloc(sizeof(struct cl_scan_options), 1))) break;
565
+
566
+        (void)memcpy(scth_tharg->options, tharg->options, sizeof(struct cl_scan_options));
567
+
568
+        scth_tharg->extra_options = extra_options;
569
+        scth_tharg->opts          = tharg->opts;
570
+        scth_tharg->pathname      = strdup(pathname);
571
+        scth_tharg->engine        = tharg->engine;
572
+
573
+        thread_started = pthread_create(&scth_pid, &scth_attr, onas_scan_th, scth_tharg);
574
+    } while (0);
575
+
576
+    if (0 != thread_started) {
577
+        /* Failed to create thread. Free anything we may have allocated. */
578
+        logg("!ScanOnAccess: Unable to kick off extra scanning.\n");
579
+        if (NULL != scth_tharg) {
580
+            if (NULL != scth_tharg->pathname) {
581
+                free(scth_tharg->pathname);
582
+                scth_tharg->pathname = NULL;
583
+            }
584
+            if (NULL != scth_tharg->options) {
585
+                free(scth_tharg->options);
586
+                scth_tharg->options = NULL;
587
+            }
588
+            free(scth_tharg);
589
+            scth_tharg = NULL;
590
+        }
591
+    }
592
+
593
+    return;
594
+}
595
+
596
+static void onas_ddd_exit(int sig)
597
+{
598
+    logg("*ScanOnAccess: onas_ddd_exit(), signal %d\n", sig);
599
+
600
+    close(onas_in_fd);
601
+
602
+    onas_free_ht(ddd_ht);
603
+    free(wdlt);
604
+
605
+    pthread_exit(NULL);
606
+    logg("ScanOnAccess: stopped\n");
607
+}
608
+#endif
0 609
new file mode 100644
... ...
@@ -0,0 +1,47 @@
0
+/*
1
+ *  Copyright (C) 2015-2019 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
2
+ *
3
+ *  Authors: Mickey Sola
4
+ *
5
+ *  This program is free software; you can redistribute it and/or modify
6
+ *  it under the terms of the GNU General Public License version 2 as
7
+ *  published by the Free Software Foundation.
8
+ *
9
+ *  This program is distributed in the hope that it will be useful,
10
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
+ *  GNU General Public License for more details.
13
+ *
14
+ *  You should have received a copy of the GNU General Public License
15
+ *  along with this program; if not, write to the Free Software
16
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
17
+ *  MA 02110-1301, USA.
18
+ */
19
+
20
+#ifndef __ONAS_IN_H
21
+#define __ONAS_IN_H
22
+
23
+#include "shared/optparser.h"
24
+#include "libclamav/clamav.h"
25
+
26
+/*
27
+ * Extra options for onas_scan_th(). 
28
+ */
29
+#define ONAS_IN 0x01
30
+#define ONAS_FAN 0x02
31
+
32
+#define MAX_WATCH_LEN 7
33
+
34
+struct ddd_thrarg {
35
+    int sid;
36
+    struct cl_scan_options *options;
37
+    int fan_fd;
38
+    uint64_t fan_mask;
39
+    const struct optstruct *opts;
40
+    const struct cl_engine *engine;
41
+};
42
+
43
+int onas_ddd_init(uint64_t nwatches, size_t ht_size);
44
+void *onas_ddd_th(void *arg);
45
+
46
+#endif
0 47
new file mode 100644
... ...
@@ -0,0 +1,700 @@
0
+/*
1
+ *  Copyright (C) 2015-2019 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
2
+ *
3
+ *  Authors: Mickey Sola
4
+ *
5
+ *  This program is free software; you can redistribute it and/or modify
6
+ *  it under the terms of the GNU General Public License version 2 as
7
+ *  published by the Free Software Foundation.
8
+ *
9
+ *  This program is distributed in the hope that it will be useful,
10
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
+ *  GNU General Public License for more details.
13
+ *
14
+ *  You should have received a copy of the GNU General Public License
15
+ *  along with this program; if not, write to the Free Software
16
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
17
+ *  MA 02110-1301, USA.
18
+ */
19
+
20
+#if HAVE_CONFIG_H
21
+#include "clamav-config.h"
22
+#endif
23
+
24
+#if defined(FANOTIFY)
25
+#include <stdio.h>
26
+#include <unistd.h>
27
+#include <sys/types.h>
28
+#include <sys/stat.h>
29
+#include <fcntl.h>
30
+#include <signal.h>
31
+#include <pthread.h>
32
+#include <string.h>
33
+#include <errno.h>
34
+#include <stdbool.h>
35
+
36
+#include <sys/fanotify.h>
37
+
38
+#include "../fanotif/onaccess_fan.h"
39
+#include "onaccess_hash.h"
40
+#include "onaccess_ddd.h"
41
+
42
+#include "libclamav/clamav.h"
43
+#include "libclamav/scanners.h"
44
+#include "libclamav/str.h"
45
+
46
+#include "shared/optparser.h"
47
+#include "shared/output.h"
48
+
49
+#include "clamd/server.h"
50
+#include "clamd/others.h"
51
+#include "clamd/scanner.h"
52
+#include "clamd/priv_fts.h"
53
+
54
+static struct onas_bucket *onas_bucket_init();
55
+static void onas_free_bucket(struct onas_bucket *bckt);
56
+static int onas_bucket_insert(struct onas_bucket *bckt, struct onas_element *elem);
57
+static int onas_bucket_remove(struct onas_bucket *bckt, struct onas_element *elem);
58
+
59
+static int onas_add_hashnode_child(struct onas_hnode *node, const char *dirname);
60
+
61
+static struct onas_lnode *onas_listnode_init(void);
62
+
63
+static struct onas_hnode *onas_hashnode_init(void);
64
+
65
+static inline uint32_t onas_hshift(uint32_t hash)
66
+{
67
+
68
+    hash = ~hash;
69
+
70
+    hash += (hash << 15);
71
+    hash ^= (hash >> 12);
72
+    hash += (hash << 2);
73
+    hash ^= (hash >> 4);
74
+    hash += (hash << 3);
75
+    hash += (hash << 11);
76
+    hash ^= (hash >> 16);
77
+
78
+    return hash;
79
+}
80
+
81
+static inline int onas_hash(const char *key, size_t keylen, uint32_t size)
82
+{
83
+
84
+    uint32_t hash = 1;
85
+    uint32_t i;
86
+
87
+    for (i = 0; i < keylen; i++) {
88
+        hash += key[i];
89
+        hash = onas_hshift(hash);
90
+    }
91
+
92
+    return hash & (size - 1);
93
+}
94
+
95
+int onas_ht_init(struct onas_ht **ht, uint32_t size)
96
+{
97
+
98
+    if (size == 0 || (size & (~size + 1)) != size) return CL_EARG;
99
+
100
+    *ht = (struct onas_ht *)cli_malloc(sizeof(struct onas_ht));
101
+    if (!(*ht)) return CL_EMEM;
102
+
103
+    **ht = (struct onas_ht){
104
+        .htable = NULL,
105
+        .size   = size,
106
+        .nbckts = 0,
107
+    };
108
+
109
+    if (!((*ht)->htable = (struct onas_bucket **)cli_calloc(size, sizeof(struct onas_bucket *)))) {
110
+        onas_free_ht(*ht);
111
+        return CL_EMEM;
112
+    }
113
+
114
+    return CL_SUCCESS;
115
+}
116
+
117
+void onas_free_ht(struct onas_ht *ht)
118
+{
119
+
120
+    if (!ht || ht->size == 0) return;
121
+
122
+    if (!ht->htable) {
123
+        free(ht);
124
+        return;
125
+    }
126
+
127
+    uint32_t i = 0;
128
+    for (i = 0; i < ht->size; i++) {
129
+        onas_free_bucket(ht->htable[i]);
130
+        ht->htable[i] = NULL;
131
+    }
132
+
133
+    free(ht->htable);
134
+    ht->htable = NULL;
135
+
136
+    free(ht);
137
+
138
+    return;
139
+}
140
+
141
+static struct onas_bucket *onas_bucket_init()
142
+{
143
+
144
+    struct onas_bucket *bckt = (struct onas_bucket *)cli_malloc(sizeof(struct onas_bucket));
145
+    if (!bckt) return NULL;
146
+
147
+    *bckt = (struct onas_bucket){
148
+        .size = 0,
149
+        .head = NULL,
150
+        .tail = NULL};
151
+
152
+    return bckt;
153
+}
154
+
155
+static void onas_free_bucket(struct onas_bucket *bckt)
156
+{
157
+
158
+    if (!bckt) return;
159
+
160
+    uint32_t i                = 0;
161
+    struct onas_element *curr = NULL;
162
+
163
+    for (i = 0; i < bckt->size; i++) {
164
+        curr       = bckt->head;
165
+        bckt->head = curr->next;
166
+        onas_free_element(curr);
167
+        curr = NULL;
168
+    }
169
+
170
+    free(bckt);
171
+
172
+    return;
173
+}
174
+
175
+struct onas_element *onas_element_init(struct onas_hnode *value, const char *key, size_t klen)
176
+{
177
+
178
+    struct onas_element *elem = (struct onas_element *)cli_malloc(sizeof(struct onas_element));
179
+    if (!elem) return NULL;
180
+
181
+    *elem = (struct onas_element){
182
+        .key  = key,
183
+        .klen = klen,
184
+        .data = value,
185
+        .next = NULL,
186
+        .prev = NULL};
187
+
188
+    return elem;
189
+}
190
+
191
+void onas_free_element(struct onas_element *elem)
192
+{
193
+
194
+    if (!elem) return;
195
+
196
+    onas_free_hashnode(elem->data);
197
+
198
+    elem->prev = NULL;
199
+    elem->next = NULL;
200
+
201
+    free(elem);
202
+
203
+    return;
204
+}
205
+
206
+int onas_ht_insert(struct onas_ht *ht, struct onas_element *elem)
207
+{
208
+
209
+    if (!ht || !elem || !elem->key) return CL_ENULLARG;
210
+
211
+    int idx                  = onas_hash(elem->key, elem->klen, ht->size);
212
+    struct onas_bucket *bckt = ht->htable[idx];
213
+
214
+    int ret        = 0;
215
+    uint32_t bsize = 0;
216
+
217
+    if (bckt == NULL) {
218
+        ht->htable[idx] = onas_bucket_init();
219
+        bckt            = ht->htable[idx];
220
+    }
221
+
222
+    bsize = bckt->size;
223
+    ret   = onas_bucket_insert(bckt, elem);
224
+
225
+    if (ret == CL_SUCCESS)
226
+        if (bsize < bckt->size)
227
+            ht->nbckts++;
228
+
229
+    return ret;
230
+}
231
+
232
+static int onas_bucket_insert(struct onas_bucket *bckt, struct onas_element *elem)
233
+{
234
+    if (!bckt || !elem) return CL_ENULLARG;
235
+
236
+    if (bckt->size == 0) {
237
+        bckt->head = elem;
238
+        bckt->tail = elem;
239
+        elem->prev = NULL;
240
+        elem->next = NULL;
241
+        bckt->size++;
242
+    } else {
243
+        struct onas_element *btail = bckt->tail;
244
+
245
+        btail->next = elem;
246
+        elem->prev  = btail;
247
+        elem->next  = NULL;
248
+        bckt->tail  = elem;
249
+        bckt->size++;
250
+    }
251
+
252
+    return CL_SUCCESS;
253
+}
254
+
255
+/* Checks if key exists and optionally stores address to the element corresponding to the key within elem */
256
+int onas_ht_get(struct onas_ht *ht, const char *key, size_t klen, struct onas_element **elem)
257
+{
258
+
259
+    if (elem) *elem = NULL;
260
+
261
+    if (!ht || !key || klen <= 0) return CL_ENULLARG;
262
+
263
+    struct onas_bucket *bckt = ht->htable[onas_hash(key, klen, ht->size)];
264
+
265
+    if (!bckt || bckt->size == 0) return CL_EARG;
266
+
267
+    struct onas_element *curr = bckt->head;
268
+
269
+    while (curr && strcmp(curr->key, key)) {
270
+        curr = curr->next;
271
+    }
272
+
273
+    if (!curr) return CL_EARG;
274
+
275
+    if (elem) *elem = curr;
276
+
277
+    return CL_SUCCESS;
278
+}
279
+
280
+/* Removes the element corresponding to key from the hashtable and optionally returns a pointer to the removed element. */
281
+int onas_ht_remove(struct onas_ht *ht, const char *key, size_t klen, struct onas_element **relem)
282
+{
283
+    if (!ht || !key || klen <= 0) return CL_ENULLARG;
284
+
285
+    struct onas_bucket *bckt = ht->htable[onas_hash(key, klen, ht->size)];
286
+
287
+    if (!bckt) return CL_EARG;
288
+
289
+    struct onas_element *elem = NULL;
290
+    onas_ht_get(ht, key, klen, &elem);
291
+
292
+    if (!elem) return CL_EARG;
293
+
294
+    int ret = onas_bucket_remove(bckt, elem);
295
+
296
+    if (relem) *relem = elem;
297
+
298
+    return ret;
299
+}
300
+
301
+static int onas_bucket_remove(struct onas_bucket *bckt, struct onas_element *elem)
302
+{
303
+    if (!bckt || !elem) return CL_ENULLARG;
304
+
305
+    struct onas_element *curr = bckt->head;
306
+
307
+    while (curr && curr != elem) {
308
+        curr = curr->next;
309
+    }
310
+
311
+    if (!curr) return CL_EARG;
312
+
313
+    if (bckt->head == elem) {
314
+        bckt->head = elem->next;
315
+        if (bckt->head) bckt->head->prev = NULL;
316
+
317
+        elem->next = NULL;
318
+    } else if (bckt->tail == elem) {
319
+        bckt->tail = elem->prev;
320
+        if (bckt->tail) bckt->tail->next = NULL;
321
+
322
+        elem->prev = NULL;
323
+    } else {
324
+        struct onas_element *tmp = NULL;
325
+
326
+        tmp = elem->prev;
327
+        if (tmp) {
328
+            tmp->next = elem->next;
329
+            tmp       = elem->next;
330
+            tmp->prev = elem->prev;
331
+        }
332
+
333
+        elem->prev = NULL;
334
+        elem->next = NULL;
335
+    }
336
+
337
+    bckt->size--;
338
+
339
+    return CL_SUCCESS;
340
+}
341
+
342
+/* Dealing with hash nodes and list nodes */
343
+
344
+/* Function to initialize hashnode. */
345
+static struct onas_hnode *onas_hashnode_init(void)
346
+{
347
+    struct onas_hnode *hnode = NULL;
348
+    if (!(hnode = (struct onas_hnode *)cli_malloc(sizeof(struct onas_hnode)))) {
349
+        return NULL;
350
+    }
351
+
352
+    *hnode = (struct onas_hnode){
353
+        .pathlen       = 0,
354
+        .pathname      = NULL,
355
+        .prnt_pathlen  = 0,
356
+        .prnt_pathname = NULL,
357
+        .childhead     = NULL,
358
+        .childtail     = NULL,
359
+        .wd            = 0,
360
+        .watched       = 0};
361
+
362
+    if (!(hnode->childhead = (struct onas_lnode *)onas_listnode_init())) {
363
+        onas_free_hashnode(hnode);
364
+        return NULL;
365
+    }
366
+
367
+    if (!(hnode->childtail = (struct onas_lnode *)onas_listnode_init())) {
368
+        onas_free_hashnode(hnode);
369
+        return NULL;
370
+    }
371
+
372
+    hnode->childhead->next = (struct onas_lnode *)hnode->childtail;
373
+    hnode->childtail->prev = (struct onas_lnode *)hnode->childhead;
374
+
375
+    return hnode;
376
+}
377
+
378
+/* Function to initialize listnode. */
379
+static struct onas_lnode *onas_listnode_init(void)
380
+{
381
+    struct onas_lnode *lnode = NULL;
382
+    if (!(lnode = (struct onas_lnode *)cli_malloc(sizeof(struct onas_lnode)))) {
383
+        return NULL;
384
+    }
385
+
386
+    *lnode = (struct onas_lnode){
387
+        .dirname = NULL,
388
+        .next    = NULL,
389
+        .prev    = NULL};
390
+
391
+    return lnode;
392
+}
393
+
394
+/* Function to free hashnode. */
395
+void onas_free_hashnode(struct onas_hnode *hnode)
396
+{
397
+    if (!hnode) return;
398
+
399
+    onas_free_dirlist(hnode->childhead);
400
+    hnode->childhead = NULL;
401
+
402
+    free(hnode->pathname);
403
+    hnode->pathname = NULL;
404
+
405
+    free(hnode->prnt_pathname);
406
+    hnode->prnt_pathname = NULL;
407
+
408
+    free(hnode);
409
+
410
+    return;
411
+}
412
+
413
+/* Function to free list of listnodes. */
414
+void onas_free_dirlist(struct onas_lnode *head)
415
+{
416
+    if (!head) return;
417
+    struct onas_lnode *curr = head;
418
+    struct onas_lnode *tmp  = curr;
419
+
420
+    while (curr) {
421
+        tmp = curr->next;
422
+        onas_free_listnode(curr);
423
+        curr = tmp;
424
+    }
425
+
426
+    return;
427
+}
428
+
429
+/* Function to free a listnode. */
430
+void onas_free_listnode(struct onas_lnode *lnode)
431
+{
432
+    if (!lnode) return;
433
+
434
+    lnode->next = NULL;
435
+    lnode->prev = NULL;
436
+
437
+    free(lnode->dirname);
438
+    lnode->dirname = NULL;
439
+
440
+    free(lnode);
441
+
442
+    return;
443
+}
444
+
445
+static int onas_add_hashnode_child(struct onas_hnode *node, const char *dirname)
446
+{
447
+    if (!node || !dirname) return CL_ENULLARG;
448
+
449
+    struct onas_lnode *child = onas_listnode_init();
450
+    if (!child) return CL_EMEM;
451
+
452
+    size_t n       = strlen(dirname);
453
+    child->dirname = cli_strndup(dirname, n);
454
+
455
+    onas_add_listnode(node->childtail, child);
456
+
457
+    return CL_SUCCESS;
458
+}
459
+
460
+/* Function to add a dir_listnode to a list */
461
+int onas_add_listnode(struct onas_lnode *tail, struct onas_lnode *node)
462
+{
463
+    if (!tail || !node) return CL_ENULLARG;
464
+
465
+    struct onas_lnode *tmp = tail->prev;
466
+
467
+    tmp->next  = node;
468
+    node->prev = tail->prev;
469
+
470
+    node->next = tail;
471
+    tail->prev = node;
472
+
473
+    return CL_SUCCESS;
474
+}
475
+
476
+/* Function to remove a listnode based on dirname. */
477
+int onas_rm_listnode(struct onas_lnode *head, const char *dirname)
478
+{
479
+    if (!dirname || !head) return CL_ENULLARG;
480
+
481
+    struct onas_lnode *curr = head;
482
+    size_t n                = strlen(dirname);
483
+
484
+    while ((curr = curr->next)) {
485
+        if (!strncmp(curr->dirname, dirname, n)) {
486
+            struct onas_lnode *tmp = curr->prev;
487
+            tmp->next              = curr->next;
488
+            tmp                    = curr->next;
489
+            tmp->prev              = curr->prev;
490
+
491
+            onas_free_listnode(curr);
492
+
493
+            return CL_SUCCESS;
494
+        }
495
+    }
496
+
497
+    return -1;
498
+}
499
+
500
+/*** Dealing with parent/child relationships in the table. ***/
501
+
502
+/* Determines parent and returns a copy based on full pathname. */
503
+inline static char *onas_get_parent(const char *pathname, size_t len)
504
+{
505
+    if (!pathname || len <= 1) return NULL;
506
+
507
+    int idx   = len - 2;
508
+    char *ret = NULL;
509
+
510
+    while (idx >= 0 && pathname[idx] != '/') {
511
+        idx--;
512
+    }
513
+
514
+    if (idx == 0) {
515
+        idx++;
516
+    }
517
+
518
+    ret = cli_strndup(pathname, idx);
519
+    if (!ret) {
520
+        errno = ENOMEM;
521
+        return NULL;
522
+    }
523
+
524
+    return ret;
525
+}
526
+
527
+/* Gets the index at which the name of directory begins from the full pathname. */
528
+inline static int onas_get_dirname_idx(const char *pathname, size_t len)
529
+{
530
+    if (!pathname || len <= 1) return -1;
531
+
532
+    int idx = len - 2;
533
+
534
+    while (idx >= 0 && pathname[idx] != '/') {
535
+        idx--;
536
+    }
537
+
538
+    if (pathname[idx] == '/')
539
+        return idx + 1;
540
+
541
+    return idx;
542
+}
543
+
544
+/* Emancipates the specified child from the specified parent. */
545
+int onas_ht_rm_child(struct onas_ht *ht, const char *prntpath, size_t prntlen, const char *childpath, size_t childlen)
546
+{
547
+
548
+    if (!ht || !prntpath || prntlen <= 0 || !childpath || childlen <= 1) return CL_ENULLARG;
549
+
550
+    struct onas_element *elem = NULL;
551
+    struct onas_hnode *hnode  = NULL;
552
+    int idx                   = onas_get_dirname_idx(childpath, childlen);
553
+    int ret                   = 0;
554
+
555
+    if (idx <= 0) return CL_SUCCESS;
556
+
557
+    if (onas_ht_get(ht, prntpath, prntlen, &elem) != CL_SUCCESS) return CL_EARG;
558
+
559
+    hnode = elem->data;
560
+
561
+    if ((ret = onas_rm_listnode(hnode->childhead, &(childpath[idx])))) return CL_EARG;
562
+
563
+    return CL_SUCCESS;
564
+}
565
+
566
+/* The specified parent adds the specified child to its list. */
567
+int onas_ht_add_child(struct onas_ht *ht, const char *prntpath, size_t prntlen, const char *childpath, size_t childlen)
568
+{
569
+    if (!ht || !prntpath || prntlen <= 0 || !childpath || childlen <= 1) return CL_ENULLARG;
570
+
571
+    struct onas_element *elem = NULL;
572
+    struct onas_hnode *hnode  = NULL;
573
+    int idx                   = onas_get_dirname_idx(childpath, childlen);
574
+
575
+    if (idx <= 0) return CL_SUCCESS;
576
+
577
+    if (onas_ht_get(ht, prntpath, prntlen, &elem)) return CL_EARG;
578
+    hnode = elem->data;
579
+
580
+    return onas_add_hashnode_child(hnode, &(childpath[idx]));
581
+}
582
+
583
+/*** Dealing with hierarchy changes. ***/
584
+
585
+/* Adds the hierarchy under pathname to the tree and allocates all necessary memory. */
586
+int onas_ht_add_hierarchy(struct onas_ht *ht, const char *pathname)
587
+{
588
+    if (!ht || !pathname) return CL_ENULLARG;
589
+
590
+    FTS *ftsp         = NULL;
591
+    int ftspopts      = FTS_PHYSICAL | FTS_XDEV;
592
+    FTSENT *curr      = NULL;
593
+    FTSENT *childlist = NULL;
594
+
595
+    size_t len = strlen(pathname);
596
+    char *prnt = onas_get_parent(pathname, len);
597
+    if (prnt) onas_ht_add_child(ht, prnt, strlen(prnt), pathname, len);
598
+    free(prnt);
599
+
600
+    char *const pathargv[] = {(char *)pathname, NULL};
601
+    if (!(ftsp = _priv_fts_open(pathargv, ftspopts, NULL))) {
602
+        logg("!ScanOnAccess: Could not open '%s'\n", pathname);
603
+        return CL_EARG;
604
+    }
605
+
606
+    while ((curr = _priv_fts_read(ftsp))) {
607
+
608
+        struct onas_hnode *hnode = NULL;
609
+
610
+        /* May want to handle other options in the future. */
611
+        switch (curr->fts_info) {
612
+            case FTS_D:
613
+                hnode = onas_hashnode_init();
614
+                if (!hnode) return CL_EMEM;
615
+
616
+                hnode->pathlen  = curr->fts_pathlen;
617
+                hnode->pathname = cli_strndup(curr->fts_path, hnode->pathlen);
618
+
619
+                hnode->prnt_pathname = onas_get_parent(hnode->pathname, hnode->pathlen);
620
+                if (hnode->prnt_pathname)
621
+                    hnode->prnt_pathlen = strlen(hnode->prnt_pathname);
622
+                else
623
+                    hnode->prnt_pathlen = 0;
624
+                break;
625
+            default:
626
+                continue;
627
+        }
628
+
629
+        if ((childlist = _priv_fts_children(ftsp, 0))) {
630
+            do {
631
+                if (childlist->fts_info == FTS_D) {
632
+                    if (CL_EMEM == onas_add_hashnode_child(hnode, childlist->fts_name)) {
633
+                        onas_free_hashnode(hnode);
634
+                        return CL_EMEM;
635
+                    }
636
+                }
637
+
638
+            } while ((childlist = childlist->fts_link));
639
+        }
640
+
641
+        struct onas_element *elem = onas_element_init(hnode, hnode->pathname, hnode->pathlen);
642
+        if (!elem) return CL_EMEM;
643
+
644
+        if (onas_ht_insert(ht, elem)) {
645
+            onas_free_element(elem);
646
+            return CL_EMEM;
647
+        }
648
+    }
649
+
650
+    _priv_fts_close(ftsp);
651
+    return CL_SUCCESS;
652
+}
653
+
654
+/* Removes the underlying hierarchy from the tree and frees all associated memory. */
655
+int onas_ht_rm_hierarchy(struct onas_ht *ht, const char *pathname, size_t len, int level)
656
+{
657
+    if (!ht || !pathname || len <= 0) return CL_ENULLARG;
658
+
659
+    struct onas_hnode *hnode  = NULL;
660
+    struct onas_element *elem = NULL;
661
+    char *prntname            = NULL;
662
+    size_t prntlen            = 0;
663
+
664
+    if (onas_ht_get(ht, pathname, len, &elem)) return CL_EARG;
665
+
666
+    hnode = elem->data;
667
+
668
+    struct onas_lnode *curr = hnode->childhead;
669
+
670
+    if (level == 0) {
671
+        if (!(prntname = onas_get_parent(pathname, len))) return CL_EARG;
672
+
673
+        prntlen = strlen(prntname);
674
+        if (onas_ht_rm_child(ht, prntname, prntlen, pathname, len)) return CL_EARG;
675
+
676
+        free(prntname);
677
+    }
678
+
679
+    while (curr->next != hnode->childtail) {
680
+        curr = curr->next;
681
+
682
+        size_t size      = len + strlen(curr->dirname) + 2;
683
+        char *child_path = (char *)cli_malloc(size);
684
+        if (child_path == NULL)
685
+            return CL_EMEM;
686
+        if (hnode->pathname[len - 1] == '/')
687
+            snprintf(child_path, size, "%s%s", hnode->pathname, curr->dirname);
688
+        else
689
+            snprintf(child_path, size, "%s/%s", hnode->pathname, curr->dirname);
690
+        onas_ht_rm_hierarchy(ht, child_path, size, level + 1);
691
+        free(child_path);
692
+    }
693
+
694
+    onas_ht_remove(ht, pathname, len, NULL);
695
+    onas_free_element(elem);
696
+
697
+    return CL_SUCCESS;
698
+}
699
+#endif
0 700
new file mode 100644
... ...
@@ -0,0 +1,109 @@
0
+/*
1
+ *  Copyright (C) 2015-2019 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
2
+ *
3
+ *  Authors: Mickey Sola
4
+ *
5
+ *  This program is free software; you can redistribute it and/or modify
6
+ *  it under the terms of the GNU General Public License version 2 as
7
+ *  published by the Free Software Foundation.
8
+ *
9
+ *  This program is distributed in the hope that it will be useful,
10
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
+ *  GNU General Public License for more details.
13
+ *
14
+ *  You should have received a copy of the GNU General Public License
15
+ *  along with this program; if not, write to the Free Software
16
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
17
+ *  MA 02110-1301, USA.
18
+ */
19
+
20
+#ifndef __ONAS_HASH_H
21
+#define __ONAS_HASH_H
22
+
23
+#define ONAS_FANWATCH 0x1
24
+#define ONAS_INWATCH 0x2
25
+#define ONAS_STOPWATCH 0x3
26
+
27
+#define ONAS_DEFAULT_HT_SIZE 1 << 18
28
+
29
+struct onas_element {
30
+
31
+    const char *key;
32
+    size_t klen;
33
+    struct onas_hnode *data;
34
+
35
+    struct onas_element *next;
36
+    struct onas_element *prev;
37
+};
38
+
39
+struct onas_bucket {
40
+
41
+    uint32_t size;
42
+
43
+    struct onas_element *head;
44
+    struct onas_element *tail;
45
+};
46
+
47
+struct onas_ht {
48
+
49
+    struct onas_bucket **htable;
50
+
51
+    /* Must be a sufficiently high power of two--will not grow. */
52
+    uint32_t size;
53
+    uint32_t nbckts;
54
+};
55
+
56
+/* Directory node struct for lists */
57
+struct onas_lnode {
58
+
59
+    /* List stuffs */
60
+    char *dirname;
61
+    struct onas_lnode *next;
62
+    struct onas_lnode *prev;
63
+};
64
+
65
+/* Directory node struct for hash tables */
66
+struct onas_hnode {
67
+
68
+    /* Path info */
69
+    int pathlen;
70
+    char *pathname;
71
+
72
+    /* Parent info */
73
+    int prnt_pathlen;
74
+    char *prnt_pathname;
75
+
76
+    /* Child head and tail are empty sentinels */
77
+    struct onas_lnode *childhead;
78
+    struct onas_lnode *childtail;
79
+
80
+    /* Inotify watch descriptor */
81
+    int wd;
82
+
83
+    /* Watched stuffs */
84
+    uint32_t watched;
85
+};
86
+
87
+void onas_free_ht(struct onas_ht *ht);
88
+int onas_ht_init(struct onas_ht **ht, uint32_t table_size);
89
+int onas_ht_insert(struct onas_ht *ht, struct onas_element *elem);
90
+int onas_ht_remove(struct onas_ht *ht, const char *key, size_t klen, struct onas_element **elem);
91
+int onas_ht_get(struct onas_ht *ht, const char *key, size_t klen, struct onas_element **elem);
92
+int onas_ht_rm_hierarchy(struct onas_ht *ht, const char *pathname, size_t len, int level);
93
+int onas_ht_add_hierarchy(struct onas_ht *ht, const char *pathname);
94
+int onas_ht_add_child(struct onas_ht *ht, const char *prntpath, size_t prntlen, const char *childpath, size_t childlen);
95
+int onas_ht_rm_child(struct onas_ht *ht, const char *prntpath, size_t prntlen, const char *childpath, size_t childlen);
96
+
97
+void onas_free_element(struct onas_element *elem);
98
+struct onas_element *onas_element_init(struct onas_hnode *value, const char *key, size_t klen);
99
+
100
+void onas_free_hashnode(struct onas_hnode *hnode);
101
+
102
+void onas_free_listnode(struct onas_lnode *lnode);
103
+int onas_add_listnode(struct onas_lnode *tail, struct onas_lnode *node);
104
+int onas_rm_listnode(struct onas_lnode *head, const char *dirname);
105
+
106
+void onas_free_dirlist(struct onas_lnode *head);
107
+
108
+#endif
0 109
new file mode 100644
... ...
@@ -0,0 +1,120 @@
0
+/*
1
+ *  Copyright (C) 2017-2019 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
2
+ *
3
+ *  Authors: Mickey Sola
4
+ *
5
+ *  This program is free software; you can redistribute it and/or modify
6
+ *  it under the terms of the GNU General Public License version 2 as
7
+ *  published by the Free Software Foundation.
8
+ *
9
+ *  This program is distributed in the hope that it will be useful,
10
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
+ *  GNU General Public License for more details.
13
+ *
14
+ *  You should have received a copy of the GNU General Public License
15
+ *  along with this program; if not, write to the Free Software
16
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
17
+ *  MA 02110-1301, USA.
18
+ */
19
+
20
+#if HAVE_CONFIG_H
21
+#include "clamav-config.h"
22
+#endif
23
+
24
+#if defined(FANOTIFY)
25
+
26
+#include <stdio.h>
27
+#include <stdarg.h>
28
+#include <stdlib.h>
29
+#include <string.h>
30
+//#include <fcntl.h>
31
+#include <sys/stat.h>
32
+#include <errno.h>
33
+#include <pthread.h>
34
+//#include <limits.h>
35
+#include "libclamav/clamav.h"
36
+//#include "libclamav/scanners.h"
37
+#include "shared/optparser.h"
38
+#include "shared/output.h"
39
+//#include "shared/misc.h"
40
+//#include "libclamav/others.h"
41
+
42
+//#include "others.h"
43
+
44
+#include "onaccess_others.h"
45
+#include "clamd/scanner.h"
46
+
47
+static pthread_mutex_t onas_scan_lock = PTHREAD_MUTEX_INITIALIZER;
48
+
49
+int onas_fan_checkowner(int pid, const struct optstruct *opts)
50
+{
51
+    char path[32];
52
+    STATBUF sb;
53
+    const struct optstruct *opt      = NULL;
54
+    const struct optstruct *opt_root = NULL;
55
+
56
+    /* always ignore ourselves */
57
+    if (pid == (int)getpid()) {
58
+        return CHK_SELF;
59
+    }
60
+
61
+    /* look up options */
62
+    opt      = optget(opts, "OnAccessExcludeUID");
63
+    opt_root = optget(opts, "OnAccessExcludeRootUID");
64
+
65
+    /* we can return immediately if no uid exclusions were requested */
66
+    if (!(opt->enabled || opt_root->enabled))
67
+        return CHK_CLEAN;
68
+
69
+    /* perform exclusion checks if we can stat OK */
70
+    snprintf(path, sizeof(path), "/proc/%u", pid);
71
+    if (CLAMSTAT(path, &sb) == 0) {
72
+        /* check all our non-root UIDs first */
73
+        if (opt->enabled) {
74
+            while (opt) {
75
+                if (opt->numarg == (long long)sb.st_uid)
76
+                    return CHK_FOUND;
77
+                opt = opt->nextarg;
78
+            }
79
+        }
80
+        /* finally check root UID */
81
+        if (opt_root->enabled) {
82
+            if (0 == (long long)sb.st_uid)
83
+                return CHK_FOUND;
84
+        }
85
+    } else if (errno == EACCES) {
86
+        logg("*Permission denied to stat /proc/%d to exclude UIDs... perhaps SELinux denial?\n", pid);
87
+    } else if (errno == ENOENT) {
88
+        /* FIXME: should this be configurable? */
89
+        logg("$/proc/%d vanished before UIDs could be excluded; scanning anyway\n", pid);
90
+    }
91
+
92
+    return CHK_CLEAN;
93
+}
94
+
95
+int onas_scan(const char *fname, int fd, const char **virname, const struct cl_engine *engine, struct cl_scan_options *options, int extinfo)
96
+{
97
+    int ret = 0;
98
+    struct cb_context context;
99
+
100
+    pthread_mutex_lock(&onas_scan_lock);
101
+
102
+    context.filename = fname;
103
+    context.virsize  = 0;
104
+    context.scandata = NULL;
105
+
106
+    /*ret = cl_scandesc_callback(fd, fname, virname, NULL, engine, options, &context);*/
107
+
108
+    if (ret) {
109
+        if (extinfo && context.virsize)
110
+            logg("ScanOnAccess: %s: %s(%s:%llu) FOUND\n", fname, *virname, context.virhash, context.virsize);
111
+        else
112
+            logg("ScanOnAccess: %s: %s FOUND\n", fname, *virname);
113
+    }
114
+
115
+    pthread_mutex_unlock(&onas_scan_lock);
116
+
117
+    return ret;
118
+}
119
+#endif
0 120
new file mode 100644
... ...
@@ -0,0 +1,36 @@
0
+/*
1
+ *  Copyright (C) 2017-2019 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
2
+ *
3
+ *  Authors: Mickey Sola
4
+ *
5
+ *  This program is free software; you can redistribute it and/or modify
6
+ *  it under the terms of the GNU General Public License version 2 as
7
+ *  published by the Free Software Foundation.
8
+ *
9
+ *  This program is distributed in the hope that it will be useful,
10
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
+ *  GNU General Public License for more details.
13
+ *
14
+ *  You should have received a copy of the GNU General Public License
15
+ *  along with this program; if not, write to the Free Software
16
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
17
+ *  MA 02110-1301, USA.
18
+ */
19
+
20
+#ifndef __CLAMD_ONAS_OTHERS_H
21
+#define __CLAMD_ONAS_OTHERS_H
22
+
23
+#include "shared/optparser.h"
24
+#include "libclamav/clamav.h"
25
+
26
+typedef enum {
27
+    CHK_CLEAN,
28
+    CHK_FOUND,
29
+    CHK_SELF
30
+} cli_check_t;
31
+
32
+int onas_fan_checkowner(int pid, const struct optstruct *opts);
33
+int onas_scan(const char *fname, int fd, const char **virname, const struct cl_engine *engine, struct cl_scan_options *options, int extinfo);
34
+
35
+#endif
0 36
deleted file mode 100644
... ...
@@ -1,322 +0,0 @@
1
-/*
2
- *  Copyright (C) 2015-2018 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
3
- *  Copyright (C) 2009 Sourcefire, Inc.
4
- *
5
- *  Authors: Tomasz Kojm, aCaB, Mickey Sola
6
- *
7
- *  This program is free software; you can redistribute it and/or modify
8
- *  it under the terms of the GNU General Public License version 2 as
9
- *  published by the Free Software Foundation.
10
- *
11
- *  This program is distributed in the hope that it will be useful,
12
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
- *  GNU General Public License for more details.
15
- *
16
- *  You should have received a copy of the GNU General Public License
17
- *  along with this program; if not, write to the Free Software
18
- *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19
- *  MA 02110-1301, USA.
20
- */
21
-
22
-#if HAVE_CONFIG_H
23
-#include "clamav-config.h"
24
-#endif
25
-
26
-#include <stdio.h>
27
-#include <stdlib.h>
28
-#ifdef	HAVE_UNISTD_H
29
-#include <unistd.h>
30
-#endif
31
-#include <string.h>
32
-#include <sys/types.h>
33
-#include <sys/stat.h>
34
-#ifdef HAVE_SYS_LIMITS_H
35
-#include <sys/limits.h>
36
-#endif
37
-#ifdef HAVE_SYS_SELECT_H
38
-#include <sys/select.h>
39
-#endif
40
-#include <sys/socket.h>
41
-#include <sys/un.h>
42
-#include <netinet/in.h>
43
-#include <arpa/inet.h>
44
-#include <netdb.h>
45
-#include <utime.h>
46
-#include <errno.h>
47
-#include <dirent.h>
48
-#include <fcntl.h>
49
-
50
-#ifdef HAVE_SYS_UIO_H
51
-#include <sys/uio.h>
52
-#endif
53
-
54
-#include "libclamav/clamav.h"
55
-#include "shared/optparser.h"
56
-#include "shared/output.h"
57
-#include "shared/misc.h"
58
-#include "shared/actions.h"
59
-#include "shared/clamdcom.h"
60
-
61
-#include "libclamav/str.h"
62
-#include "libclamav/others.h"
63
-
64
-#include "onaccess_client.h"
65
-#include "onaccess_proto.h"
66
-
67
-unsigned long int maxstream;
68
-struct sockaddr_un nixsock;
69
-extern struct optstruct *clamdopts;
70
-
71
-/* Inits the communication layer
72
- * Returns 0 if clamd is local, non zero if clamd is remote */
73
-static int isremote(const struct optstruct *opts) {
74
-    int s, ret;
75
-    const struct optstruct *opt;
76
-    char *ipaddr, port[10];
77
-    struct addrinfo hints, *info, *p;
78
-    int res;
79
-
80
-    UNUSEDPARAM(opts);
81
-
82
-#ifndef _WIN32
83
-    if((opt = optget(clamdopts, "LocalSocket"))->enabled) {
84
-        memset((void *)&nixsock, 0, sizeof(nixsock));
85
-        nixsock.sun_family = AF_UNIX;
86
-        strncpy(nixsock.sun_path, opt->strarg, sizeof(nixsock.sun_path));
87
-        nixsock.sun_path[sizeof(nixsock.sun_path)-1]='\0';
88
-        return 0;
89
-    }
90
-#endif
91
-    if(!(opt = optget(clamdopts, "TCPSocket"))->enabled)
92
-        return 0;
93
-
94
-    snprintf(port, sizeof(port), "%lld", optget(clamdopts, "TCPSocket")->numarg);
95
-
96
-    opt = optget(clamdopts, "TCPAddr");
97
-    while (opt) {
98
-        ipaddr = NULL;
99
-        if (opt->strarg)
100
-            ipaddr = (!strcmp(opt->strarg, "any") ? NULL : opt->strarg);
101
-
102
-        memset(&hints, 0x00, sizeof(struct addrinfo));
103
-        hints.ai_family = AF_UNSPEC;
104
-        hints.ai_socktype = SOCK_STREAM;
105
-        hints.ai_flags = AI_PASSIVE;
106
-
107
-        if ((res = getaddrinfo(ipaddr, port, &hints, &info))) {
108
-            logg("!Can't lookup clamd hostname: %s\n", gai_strerror(res));
109
-            opt = opt->nextarg;
110
-            continue;
111
-        }
112
-
113
-        for (p = info; p != NULL; p = p->ai_next) {
114
-            if((s = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) < 0) {
115
-                logg("isremote: socket() returning: %s.\n", strerror(errno));
116
-                continue;
117
-            }
118
-
119
-            switch (p->ai_family) {
120
-            case AF_INET:
121
-                ((struct sockaddr_in *)(p->ai_addr))->sin_port = htons(INADDR_ANY);
122
-                break;
123
-            case AF_INET6:
124
-                ((struct sockaddr_in6 *)(p->ai_addr))->sin6_port = htons(INADDR_ANY);
125
-                break;
126
-            default:
127
-                break;
128
-            }
129
-
130
-            ret = bind(s, p->ai_addr, p->ai_addrlen);
131
-            if (ret) {
132
-                if (errno == EADDRINUSE) {
133
-                    /* 
134
-                     * If we can't bind, then either we're attempting to listen on an IP that isn't
135
-                     * ours or that clamd is already listening on.
136
-                     */
137
-                    closesocket(s);
138
-                    freeaddrinfo(info);
139
-                    return 0;
140
-                }
141
-
142
-                closesocket(s);
143
-                freeaddrinfo(info);
144
-                return 1;
145
-            }
146
-
147
-            closesocket(s);
148
-        }
149
-
150
-        freeaddrinfo(info);
151
-
152
-        opt = opt->nextarg;
153
-    }
154
-
155
-    return 0;
156
-}
157
-
158
-
159
-/* Turns a relative path into an absolute one
160
- * Returns a pointer to the path (which must be 
161
- * freed by the caller) or NULL on error */
162
-static char *makeabs(const char *basepath) {
163
-    int namelen;
164
-    char *ret;
165
-
166
-    if(!(ret = malloc(PATH_MAX + 1))) {
167
-	logg("^Can't make room for fullpath.\n");
168
-	return NULL;
169
-    }
170
-    if(!cli_is_abspath(basepath)) {
171
-	if(!getcwd(ret, PATH_MAX)) {
172
-	    logg("^Can't get absolute pathname of current working directory.\n");
173
-	    free(ret);
174
-	    return NULL;
175
-	}
176
-	if(*basepath == '\\') {
177
-	    namelen = 2;
178
-	    basepath++;
179
-	} else
180
-	namelen = strlen(ret);
181
-	snprintf(&ret[namelen], PATH_MAX - namelen, PATHSEP"%s", basepath);
182
-    } else {
183
-	strncpy(ret, basepath, PATH_MAX);
184
-    }
185
-    ret[PATH_MAX] = '\0';
186
-    return ret;
187
-}
188
-
189
-/* Recursively scans a path with the given scantype
190
- * Returns non zero for serious errors, zero otherwise */
191
-static int client_scan(const char *file, int scantype, int *infected, int *err, int maxlevel, int session, int flags) {
192
-    int ret;
193
-    char *fullpath = makeabs(file);
194
-
195
-    if(!fullpath)
196
-	return 0;
197
-    if (!session)
198
-	ret = serial_client_scan(fullpath, scantype, infected, err, maxlevel, flags);
199
-    else
200
-	ret = parallel_client_scan(fullpath, scantype, infected, err, maxlevel, flags);
201
-    free(fullpath);
202
-    return ret;
203
-}
204
-
205
-int get_clamd_version(const struct optstruct *opts)
206
-{
207
-    char *buff;
208
-    int len, sockd;
209
-    struct RCVLN rcv;
210
-
211
-    isremote(opts);
212
-    if((sockd = dconnect()) < 0) return 2;
213
-    recvlninit(&rcv, sockd);
214
-
215
-    if(sendln(sockd, "zVERSION", 9)) {
216
-        closesocket(sockd);
217
-        return 2;
218
-    }
219
-
220
-    while((len = recvln(&rcv, &buff, NULL))) {
221
-        if(len == -1) {
222
-            logg("!Error occurred while receiving version information.\n");
223
-            break;
224
-        }
225
-        printf("%s\n", buff);
226
-    }
227
-
228
-    closesocket(sockd);
229
-    return 0;
230
-}
231
-
232
-int reload_clamd_database(const struct optstruct *opts)
233
-{
234
-    char *buff;
235
-    int len, sockd;
236
-    struct RCVLN rcv;
237
-
238
-    isremote(opts);
239
-    if((sockd = dconnect()) < 0) return 2;
240
-    recvlninit(&rcv, sockd);
241
-
242
-    if(sendln(sockd, "zRELOAD", 8)) {
243
-        closesocket(sockd);
244
-        return 2;
245
-    }
246
-
247
-    if(!(len = recvln(&rcv, &buff, NULL)) || len < 10 || memcmp(buff, "RELOADING", 9)) {
248
-        logg("!Clamd did not reload the database\n");
249
-        closesocket(sockd);
250
-        return 2;
251
-    }
252
-    closesocket(sockd);
253
-    return 0;
254
-}
255
-
256
-int client(const struct optstruct *opts, int *infected, int *err)
257
-{
258
-    int remote, scantype, session = 0, errors = 0, scandash = 0, maxrec, flags = 0;
259
-    const char *fname;
260
-
261
-    scandash = (opts->filename && opts->filename[0] && !strcmp(opts->filename[0], "-") && !optget(opts, "file-list")->enabled && !opts->filename[1]);
262
-    remote = isremote(opts) | optget(opts, "stream")->enabled;
263
-#ifdef HAVE_FD_PASSING
264
-    if(!remote && optget(clamdopts, "LocalSocket")->enabled && (optget(opts, "fdpass")->enabled || scandash)) {
265
-        scantype = FILDES;
266
-        session = optget(opts, "multiscan")->enabled;
267
-    } else 
268
-#endif
269
-        if(remote || scandash) {
270
-            scantype = STREAM;
271
-            session = optget(opts, "multiscan")->enabled;
272
-        } 
273
-        else if(optget(opts, "multiscan")->enabled) scantype = MULTI;
274
-        else if(optget(opts, "allmatch")->enabled) scantype = ALLMATCH;
275
-        else scantype = CONT;
276
-
277
-    maxrec = optget(clamdopts, "MaxDirectoryRecursion")->numarg;
278
-    maxstream = optget(clamdopts, "StreamMaxLength")->numarg;
279
-    if (optget(clamdopts, "FollowDirectorySymlinks")->enabled)
280
-        flags |= CLI_FTW_FOLLOW_DIR_SYMLINK;
281
-    if (optget(clamdopts, "FollowFileSymlinks")->enabled)
282
-        flags |= CLI_FTW_FOLLOW_FILE_SYMLINK;
283
-    flags |= CLI_FTW_TRIM_SLASHES;
284
-
285
-    *infected = 0;
286
-
287
-    if(scandash) {
288
-        int sockd, ret;
289
-        STATBUF sb;
290
-        if(FSTAT(0, &sb) < 0) {
291
-            logg("client.c: fstat failed for file name \"%s\", with %s\n.", 
292
-                    opts->filename[0], strerror(errno));
293
-            return 2;
294
-        }
295
-        if((sb.st_mode & S_IFMT) != S_IFREG) scantype = STREAM;
296
-        if((sockd = dconnect()) >= 0 && (ret = dsresult(sockd, scantype, NULL, &ret, NULL)) >= 0)
297
-            *infected = ret;
298
-        else
299
-            errors = 1;
300
-        if(sockd >= 0) closesocket(sockd);
301
-    } else if(opts->filename || optget(opts, "file-list")->enabled) {
302
-        if(opts->filename && optget(opts, "file-list")->enabled)
303
-            logg("^Only scanning files from --file-list (files passed at cmdline are ignored)\n");
304
-
305
-        while((fname = filelist(opts, NULL))) {
306
-            if(!strcmp(fname, "-")) {
307
-                logg("!Scanning from standard input requires \"-\" to be the only file argument\n");
308
-                continue;
309
-            }
310
-            errors += client_scan(fname, scantype, infected, err, maxrec, session, flags);
311
-            /* this may be too strict
312
-               if(errors >= 10) {
313
-               logg("!Too many errors\n");
314
-               break;
315
-               }
316
-               */
317
-        }
318
-    } else {
319
-        errors = client_scan("", scantype, infected, err, maxrec, session, flags);
320
-    }
321
-    return *infected ? 1 : (errors ? 2 : 0);
322
-}
323 1
deleted file mode 100644
... ...
@@ -1,40 +0,0 @@
1
-/*
2
- *  Copyright (C) 2015-2019 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
3
- *  Copyright (C) 2009 Sourcefire, Inc.
4
- *
5
- *  Authors: Tomasz Kojm, aCaB
6
- *
7
- *  This program is free software; you can redistribute it and/or modify
8
- *  it under the terms of the GNU General Public License version 2 as
9
- *  published by the Free Software Foundation.
10
- *
11
- *  This program is distributed in the hope that it will be useful,
12
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
- *  GNU General Public License for more details.
15
- *
16
- *  You should have received a copy of the GNU General Public License
17
- *  along with this program; if not, write to the Free Software
18
- *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19
- *  MA 02110-1301, USA.
20
- */
21
-
22
-#ifndef __ONAS_CLIENT_H
23
-#define __ONAS_CLIENT_H
24
-
25
-#include "shared/optparser.h"
26
-
27
-enum {
28
-    CONT,
29
-    MULTI,
30
-    STREAM,
31
-    FILDES,
32
-    ALLMATCH,
33
-    MAX_SCANTYPE = ALLMATCH
34
-};
35
-
36
-int client(const struct optstruct *opts, int *infected, int *err);
37
-int get_clamd_version(const struct optstruct *opts);
38
-int reload_clamd_database(const struct optstruct *opts);
39
-
40
-#endif
41 1
deleted file mode 100644
... ...
@@ -1,609 +0,0 @@
1
-/*
2
- *  Copyright (C) 2015-2019 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
3
- *
4
- *  Authors: Mickey Sola
5
- *
6
- *  This program is free software; you can redistribute it and/or modify
7
- *  it under the terms of the GNU General Public License version 2 as
8
- *  published by the Free Software Foundation.
9
- *
10
- *  This program is distributed in the hope that it will be useful,
11
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
- *  GNU General Public License for more details.
14
- *
15
- *  You should have received a copy of the GNU General Public License
16
- *  along with this program; if not, write to the Free Software
17
- *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
18
- *  MA 02110-1301, USA.
19
- */
20
-
21
-#if HAVE_CONFIG_H
22
-#include "clamav-config.h"
23
-#endif
24
-
25
-#if defined(FANOTIFY)
26
-
27
-#include <stdio.h>
28
-#include <stdlib.h>
29
-#include <unistd.h>
30
-#include <sys/types.h>
31
-#include <sys/stat.h>
32
-#include <fcntl.h>
33
-#include <signal.h>
34
-#include <pthread.h>
35
-#include <string.h>
36
-#include <errno.h>
37
-#include <stdbool.h>
38
-
39
-#include <sys/fanotify.h>
40
-#include <sys/inotify.h>
41
-
42
-#include "onaccess_fan.h"
43
-#include "onaccess_hash.h"
44
-#include "onaccess_ddd.h"
45
-#include "onaccess_scth.h"
46
-
47
-#include "libclamav/clamav.h"
48
-#include "libclamav/scanners.h"
49
-
50
-#include "shared/optparser.h"
51
-#include "shared/output.h"
52
-
53
-#include "clamd/server.h"
54
-#include "clamd/others.h"
55
-#include "clamd/scanner.h"
56
-
57
-static int onas_ddd_init_ht(uint32_t ht_size);
58
-static int onas_ddd_init_wdlt(uint64_t nwatches);
59
-static int onas_ddd_grow_wdlt();
60
-
61
-static int onas_ddd_watch(const char *pathname, int fan_fd, uint64_t fan_mask, int in_fd, uint64_t in_mask);
62
-static int onas_ddd_watch_hierarchy(const char *pathname, size_t len, int fd, uint64_t mask, uint32_t type);
63
-static int onas_ddd_unwatch(const char *pathname, int fan_fd, int in_fd);
64
-static int onas_ddd_unwatch_hierarchy(const char *pathname, size_t len, int fd, uint32_t type);
65
-
66
-static void onas_ddd_handle_in_moved_to(struct ddd_thrarg *tharg, const char *path, const char *child_path, const struct inotify_event *event, int wd, uint64_t in_mask);
67
-static void onas_ddd_handle_in_create(struct ddd_thrarg *tharg, const char *path, const char *child_path, const struct inotify_event *event, int wd, uint64_t in_mask);
68
-static void onas_ddd_handle_in_moved_from(struct ddd_thrarg *tharg, const char *path, const char *child_path, const struct inotify_event *event, int wd);
69
-static void onas_ddd_handle_in_delete(struct ddd_thrarg *tharg, const char *path, const char *child_path, const struct inotify_event *event, int wd);
70
-static void onas_ddd_handle_extra_scanning(struct ddd_thrarg *tharg, const char *pathname, int extra_options);
71
-
72
-static void onas_ddd_exit(int sig);
73
-
74
-/* TODO: Unglobalize these. */
75
-static struct onas_ht *ddd_ht;
76
-static char **wdlt;
77
-static uint32_t wdlt_len;
78
-static int onas_in_fd;
79
-
80
-static int onas_ddd_init_ht(uint32_t ht_size)
81
-{
82
-
83
-    if (ht_size <= 0)
84
-        ht_size = ONAS_DEFAULT_HT_SIZE;
85
-
86
-    return onas_ht_init(&ddd_ht, ht_size);
87
-}
88
-
89
-static int onas_ddd_init_wdlt(uint64_t nwatches)
90
-{
91
-
92
-    if (nwatches <= 0) return CL_EARG;
93
-
94
-    wdlt = (char **)cli_calloc(nwatches << 1, sizeof(char *));
95
-    if (!wdlt) return CL_EMEM;
96
-
97
-    wdlt_len = nwatches << 1;
98
-
99
-    return CL_SUCCESS;
100
-}
101
-
102
-static int onas_ddd_grow_wdlt()
103
-{
104
-
105
-    char **ptr = NULL;
106
-
107
-    ptr = (char **)cli_realloc(wdlt, wdlt_len << 1);
108
-    if (ptr) {
109
-        wdlt = ptr;
110
-        memset(&ptr[wdlt_len], 0, sizeof(char *) * (wdlt_len - 1));
111
-    } else {
112
-        return CL_EMEM;
113
-    }
114
-
115
-    wdlt_len <<= 1;
116
-
117
-    return CL_SUCCESS;
118
-}
119
-
120
-/* TODO: Support configuration for changing/setting number of inotify watches. */
121
-int onas_ddd_init(uint64_t nwatches, size_t ht_size)
122
-{
123
-
124
-    const char *nwatch_file = "/proc/sys/fs/inotify/max_user_watches";
125
-    int nwfd                = 0;
126
-    int ret                 = 0;
127
-    char nwatch_str[MAX_WATCH_LEN];
128
-    char *p  = NULL;
129
-    nwatches = 0;
130
-
131
-    nwfd = open(nwatch_file, O_RDONLY);
132
-    if (nwfd < 0) return CL_EOPEN;
133
-
134
-    ret = read(nwfd, nwatch_str, MAX_WATCH_LEN);
135
-    close(nwfd);
136
-    if (ret < 0) return CL_EREAD;
137
-
138
-    nwatches = strtol(nwatch_str, &p, 10);
139
-
140
-    ret = onas_ddd_init_wdlt(nwatches);
141
-    if (ret) return ret;
142
-
143
-    ret = onas_ddd_init_ht(ht_size);
144
-    if (ret) return ret;
145
-
146
-    return CL_SUCCESS;
147
-}
148
-
149
-static int onas_ddd_watch(const char *pathname, int fan_fd, uint64_t fan_mask, int in_fd, uint64_t in_mask)
150
-{
151
-    if (!pathname || fan_fd <= 0 || in_fd <= 0) return CL_ENULLARG;
152
-
153
-    int ret    = CL_SUCCESS;
154
-    size_t len = strlen(pathname);
155
-
156
-    ret = onas_ddd_watch_hierarchy(pathname, len, in_fd, in_mask, ONAS_IN);
157
-    if (ret) return ret;
158
-
159
-    ret = onas_ddd_watch_hierarchy(pathname, len, fan_fd, fan_mask, ONAS_FAN);
160
-    if (ret) return ret;
161
-
162
-    return CL_SUCCESS;
163
-}
164
-
165
-static int onas_ddd_watch_hierarchy(const char *pathname, size_t len, int fd, uint64_t mask, uint32_t type)
166
-{
167
-
168
-    if (!pathname || fd <= 0 || !type) return CL_ENULLARG;
169
-
170
-    if (type == (ONAS_IN | ONAS_FAN)) return CL_EARG;
171
-
172
-    struct onas_hnode *hnode  = NULL;
173
-    struct onas_element *elem = NULL;
174
-    int wd                    = 0;
175
-
176
-    if (onas_ht_get(ddd_ht, pathname, len, &elem) != CL_SUCCESS) return CL_EARG;
177
-
178
-    hnode = elem->data;
179
-
180
-    if (type & ONAS_IN) {
181
-        wd = inotify_add_watch(fd, pathname, (uint32_t)mask);
182
-
183
-        if (wd < 0) return CL_EARG;
184
-
185
-        if ((uint32_t)wd >= wdlt_len) {
186
-            onas_ddd_grow_wdlt();
187
-        }
188
-
189
-        /* Link the hash node to the watch descriptor lookup table */
190
-        hnode->wd = wd;
191
-        wdlt[wd]  = hnode->pathname;
192
-
193
-        hnode->watched |= ONAS_INWATCH;
194
-    } else if (type & ONAS_FAN) {
195
-        if (fanotify_mark(fd, FAN_MARK_ADD, mask, AT_FDCWD, hnode->pathname) < 0) return CL_EARG;
196
-        hnode->watched |= ONAS_FANWATCH;
197
-    } else {
198
-        return CL_EARG;
199
-    }
200
-
201
-    struct onas_lnode *curr = hnode->childhead;
202
-
203
-    while (curr->next != hnode->childtail) {
204
-        curr = curr->next;
205
-
206
-        size_t size      = len + strlen(curr->dirname) + 2;
207
-        char *child_path = (char *)cli_malloc(size);
208
-        if (child_path == NULL)
209
-            return CL_EMEM;
210
-        if (hnode->pathname[len - 1] == '/')
211
-            snprintf(child_path, --size, "%s%s", hnode->pathname, curr->dirname);
212
-        else
213
-            snprintf(child_path, size, "%s/%s", hnode->pathname, curr->dirname);
214
-
215
-        if (onas_ddd_watch_hierarchy(child_path, strlen(child_path), fd, mask, type)) {
216
-            return CL_EARG;
217
-        }
218
-        free(child_path);
219
-    }
220
-
221
-    return CL_SUCCESS;
222
-}
223
-
224
-static int onas_ddd_unwatch(const char *pathname, int fan_fd, int in_fd)
225
-{
226
-    if (!pathname || fan_fd <= 0 || in_fd <= 0) return CL_ENULLARG;
227
-
228
-    int ret    = CL_SUCCESS;
229
-    size_t len = strlen(pathname);
230
-
231
-    ret = onas_ddd_unwatch_hierarchy(pathname, len, in_fd, ONAS_IN);
232
-    if (ret) return ret;
233
-
234
-    ret = onas_ddd_unwatch_hierarchy(pathname, len, fan_fd, ONAS_FAN);
235
-    if (ret) return ret;
236
-
237
-    return CL_SUCCESS;
238
-}
239
-
240
-static int onas_ddd_unwatch_hierarchy(const char *pathname, size_t len, int fd, uint32_t type)
241
-{
242
-
243
-    if (!pathname || fd <= 0 || !type) return CL_ENULLARG;
244
-
245
-    if (type == (ONAS_IN | ONAS_FAN)) return CL_EARG;
246
-
247
-    struct onas_hnode *hnode  = NULL;
248
-    struct onas_element *elem = NULL;
249
-    int wd                    = 0;
250
-
251
-    if (onas_ht_get(ddd_ht, pathname, len, &elem)) return CL_EARG;
252
-
253
-    hnode = elem->data;
254
-
255
-    if (type & ONAS_IN) {
256
-        wd = hnode->wd;
257
-
258
-        if (!inotify_rm_watch(fd, wd)) return CL_EARG;
259
-
260
-        /* Unlink the hash node from the watch descriptor lookup table */
261
-        hnode->wd = 0;
262
-        wdlt[wd]  = NULL;
263
-
264
-        hnode->watched = ONAS_STOPWATCH;
265
-    } else if (type & ONAS_FAN) {
266
-        if (fanotify_mark(fd, FAN_MARK_REMOVE, 0, AT_FDCWD, hnode->pathname) < 0) return CL_EARG;
267
-        hnode->watched = ONAS_STOPWATCH;
268
-    } else {
269
-        return CL_EARG;
270
-    }
271
-
272
-    struct onas_lnode *curr = hnode->childhead;
273
-
274
-    while (curr->next != hnode->childtail) {
275
-        curr = curr->next;
276
-
277
-        size_t size      = len + strlen(curr->dirname) + 2;
278
-        char *child_path = (char *)cli_malloc(size);
279
-        if (child_path == NULL)
280
-            return CL_EMEM;
281
-        if (hnode->pathname[len - 1] == '/')
282
-            snprintf(child_path, --size, "%s%s", hnode->pathname, curr->dirname);
283
-        else
284
-            snprintf(child_path, size, "%s/%s", hnode->pathname, curr->dirname);
285
-
286
-        onas_ddd_unwatch_hierarchy(child_path, strlen(child_path), fd, type);
287
-        free(child_path);
288
-    }
289
-
290
-    return CL_SUCCESS;
291
-}
292
-
293
-void *onas_ddd_th(void *arg)
294
-{
295
-    struct ddd_thrarg *tharg = (struct ddd_thrarg *)arg;
296
-    sigset_t sigset;
297
-    struct sigaction act;
298
-    const struct optstruct *pt;
299
-    uint64_t in_mask = IN_ONLYDIR | IN_MOVE | IN_DELETE | IN_CREATE;
300
-    fd_set rfds;
301
-    char buf[4096];
302
-    ssize_t bread;
303
-    const struct inotify_event *event;
304
-    int ret, len;
305
-
306
-    /* ignore all signals except SIGUSR1 */
307
-    sigfillset(&sigset);
308
-    sigdelset(&sigset, SIGUSR1);
309
-    /* The behavior of a process is undefined after it ignores a
310
-	 * SIGFPE, SIGILL, SIGSEGV, or SIGBUS signal */
311
-    sigdelset(&sigset, SIGFPE);
312
-    sigdelset(&sigset, SIGILL);
313
-    sigdelset(&sigset, SIGSEGV);
314
-#ifdef SIGBUS
315
-    sigdelset(&sigset, SIGBUS);
316
-#endif
317
-    pthread_sigmask(SIG_SETMASK, &sigset, NULL);
318
-    memset(&act, 0, sizeof(struct sigaction));
319
-    act.sa_handler = onas_ddd_exit;
320
-    sigfillset(&(act.sa_mask));
321
-    sigaction(SIGUSR1, &act, NULL);
322
-    sigaction(SIGSEGV, &act, NULL);
323
-
324
-    onas_in_fd = inotify_init1(IN_NONBLOCK);
325
-    if (onas_in_fd == -1) {
326
-        logg("!ScanOnAccess: Could not init inotify.");
327
-        return NULL;
328
-    }
329
-
330
-    ret = onas_ddd_init(0, ONAS_DEFAULT_HT_SIZE);
331
-    if (ret) {
332
-        logg("!ScanOnAccess: Failed to initialize 3D. \n");
333
-        return NULL;
334
-    }
335
-
336
-    /* Add provided paths recursively. */
337
-    if ((pt = optget(tharg->opts, "OnAccessIncludePath"))->enabled) {
338
-        while (pt) {
339
-            if (!strcmp(pt->strarg, "/")) {
340
-                logg("!ScanOnAccess: Not including path '%s' while DDD is enabled\n", pt->strarg);
341
-                logg("!ScanOnAccess: Please use the OnAccessMountPath option to watch '%s'\n", pt->strarg);
342
-                pt = (struct optstruct *)pt->nextarg;
343
-                continue;
344
-            }
345
-            if (onas_ht_get(ddd_ht, pt->strarg, strlen(pt->strarg), NULL) != CL_SUCCESS) {
346
-                if (onas_ht_add_hierarchy(ddd_ht, pt->strarg)) {
347
-                    logg("!ScanOnAccess: Can't include path '%s'\n", pt->strarg);
348
-                    return NULL;
349
-                } else
350
-                    logg("ScanOnAccess: Protecting directory '%s' (and all sub-directories)\n", pt->strarg);
351
-            }
352
-
353
-            pt = (struct optstruct *)pt->nextarg;
354
-        }
355
-    } else {
356
-        logg("!ScanOnAccess: Please specify at least one path with OnAccessIncludePath\n");
357
-        return NULL;
358
-    }
359
-
360
-    /* Remove provided paths recursively. */
361
-    if ((pt = optget(tharg->opts, "OnAccessExcludePath"))->enabled) {
362
-        while (pt) {
363
-            size_t ptlen = strlen(pt->strarg);
364
-            if (onas_ht_get(ddd_ht, pt->strarg, ptlen, NULL) == CL_SUCCESS) {
365
-                if (onas_ht_rm_hierarchy(ddd_ht, pt->strarg, ptlen, 0)) {
366
-                    logg("!ScanOnAccess: Can't exclude path '%s'\n", pt->strarg);
367
-                    return NULL;
368
-                } else
369
-                    logg("ScanOnAccess: Excluding  directory '%s' (and all sub-directories)\n", pt->strarg);
370
-            }
371
-
372
-            pt = (struct optstruct *)pt->nextarg;
373
-        }
374
-    }
375
-
376
-    /* Watch provided paths recursively */
377
-    if ((pt = optget(tharg->opts, "OnAccessIncludePath"))->enabled) {
378
-        while (pt) {
379
-            size_t ptlen = strlen(pt->strarg);
380
-            if (onas_ht_get(ddd_ht, pt->strarg, ptlen, NULL) == CL_SUCCESS) {
381
-                if (onas_ddd_watch(pt->strarg, tharg->fan_fd, tharg->fan_mask, onas_in_fd, in_mask)) {
382
-                    logg("!ScanOnAccess: Could not watch path '%s', %s\n", pt->strarg, strerror(errno));
383
-                    if (errno == EINVAL && optget(tharg->opts, "OnAccessPrevention")->enabled) {
384
-                        logg("!ScanOnAccess: When using the OnAccessPrevention option, please ensure your kernel\n\t\t\twas compiled with CONFIG_FANOTIFY_ACCESS_PERMISSIONS set to Y\n");
385
-
386
-                        kill(getpid(), SIGTERM);
387
-                    }
388
-                    return NULL;
389
-                }
390
-            }
391
-            pt = (struct optstruct *)pt->nextarg;
392
-        }
393
-    }
394
-
395
-    /* TODO: Re-enable OnAccessExtraScanning once the thread resource consumption issue is resolved. */
396
-#if 0
397
-	if(optget(tharg->opts, "OnAccessExtraScanning")->enabled) {
398
-		logg("ScanOnAccess: Extra scanning and notifications enabled.\n");
399
-}
400
-#endif
401
-
402
-    FD_ZERO(&rfds);
403
-    FD_SET(onas_in_fd, &rfds);
404
-
405
-    while (1) {
406
-        do {
407
-            ret = select(onas_in_fd + 1, &rfds, NULL, NULL, NULL);
408
-        } while (ret == -1 && errno == EINTR);
409
-
410
-        while ((bread = read(onas_in_fd, buf, sizeof(buf))) > 0) {
411
-
412
-            /* Handle events. */
413
-            int wd;
414
-            char *p           = buf;
415
-            const char *path  = NULL;
416
-            const char *child = NULL;
417
-            for (; p < buf + bread; p += sizeof(struct inotify_event) + event->len) {
418
-
419
-                event = (const struct inotify_event *)p;
420
-                wd    = event->wd;
421
-                path  = wdlt[wd];
422
-                child = event->name;
423
-
424
-                len              = strlen(path);
425
-                size_t size      = strlen(child) + len + 2;
426
-                char *child_path = (char *)cli_malloc(size);
427
-                if (child_path == NULL)
428
-                    return NULL;
429
-
430
-                if (path[len - 1] == '/')
431
-                    snprintf(child_path, --size, "%s%s", path, child);
432
-                else
433
-                    snprintf(child_path, size, "%s/%s", path, child);
434
-
435
-                if (event->mask & IN_DELETE) {
436
-                    onas_ddd_handle_in_delete(tharg, path, child_path, event, wd);
437
-
438
-                } else if (event->mask & IN_MOVED_FROM) {
439
-                    onas_ddd_handle_in_moved_from(tharg, path, child_path, event, wd);
440
-
441
-                } else if (event->mask & IN_CREATE) {
442
-                    onas_ddd_handle_in_create(tharg, path, child_path, event, wd, in_mask);
443
-
444
-                } else if (event->mask & IN_MOVED_TO) {
445
-                    onas_ddd_handle_in_moved_to(tharg, path, child_path, event, wd, in_mask);
446
-                }
447
-            }
448
-        }
449
-    }
450
-
451
-    return NULL;
452
-}
453
-
454
-static void onas_ddd_handle_in_delete(struct ddd_thrarg *tharg,
455
-                                      const char *path, const char *child_path, const struct inotify_event *event, int wd)
456
-{
457
-
458
-    struct stat s;
459
-    if (stat(child_path, &s) == 0 && S_ISREG(s.st_mode)) return;
460
-    if (!(event->mask & IN_ISDIR)) return;
461
-
462
-    logg("*ddd: DELETE - Removing %s from %s with wd:%d\n", child_path, path, wd);
463
-    onas_ddd_unwatch(child_path, tharg->fan_fd, onas_in_fd);
464
-    onas_ht_rm_hierarchy(ddd_ht, child_path, strlen(child_path), 0);
465
-
466
-    return;
467
-}
468
-
469
-static void onas_ddd_handle_in_moved_from(struct ddd_thrarg *tharg,
470
-                                          const char *path, const char *child_path, const struct inotify_event *event, int wd)
471
-{
472
-
473
-    struct stat s;
474
-    if (stat(child_path, &s) == 0 && S_ISREG(s.st_mode)) return;
475
-    if (!(event->mask & IN_ISDIR)) return;
476
-
477
-    logg("*ddd: MOVED_FROM - Removing %s from %s with wd:%d\n", child_path, path, wd);
478
-    onas_ddd_unwatch(child_path, tharg->fan_fd, onas_in_fd);
479
-    onas_ht_rm_hierarchy(ddd_ht, child_path, strlen(child_path), 0);
480
-
481
-    return;
482
-}
483
-
484
-static void onas_ddd_handle_in_create(struct ddd_thrarg *tharg,
485
-                                      const char *path, const char *child_path, const struct inotify_event *event, int wd, uint64_t in_mask)
486
-{
487
-
488
-    struct stat s;
489
-
490
-    /* TODO: Re-enable OnAccessExtraScanning once the thread resource consumption issue is resolved. */
491
-#if 0
492
-	if (optget(tharg->opts, "OnAccessExtraScanning")->enabled) {
493
-		if(stat(child_path, &s) == 0 && S_ISREG(s.st_mode)) {
494
-			onas_ddd_handle_extra_scanning(tharg, child_path, ONAS_SCTH_ISFILE);
495
-
496
-		} else if(stat(child_path, &s) == 0 && S_ISDIR(s.st_mode)) {
497
-			logg("*ddd: CREATE - Adding %s to %s with wd:%d\n", child_path, path, wd);
498
-			onas_ht_add_hierarchy(ddd_ht, child_path);
499
-			onas_ddd_watch(child_path, tharg->fan_fd, tharg->fan_mask, onas_in_fd, in_mask);
500
-
501
-			onas_ddd_handle_extra_scanning(tharg, child_path, ONAS_SCTH_ISDIR);
502
-		}
503
-	}
504
-	else
505
-#endif
506
-    {
507
-        if (stat(child_path, &s) == 0 && S_ISREG(s.st_mode)) return;
508
-        if (!(event->mask & IN_ISDIR)) return;
509
-
510
-        logg("*ddd: MOVED_TO - Adding %s to %s with wd:%d\n", child_path, path, wd);
511
-        onas_ht_add_hierarchy(ddd_ht, child_path);
512
-        onas_ddd_watch(child_path, tharg->fan_fd, tharg->fan_mask, onas_in_fd, in_mask);
513
-    }
514
-
515
-    return;
516
-}
517
-
518
-static void onas_ddd_handle_in_moved_to(struct ddd_thrarg *tharg,
519
-                                        const char *path, const char *child_path, const struct inotify_event *event, int wd, uint64_t in_mask)
520
-{
521
-
522
-    struct stat s;
523
-    /* TODO: Re-enable OnAccessExtraScanning once the thread resource consumption issue is resolved. */
524
-#if 0
525
-	if (optget(tharg->opts, "OnAccessExtraScanning")->enabled) {
526
-		if(stat(child_path, &s) == 0 && S_ISREG(s.st_mode)) {
527
-			onas_ddd_handle_extra_scanning(tharg, child_path, ONAS_SCTH_ISFILE);
528
-
529
-		} else if(stat(child_path, &s) == 0 && S_ISDIR(s.st_mode)) {
530
-			logg("*ddd: MOVED_TO - Adding %s to %s with wd:%d\n", child_path, path, wd);
531
-			onas_ht_add_hierarchy(ddd_ht, child_path);
532
-			onas_ddd_watch(child_path, tharg->fan_fd, tharg->fan_mask, onas_in_fd, in_mask);
533
-
534
-			onas_ddd_handle_extra_scanning(tharg, child_path, ONAS_SCTH_ISDIR);
535
-		}
536
-	}
537
-	else
538
-#endif
539
-    {
540
-        if (stat(child_path, &s) == 0 && S_ISREG(s.st_mode)) return;
541
-        if (!(event->mask & IN_ISDIR)) return;
542
-
543
-        logg("*ddd: MOVED_TO - Adding %s to %s with wd:%d\n", child_path, path, wd);
544
-        onas_ht_add_hierarchy(ddd_ht, child_path);
545
-        onas_ddd_watch(child_path, tharg->fan_fd, tharg->fan_mask, onas_in_fd, in_mask);
546
-    }
547
-
548
-    return;
549
-}
550
-
551
-static void onas_ddd_handle_extra_scanning(struct ddd_thrarg *tharg, const char *pathname, int extra_options)
552
-{
553
-
554
-    int thread_started             = 1;
555
-    struct scth_thrarg *scth_tharg = NULL;
556
-    pthread_attr_t scth_attr;
557
-    pthread_t scth_pid = 0;
558
-
559
-    do {
560
-        if (pthread_attr_init(&scth_attr)) break;
561
-        pthread_attr_setdetachstate(&scth_attr, PTHREAD_CREATE_JOINABLE);
562
-
563
-        /* Allocate memory for arguments. Thread is responsible for freeing it. */
564
-        if (!(scth_tharg = (struct scth_thrarg *)calloc(sizeof(struct scth_thrarg), 1))) break;
565
-        if (!(scth_tharg->options = (struct cl_scan_options *)calloc(sizeof(struct cl_scan_options), 1))) break;
566
-
567
-        (void)memcpy(scth_tharg->options, tharg->options, sizeof(struct cl_scan_options));
568
-
569
-        scth_tharg->extra_options = extra_options;
570
-        scth_tharg->opts          = tharg->opts;
571
-        scth_tharg->pathname      = strdup(pathname);
572
-        scth_tharg->engine        = tharg->engine;
573
-
574
-        thread_started = pthread_create(&scth_pid, &scth_attr, onas_scan_th, scth_tharg);
575
-    } while (0);
576
-
577
-    if (0 != thread_started) {
578
-        /* Failed to create thread. Free anything we may have allocated. */
579
-        logg("!ScanOnAccess: Unable to kick off extra scanning.\n");
580
-        if (NULL != scth_tharg) {
581
-            if (NULL != scth_tharg->pathname) {
582
-                free(scth_tharg->pathname);
583
-                scth_tharg->pathname = NULL;
584
-            }
585
-            if (NULL != scth_tharg->options) {
586
-                free(scth_tharg->options);
587
-                scth_tharg->options = NULL;
588
-            }
589
-            free(scth_tharg);
590
-            scth_tharg = NULL;
591
-        }
592
-    }
593
-
594
-    return;
595
-}
596
-
597
-static void onas_ddd_exit(int sig)
598
-{
599
-    logg("*ScanOnAccess: onas_ddd_exit(), signal %d\n", sig);
600
-
601
-    close(onas_in_fd);
602
-
603
-    onas_free_ht(ddd_ht);
604
-    free(wdlt);
605
-
606
-    pthread_exit(NULL);
607
-    logg("ScanOnAccess: stopped\n");
608
-}
609
-#endif
610 1
deleted file mode 100644
... ...
@@ -1,47 +0,0 @@
1
-/*
2
- *  Copyright (C) 2015-2019 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
3
- *
4
- *  Authors: Mickey Sola
5
- *
6
- *  This program is free software; you can redistribute it and/or modify
7
- *  it under the terms of the GNU General Public License version 2 as
8
- *  published by the Free Software Foundation.
9
- *
10
- *  This program is distributed in the hope that it will be useful,
11
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
- *  GNU General Public License for more details.
14
- *
15
- *  You should have received a copy of the GNU General Public License
16
- *  along with this program; if not, write to the Free Software
17
- *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
18
- *  MA 02110-1301, USA.
19
- */
20
-
21
-#ifndef __ONAS_IN_H
22
-#define __ONAS_IN_H
23
-
24
-#include "shared/optparser.h"
25
-#include "libclamav/clamav.h"
26
-
27
-/*
28
- * Extra options for onas_scan_th(). 
29
- */
30
-#define ONAS_IN 0x01
31
-#define ONAS_FAN 0x02
32
-
33
-#define MAX_WATCH_LEN 7
34
-
35
-struct ddd_thrarg {
36
-    int sid;
37
-    struct cl_scan_options *options;
38
-    int fan_fd;
39
-    uint64_t fan_mask;
40
-    const struct optstruct *opts;
41
-    const struct cl_engine *engine;
42
-};
43
-
44
-int onas_ddd_init(uint64_t nwatches, size_t ht_size);
45
-void *onas_ddd_th(void *arg);
46
-
47
-#endif
48 1
deleted file mode 100644
... ...
@@ -1,306 +0,0 @@
1
-/*
2
- *  Copyright (C) 2013-2019 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
3
- *  Copyright (C) 2011-2013 Sourcefire, Inc.
4
- *
5
- *  Authors: Tomasz Kojm, Mickey Sola
6
- *
7
- *  This program is free software; you can redistribute it and/or modify
8
- *  it under the terms of the GNU General Public License version 2 as
9
- *  published by the Free Software Foundation.
10
- *
11
- *  This program is distributed in the hope that it will be useful,
12
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
- *  GNU General Public License for more details.
15
- *
16
- *  You should have received a copy of the GNU General Public License
17
- *  along with this program; if not, write to the Free Software
18
- *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19
- *  MA 02110-1301, USA.
20
- */
21
-
22
-#if HAVE_CONFIG_H
23
-#include "clamav-config.h"
24
-#endif
25
-
26
-#if defined(FANOTIFY)
27
-
28
-#include <stdio.h>
29
-#include <unistd.h>
30
-#include <sys/types.h>
31
-#include <sys/stat.h>
32
-#include <fcntl.h>
33
-#include <signal.h>
34
-#include <pthread.h>
35
-#include <string.h>
36
-#include <errno.h>
37
-#include <time.h>
38
-
39
-#include <sys/fanotify.h>
40
-
41
-#include "libclamav/clamav.h"
42
-#include "libclamav/scanners.h"
43
-
44
-#include "shared/optparser.h"
45
-#include "shared/output.h"
46
-
47
-#include "onaccess_others.h"
48
-#include "clamd/server.h"
49
-
50
-#include "onaccess_fan.h"
51
-#include "onaccess_hash.h"
52
-#include "onaccess_ddd.h"
53
-
54
-static pthread_t ddd_pid;
55
-static int onas_fan_fd;
56
-
57
-static void onas_fan_exit(int sig)
58
-{
59
-    logg("*ScanOnAccess: onas_fan_exit(), signal %d\n", sig);
60
-
61
-    close(onas_fan_fd);
62
-
63
-    if (ddd_pid > 0) {
64
-        pthread_kill(ddd_pid, SIGUSR1);
65
-        pthread_join(ddd_pid, NULL);
66
-    }
67
-
68
-    pthread_exit(NULL);
69
-    logg("ScanOnAccess: stopped\n");
70
-}
71
-
72
-static int onas_fan_scanfile(int fan_fd, const char *fname, struct fanotify_event_metadata *fmd, int scan, int extinfo, struct thrarg *tharg)
73
-{
74
-    struct fanotify_response res;
75
-    const char *virname = NULL;
76
-    int ret             = 0;
77
-
78
-    res.fd       = fmd->fd;
79
-    res.response = FAN_ALLOW;
80
-
81
-    if (scan) {
82
-        if (onas_scan(fname, fmd->fd, &virname, tharg->engine, tharg->options, extinfo) == CL_VIRUS) {
83
-            /* TODO : FIXME? virusaction forks. This could be extraordinarily problematic, lead to deadlocks,
84
-             * or at the very least lead to extreme memory consumption. Leaving disabled for now.*/
85
-            //virusaction(fname, virname, tharg->opts);
86
-            res.response = FAN_DENY;
87
-        }
88
-    }
89
-
90
-    if (fmd->mask & FAN_ALL_PERM_EVENTS) {
91
-        ret = write(fan_fd, &res, sizeof(res));
92
-        if (ret == -1)
93
-            logg("!ScanOnAccess: Internal error (can't write to fanotify)\n");
94
-    }
95
-
96
-    return ret;
97
-}
98
-
99
-void *onas_fan_th(void *arg)
100
-{
101
-    struct thrarg *tharg = (struct thrarg *)arg;
102
-    sigset_t sigset;
103
-    struct sigaction act;
104
-    const struct optstruct *pt;
105
-    short int scan;
106
-    unsigned int sizelimit = 0, extinfo;
107
-    STATBUF sb;
108
-    uint64_t fan_mask = FAN_EVENT_ON_CHILD | FAN_CLOSE;
109
-    fd_set rfds;
110
-    char buf[4096];
111
-    ssize_t bread;
112
-    struct fanotify_event_metadata *fmd;
113
-    char fname[1024];
114
-    int ret, len, check;
115
-    char err[128];
116
-
117
-    pthread_attr_t ddd_attr;
118
-    struct ddd_thrarg *ddd_tharg = NULL;
119
-
120
-    ddd_pid = 0;
121
-
122
-    /* ignore all signals except SIGUSR1 */
123
-    sigfillset(&sigset);
124
-    sigdelset(&sigset, SIGUSR1);
125
-    /* The behavior of a process is undefined after it ignores a
126
-     * SIGFPE, SIGILL, SIGSEGV, or SIGBUS signal */
127
-    sigdelset(&sigset, SIGFPE);
128
-    sigdelset(&sigset, SIGILL);
129
-    sigdelset(&sigset, SIGSEGV);
130
-#ifdef SIGBUS
131
-    sigdelset(&sigset, SIGBUS);
132
-#endif
133
-    pthread_sigmask(SIG_SETMASK, &sigset, NULL);
134
-    memset(&act, 0, sizeof(struct sigaction));
135
-    act.sa_handler = onas_fan_exit;
136
-    sigfillset(&(act.sa_mask));
137
-    sigaction(SIGUSR1, &act, NULL);
138
-    sigaction(SIGSEGV, &act, NULL);
139
-
140
-    /* Initialize fanotify */
141
-    onas_fan_fd = fanotify_init(FAN_CLASS_CONTENT | FAN_UNLIMITED_QUEUE | FAN_UNLIMITED_MARKS, O_LARGEFILE | O_RDONLY);
142
-    if (onas_fan_fd < 0) {
143
-        logg("!ScanOnAccess: fanotify_init failed: %s\n", cli_strerror(errno, err, sizeof(err)));
144
-        if (errno == EPERM)
145
-            logg("ScanOnAccess: clamd must be started by root\n");
146
-        return NULL;
147
-    }
148
-
149
-    if (!tharg) {
150
-        logg("!Unable to start on-access scanner. Bad thread args.\n");
151
-        return NULL;
152
-    }
153
-
154
-    if (optget(tharg->opts, "OnAccessPrevention")->enabled && !optget(tharg->opts, "OnAccessMountPath")->enabled) {
155
-        logg("ScanOnAccess: preventing access attempts on malicious files.\n");
156
-        fan_mask |= FAN_ACCESS_PERM | FAN_OPEN_PERM;
157
-    } else {
158
-        logg("ScanOnAccess: notifying only for access attempts.\n");
159
-        fan_mask |= FAN_ACCESS | FAN_OPEN;
160
-    }
161
-
162
-    if ((pt = optget(tharg->opts, "OnAccessMountPath"))->enabled) {
163
-        while (pt) {
164
-            if (fanotify_mark(onas_fan_fd, FAN_MARK_ADD | FAN_MARK_MOUNT, fan_mask, onas_fan_fd, pt->strarg) != 0) {
165
-                logg("!ScanOnAccess: Can't include mountpoint '%s'\n", pt->strarg);
166
-                return NULL;
167
-            } else
168
-                logg("ScanOnAccess: Protecting '%s' and rest of mount.\n", pt->strarg);
169
-            pt = (struct optstruct *)pt->nextarg;
170
-        }
171
-
172
-    } else if (!optget(tharg->opts, "OnAccessDisableDDD")->enabled) {
173
-        int thread_started = 1;
174
-        do {
175
-            if (pthread_attr_init(&ddd_attr)) break;
176
-            pthread_attr_setdetachstate(&ddd_attr, PTHREAD_CREATE_JOINABLE);
177
-
178
-            /* Allocate memory for arguments. Thread is responsible for freeing it. */
179
-            if (!(ddd_tharg = (struct ddd_thrarg *)calloc(sizeof(struct ddd_thrarg), 1))) break;
180
-            if (!(ddd_tharg->options = (struct cl_scan_options *)calloc(sizeof(struct cl_scan_options), 1))) break;
181
-
182
-            (void)memcpy(ddd_tharg->options, tharg->options, sizeof(struct cl_scan_options));
183
-            ddd_tharg->fan_fd   = onas_fan_fd;
184
-            ddd_tharg->fan_mask = fan_mask;
185
-            ddd_tharg->opts     = tharg->opts;
186
-            ddd_tharg->engine   = tharg->engine;
187
-
188
-            thread_started = pthread_create(&ddd_pid, &ddd_attr, onas_ddd_th, ddd_tharg);
189
-        } while (0);
190
-
191
-        if (0 != thread_started) {
192
-            /* Failed to create thread. Free anything we may have allocated. */
193
-            logg("!Unable to start dynamic directory determination.\n");
194
-            if (NULL != ddd_tharg) {
195
-                if (NULL != ddd_tharg->options) {
196
-                    free(ddd_tharg->options);
197
-                    ddd_tharg->options = NULL;
198
-                }
199
-                free(ddd_tharg);
200
-                ddd_tharg = NULL;
201
-            }
202
-        }
203
-
204
-    } else {
205
-        if ((pt = optget(tharg->opts, "OnAccessIncludePath"))->enabled) {
206
-            while (pt) {
207
-                if (fanotify_mark(onas_fan_fd, FAN_MARK_ADD, fan_mask, onas_fan_fd, pt->strarg) != 0) {
208
-                    logg("!ScanOnAccess: Can't include path '%s'\n", pt->strarg);
209
-                    return NULL;
210
-                } else
211
-                    logg("ScanOnAccess: Protecting directory '%s'\n", pt->strarg);
212
-                pt = (struct optstruct *)pt->nextarg;
213
-            }
214
-        } else {
215
-            logg("!ScanOnAccess: Please specify at least one path with OnAccessIncludePath\n");
216
-            return NULL;
217
-        }
218
-    }
219
-
220
-    /* Load other options. */
221
-    sizelimit = optget(tharg->opts, "OnAccessMaxFileSize")->numarg;
222
-    if (sizelimit)
223
-        logg("ScanOnAccess: Max file size limited to %u bytes\n", sizelimit);
224
-    else
225
-        logg("ScanOnAccess: File size limit disabled\n");
226
-
227
-    extinfo = optget(tharg->opts, "ExtendedDetectionInfo")->enabled;
228
-
229
-    FD_ZERO(&rfds);
230
-    FD_SET(onas_fan_fd, &rfds);
231
-    do {
232
-        if (reload) sleep(1);
233
-        ret = select(onas_fan_fd + 1, &rfds, NULL, NULL, NULL);
234
-    } while ((ret == -1 && errno == EINTR) || reload);
235
-
236
-    time_t start = time(NULL) - 30;
237
-    while (((bread = read(onas_fan_fd, buf, sizeof(buf))) > 0) || errno == EOVERFLOW) {
238
-
239
-        if (errno == EOVERFLOW) {
240
-            if (time(NULL) - start >= 30) {
241
-                logg("!ScanOnAccess: Internal error (failed to read data) ... %s\n", strerror(errno));
242
-                logg("!ScanOnAccess: File too large for fanotify ... recovering and continuing scans...\n");
243
-                start = time(NULL);
244
-            }
245
-
246
-            errno = 0;
247
-            continue;
248
-        }
249
-
250
-        fmd = (struct fanotify_event_metadata *)buf;
251
-        while (FAN_EVENT_OK(fmd, bread)) {
252
-            scan = 1;
253
-            if (fmd->fd >= 0) {
254
-                sprintf(fname, "/proc/self/fd/%d", fmd->fd);
255
-                len = readlink(fname, fname, sizeof(fname) - 1);
256
-                if (len == -1) {
257
-                    close(fmd->fd);
258
-                    logg("!ScanOnAccess: Internal error (readlink() failed)\n");
259
-                    return NULL;
260
-                }
261
-                fname[len] = 0;
262
-
263
-                if ((check = onas_fan_checkowner(fmd->pid, tharg->opts))) {
264
-                    scan = 0;
265
-/* TODO: Re-enable OnAccessExtraScanning once the thread resource consumption issue is resolved. */
266
-#if 0
267
-			if ((check != CHK_SELF) || !(optget(tharg->opts, "OnAccessExtraScanning")->enabled)) {
268
-#else
269
-                    if (check != CHK_SELF) {
270
-#endif
271
-                    logg("*ScanOnAccess: %s skipped (excluded UID)\n", fname);
272
-                }
273
-            }
274
-
275
-            if (sizelimit) {
276
-                if (FSTAT(fmd->fd, &sb) != 0 || sb.st_size > sizelimit) {
277
-                    scan = 0;
278
-                    /* logg("*ScanOnAccess: %s skipped (size > %d)\n", fname, sizelimit); */
279
-                }
280
-            }
281
-
282
-            if (onas_fan_scanfile(onas_fan_fd, fname, fmd, scan, extinfo, tharg) == -1) {
283
-                close(fmd->fd);
284
-                return NULL;
285
-            }
286
-
287
-            if (close(fmd->fd) == -1) {
288
-                printf("!ScanOnAccess: Internal error (close(%d) failed)\n", fmd->fd);
289
-                close(fmd->fd);
290
-                return NULL;
291
-            }
292
-        }
293
-        fmd = FAN_EVENT_NEXT(fmd, bread);
294
-    }
295
-    do {
296
-        if (reload) sleep(1);
297
-        ret = select(onas_fan_fd + 1, &rfds, NULL, NULL, NULL);
298
-    } while ((ret == -1 && errno == EINTR) || reload);
299
-}
300
-
301
-if (bread < 0)
302
-    logg("!ScanOnAccess: Internal error (failed to read data) ... %s\n", strerror(errno));
303
-
304
-return NULL;
305
-}
306
-#endif
307 1
deleted file mode 100644
... ...
@@ -1,27 +0,0 @@
1
-/*
2
- *  Copyright (C) 2013-2019 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
3
- *  Copyright (C) 2011-2013 Sourcefire, Inc.
4
- *
5
- *  Authors: Tomasz Kojm
6
- *
7
- *  This program is free software; you can redistribute it and/or modify
8
- *  it under the terms of the GNU General Public License version 2 as
9
- *  published by the Free Software Foundation.
10
- *
11
- *  This program is distributed in the hope that it will be useful,
12
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
- *  GNU General Public License for more details.
15
- *
16
- *  You should have received a copy of the GNU General Public License
17
- *  along with this program; if not, write to the Free Software
18
- *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19
- *  MA 02110-1301, USA.
20
- */
21
-
22
-#ifndef __FAN_H
23
-#define __FAN_H
24
-
25
-void *onas_fan_th(void *arg);
26
-
27
-#endif
28 1
deleted file mode 100644
... ...
@@ -1,700 +0,0 @@
1
-/*
2
- *  Copyright (C) 2015-2019 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
3
- *
4
- *  Authors: Mickey Sola
5
- *
6
- *  This program is free software; you can redistribute it and/or modify
7
- *  it under the terms of the GNU General Public License version 2 as
8
- *  published by the Free Software Foundation.
9
- *
10
- *  This program is distributed in the hope that it will be useful,
11
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
- *  GNU General Public License for more details.
14
- *
15
- *  You should have received a copy of the GNU General Public License
16
- *  along with this program; if not, write to the Free Software
17
- *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
18
- *  MA 02110-1301, USA.
19
- */
20
-
21
-#if HAVE_CONFIG_H
22
-#include "clamav-config.h"
23
-#endif
24
-
25
-#if defined(FANOTIFY)
26
-#include <stdio.h>
27
-#include <unistd.h>
28
-#include <sys/types.h>
29
-#include <sys/stat.h>
30
-#include <fcntl.h>
31
-#include <signal.h>
32
-#include <pthread.h>
33
-#include <string.h>
34
-#include <errno.h>
35
-#include <stdbool.h>
36
-
37
-#include <sys/fanotify.h>
38
-
39
-#include "onaccess_fan.h"
40
-#include "onaccess_hash.h"
41
-#include "onaccess_ddd.h"
42
-
43
-#include "libclamav/clamav.h"
44
-#include "libclamav/scanners.h"
45
-#include "libclamav/str.h"
46
-
47
-#include "shared/optparser.h"
48
-#include "shared/output.h"
49
-
50
-#include "clamd/server.h"
51
-#include "clamd/others.h"
52
-#include "clamd/scanner.h"
53
-#include "clamd/priv_fts.h"
54
-
55
-static struct onas_bucket *onas_bucket_init();
56
-static void onas_free_bucket(struct onas_bucket *bckt);
57
-static int onas_bucket_insert(struct onas_bucket *bckt, struct onas_element *elem);
58
-static int onas_bucket_remove(struct onas_bucket *bckt, struct onas_element *elem);
59
-
60
-static int onas_add_hashnode_child(struct onas_hnode *node, const char *dirname);
61
-
62
-static struct onas_lnode *onas_listnode_init(void);
63
-
64
-static struct onas_hnode *onas_hashnode_init(void);
65
-
66
-static inline uint32_t onas_hshift(uint32_t hash)
67
-{
68
-
69
-    hash = ~hash;
70
-
71
-    hash += (hash << 15);
72
-    hash ^= (hash >> 12);
73
-    hash += (hash << 2);
74
-    hash ^= (hash >> 4);
75
-    hash += (hash << 3);
76
-    hash += (hash << 11);
77
-    hash ^= (hash >> 16);
78
-
79
-    return hash;
80
-}
81
-
82
-static inline int onas_hash(const char *key, size_t keylen, uint32_t size)
83
-{
84
-
85
-    uint32_t hash = 1;
86
-    uint32_t i;
87
-
88
-    for (i = 0; i < keylen; i++) {
89
-        hash += key[i];
90
-        hash = onas_hshift(hash);
91
-    }
92
-
93
-    return hash & (size - 1);
94
-}
95
-
96
-int onas_ht_init(struct onas_ht **ht, uint32_t size)
97
-{
98
-
99
-    if (size == 0 || (size & (~size + 1)) != size) return CL_EARG;
100
-
101
-    *ht = (struct onas_ht *)cli_malloc(sizeof(struct onas_ht));
102
-    if (!(*ht)) return CL_EMEM;
103
-
104
-    **ht = (struct onas_ht){
105
-        .htable = NULL,
106
-        .size   = size,
107
-        .nbckts = 0,
108
-    };
109
-
110
-    if (!((*ht)->htable = (struct onas_bucket **)cli_calloc(size, sizeof(struct onas_bucket *)))) {
111
-        onas_free_ht(*ht);
112
-        return CL_EMEM;
113
-    }
114
-
115
-    return CL_SUCCESS;
116
-}
117
-
118
-void onas_free_ht(struct onas_ht *ht)
119
-{
120
-
121
-    if (!ht || ht->size == 0) return;
122
-
123
-    if (!ht->htable) {
124
-        free(ht);
125
-        return;
126
-    }
127
-
128
-    uint32_t i = 0;
129
-    for (i = 0; i < ht->size; i++) {
130
-        onas_free_bucket(ht->htable[i]);
131
-        ht->htable[i] = NULL;
132
-    }
133
-
134
-    free(ht->htable);
135
-    ht->htable = NULL;
136
-
137
-    free(ht);
138
-
139
-    return;
140
-}
141
-
142
-static struct onas_bucket *onas_bucket_init()
143
-{
144
-
145
-    struct onas_bucket *bckt = (struct onas_bucket *)cli_malloc(sizeof(struct onas_bucket));
146
-    if (!bckt) return NULL;
147
-
148
-    *bckt = (struct onas_bucket){
149
-        .size = 0,
150
-        .head = NULL,
151
-        .tail = NULL};
152
-
153
-    return bckt;
154
-}
155
-
156
-static void onas_free_bucket(struct onas_bucket *bckt)
157
-{
158
-
159
-    if (!bckt) return;
160
-
161
-    uint32_t i                = 0;
162
-    struct onas_element *curr = NULL;
163
-
164
-    for (i = 0; i < bckt->size; i++) {
165
-        curr       = bckt->head;
166
-        bckt->head = curr->next;
167
-        onas_free_element(curr);
168
-        curr = NULL;
169
-    }
170
-
171
-    free(bckt);
172
-
173
-    return;
174
-}
175
-
176
-struct onas_element *onas_element_init(struct onas_hnode *value, const char *key, size_t klen)
177
-{
178
-
179
-    struct onas_element *elem = (struct onas_element *)cli_malloc(sizeof(struct onas_element));
180
-    if (!elem) return NULL;
181
-
182
-    *elem = (struct onas_element){
183
-        .key  = key,
184
-        .klen = klen,
185
-        .data = value,
186
-        .next = NULL,
187
-        .prev = NULL};
188
-
189
-    return elem;
190
-}
191
-
192
-void onas_free_element(struct onas_element *elem)
193
-{
194
-
195
-    if (!elem) return;
196
-
197
-    onas_free_hashnode(elem->data);
198
-
199
-    elem->prev = NULL;
200
-    elem->next = NULL;
201
-
202
-    free(elem);
203
-
204
-    return;
205
-}
206
-
207
-int onas_ht_insert(struct onas_ht *ht, struct onas_element *elem)
208
-{
209
-
210
-    if (!ht || !elem || !elem->key) return CL_ENULLARG;
211
-
212
-    int idx                  = onas_hash(elem->key, elem->klen, ht->size);
213
-    struct onas_bucket *bckt = ht->htable[idx];
214
-
215
-    int ret        = 0;
216
-    uint32_t bsize = 0;
217
-
218
-    if (bckt == NULL) {
219
-        ht->htable[idx] = onas_bucket_init();
220
-        bckt            = ht->htable[idx];
221
-    }
222
-
223
-    bsize = bckt->size;
224
-    ret   = onas_bucket_insert(bckt, elem);
225
-
226
-    if (ret == CL_SUCCESS)
227
-        if (bsize < bckt->size)
228
-            ht->nbckts++;
229
-
230
-    return ret;
231
-}
232
-
233
-static int onas_bucket_insert(struct onas_bucket *bckt, struct onas_element *elem)
234
-{
235
-    if (!bckt || !elem) return CL_ENULLARG;
236
-
237
-    if (bckt->size == 0) {
238
-        bckt->head = elem;
239
-        bckt->tail = elem;
240
-        elem->prev = NULL;
241
-        elem->next = NULL;
242
-        bckt->size++;
243
-    } else {
244
-        struct onas_element *btail = bckt->tail;
245
-
246
-        btail->next = elem;
247
-        elem->prev  = btail;
248
-        elem->next  = NULL;
249
-        bckt->tail  = elem;
250
-        bckt->size++;
251
-    }
252
-
253
-    return CL_SUCCESS;
254
-}
255
-
256
-/* Checks if key exists and optionally stores address to the element corresponding to the key within elem */
257
-int onas_ht_get(struct onas_ht *ht, const char *key, size_t klen, struct onas_element **elem)
258
-{
259
-
260
-    if (elem) *elem = NULL;
261
-
262
-    if (!ht || !key || klen <= 0) return CL_ENULLARG;
263
-
264
-    struct onas_bucket *bckt = ht->htable[onas_hash(key, klen, ht->size)];
265
-
266
-    if (!bckt || bckt->size == 0) return CL_EARG;
267
-
268
-    struct onas_element *curr = bckt->head;
269
-
270
-    while (curr && strcmp(curr->key, key)) {
271
-        curr = curr->next;
272
-    }
273
-
274
-    if (!curr) return CL_EARG;
275
-
276
-    if (elem) *elem = curr;
277
-
278
-    return CL_SUCCESS;
279
-}
280
-
281
-/* Removes the element corresponding to key from the hashtable and optionally returns a pointer to the removed element. */
282
-int onas_ht_remove(struct onas_ht *ht, const char *key, size_t klen, struct onas_element **relem)
283
-{
284
-    if (!ht || !key || klen <= 0) return CL_ENULLARG;
285
-
286
-    struct onas_bucket *bckt = ht->htable[onas_hash(key, klen, ht->size)];
287
-
288
-    if (!bckt) return CL_EARG;
289
-
290
-    struct onas_element *elem = NULL;
291
-    onas_ht_get(ht, key, klen, &elem);
292
-
293
-    if (!elem) return CL_EARG;
294
-
295
-    int ret = onas_bucket_remove(bckt, elem);
296
-
297
-    if (relem) *relem = elem;
298
-
299
-    return ret;
300
-}
301
-
302
-static int onas_bucket_remove(struct onas_bucket *bckt, struct onas_element *elem)
303
-{
304
-    if (!bckt || !elem) return CL_ENULLARG;
305
-
306
-    struct onas_element *curr = bckt->head;
307
-
308
-    while (curr && curr != elem) {
309
-        curr = curr->next;
310
-    }
311
-
312
-    if (!curr) return CL_EARG;
313
-
314
-    if (bckt->head == elem) {
315
-        bckt->head = elem->next;
316
-        if (bckt->head) bckt->head->prev = NULL;
317
-
318
-        elem->next = NULL;
319
-    } else if (bckt->tail == elem) {
320
-        bckt->tail = elem->prev;
321
-        if (bckt->tail) bckt->tail->next = NULL;
322
-
323
-        elem->prev = NULL;
324
-    } else {
325
-        struct onas_element *tmp = NULL;
326
-
327
-        tmp = elem->prev;
328
-        if (tmp) {
329
-            tmp->next = elem->next;
330
-            tmp       = elem->next;
331
-            tmp->prev = elem->prev;
332
-        }
333
-
334
-        elem->prev = NULL;
335
-        elem->next = NULL;
336
-    }
337
-
338
-    bckt->size--;
339
-
340
-    return CL_SUCCESS;
341
-}
342
-
343
-/* Dealing with hash nodes and list nodes */
344
-
345
-/* Function to initialize hashnode. */
346
-static struct onas_hnode *onas_hashnode_init(void)
347
-{
348
-    struct onas_hnode *hnode = NULL;
349
-    if (!(hnode = (struct onas_hnode *)cli_malloc(sizeof(struct onas_hnode)))) {
350
-        return NULL;
351
-    }
352
-
353
-    *hnode = (struct onas_hnode){
354
-        .pathlen       = 0,
355
-        .pathname      = NULL,
356
-        .prnt_pathlen  = 0,
357
-        .prnt_pathname = NULL,
358
-        .childhead     = NULL,
359
-        .childtail     = NULL,
360
-        .wd            = 0,
361
-        .watched       = 0};
362
-
363
-    if (!(hnode->childhead = (struct onas_lnode *)onas_listnode_init())) {
364
-        onas_free_hashnode(hnode);
365
-        return NULL;
366
-    }
367
-
368
-    if (!(hnode->childtail = (struct onas_lnode *)onas_listnode_init())) {
369
-        onas_free_hashnode(hnode);
370
-        return NULL;
371
-    }
372
-
373
-    hnode->childhead->next = (struct onas_lnode *)hnode->childtail;
374
-    hnode->childtail->prev = (struct onas_lnode *)hnode->childhead;
375
-
376
-    return hnode;
377
-}
378
-
379
-/* Function to initialize listnode. */
380
-static struct onas_lnode *onas_listnode_init(void)
381
-{
382
-    struct onas_lnode *lnode = NULL;
383
-    if (!(lnode = (struct onas_lnode *)cli_malloc(sizeof(struct onas_lnode)))) {
384
-        return NULL;
385
-    }
386
-
387
-    *lnode = (struct onas_lnode){
388
-        .dirname = NULL,
389
-        .next    = NULL,
390
-        .prev    = NULL};
391
-
392
-    return lnode;
393
-}
394
-
395
-/* Function to free hashnode. */
396
-void onas_free_hashnode(struct onas_hnode *hnode)
397
-{
398
-    if (!hnode) return;
399
-
400
-    onas_free_dirlist(hnode->childhead);
401
-    hnode->childhead = NULL;
402
-
403
-    free(hnode->pathname);
404
-    hnode->pathname = NULL;
405
-
406
-    free(hnode->prnt_pathname);
407
-    hnode->prnt_pathname = NULL;
408
-
409
-    free(hnode);
410
-
411
-    return;
412
-}
413
-
414
-/* Function to free list of listnodes. */
415
-void onas_free_dirlist(struct onas_lnode *head)
416
-{
417
-    if (!head) return;
418
-    struct onas_lnode *curr = head;
419
-    struct onas_lnode *tmp  = curr;
420
-
421
-    while (curr) {
422
-        tmp = curr->next;
423
-        onas_free_listnode(curr);
424
-        curr = tmp;
425
-    }
426
-
427
-    return;
428
-}
429
-
430
-/* Function to free a listnode. */
431
-void onas_free_listnode(struct onas_lnode *lnode)
432
-{
433
-    if (!lnode) return;
434
-
435
-    lnode->next = NULL;
436
-    lnode->prev = NULL;
437
-
438
-    free(lnode->dirname);
439
-    lnode->dirname = NULL;
440
-
441
-    free(lnode);
442
-
443
-    return;
444
-}
445
-
446
-static int onas_add_hashnode_child(struct onas_hnode *node, const char *dirname)
447
-{
448
-    if (!node || !dirname) return CL_ENULLARG;
449
-
450
-    struct onas_lnode *child = onas_listnode_init();
451
-    if (!child) return CL_EMEM;
452
-
453
-    size_t n       = strlen(dirname);
454
-    child->dirname = cli_strndup(dirname, n);
455
-
456
-    onas_add_listnode(node->childtail, child);
457
-
458
-    return CL_SUCCESS;
459
-}
460
-
461
-/* Function to add a dir_listnode to a list */
462
-int onas_add_listnode(struct onas_lnode *tail, struct onas_lnode *node)
463
-{
464
-    if (!tail || !node) return CL_ENULLARG;
465
-
466
-    struct onas_lnode *tmp = tail->prev;
467
-
468
-    tmp->next  = node;
469
-    node->prev = tail->prev;
470
-
471
-    node->next = tail;
472
-    tail->prev = node;
473
-
474
-    return CL_SUCCESS;
475
-}
476
-
477
-/* Function to remove a listnode based on dirname. */
478
-int onas_rm_listnode(struct onas_lnode *head, const char *dirname)
479
-{
480
-    if (!dirname || !head) return CL_ENULLARG;
481
-
482
-    struct onas_lnode *curr = head;
483
-    size_t n                = strlen(dirname);
484
-
485
-    while ((curr = curr->next)) {
486
-        if (!strncmp(curr->dirname, dirname, n)) {
487
-            struct onas_lnode *tmp = curr->prev;
488
-            tmp->next              = curr->next;
489
-            tmp                    = curr->next;
490
-            tmp->prev              = curr->prev;
491
-
492
-            onas_free_listnode(curr);
493
-
494
-            return CL_SUCCESS;
495
-        }
496
-    }
497
-
498
-    return -1;
499
-}
500
-
501
-/*** Dealing with parent/child relationships in the table. ***/
502
-
503
-/* Determines parent and returns a copy based on full pathname. */
504
-inline static char *onas_get_parent(const char *pathname, size_t len)
505
-{
506
-    if (!pathname || len <= 1) return NULL;
507
-
508
-    int idx   = len - 2;
509
-    char *ret = NULL;
510
-
511
-    while (idx >= 0 && pathname[idx] != '/') {
512
-        idx--;
513
-    }
514
-
515
-    if (idx == 0) {
516
-        idx++;
517
-    }
518
-
519
-    ret = cli_strndup(pathname, idx);
520
-    if (!ret) {
521
-        errno = ENOMEM;
522
-        return NULL;
523
-    }
524
-
525
-    return ret;
526
-}
527
-
528
-/* Gets the index at which the name of directory begins from the full pathname. */
529
-inline static int onas_get_dirname_idx(const char *pathname, size_t len)
530
-{
531
-    if (!pathname || len <= 1) return -1;
532
-
533
-    int idx = len - 2;
534
-
535
-    while (idx >= 0 && pathname[idx] != '/') {
536
-        idx--;
537
-    }
538
-
539
-    if (pathname[idx] == '/')
540
-        return idx + 1;
541
-
542
-    return idx;
543
-}
544
-
545
-/* Emancipates the specified child from the specified parent. */
546
-int onas_ht_rm_child(struct onas_ht *ht, const char *prntpath, size_t prntlen, const char *childpath, size_t childlen)
547
-{
548
-
549
-    if (!ht || !prntpath || prntlen <= 0 || !childpath || childlen <= 1) return CL_ENULLARG;
550
-
551
-    struct onas_element *elem = NULL;
552
-    struct onas_hnode *hnode  = NULL;
553
-    int idx                   = onas_get_dirname_idx(childpath, childlen);
554
-    int ret                   = 0;
555
-
556
-    if (idx <= 0) return CL_SUCCESS;
557
-
558
-    if (onas_ht_get(ht, prntpath, prntlen, &elem) != CL_SUCCESS) return CL_EARG;
559
-
560
-    hnode = elem->data;
561
-
562
-    if ((ret = onas_rm_listnode(hnode->childhead, &(childpath[idx])))) return CL_EARG;
563
-
564
-    return CL_SUCCESS;
565
-}
566
-
567
-/* The specified parent adds the specified child to its list. */
568
-int onas_ht_add_child(struct onas_ht *ht, const char *prntpath, size_t prntlen, const char *childpath, size_t childlen)
569
-{
570
-    if (!ht || !prntpath || prntlen <= 0 || !childpath || childlen <= 1) return CL_ENULLARG;
571
-
572
-    struct onas_element *elem = NULL;
573
-    struct onas_hnode *hnode  = NULL;
574
-    int idx                   = onas_get_dirname_idx(childpath, childlen);
575
-
576
-    if (idx <= 0) return CL_SUCCESS;
577
-
578
-    if (onas_ht_get(ht, prntpath, prntlen, &elem)) return CL_EARG;
579
-    hnode = elem->data;
580
-
581
-    return onas_add_hashnode_child(hnode, &(childpath[idx]));
582
-}
583
-
584
-/*** Dealing with hierarchy changes. ***/
585
-
586
-/* Adds the hierarchy under pathname to the tree and allocates all necessary memory. */
587
-int onas_ht_add_hierarchy(struct onas_ht *ht, const char *pathname)
588
-{
589
-    if (!ht || !pathname) return CL_ENULLARG;
590
-
591
-    FTS *ftsp         = NULL;
592
-    int ftspopts      = FTS_PHYSICAL | FTS_XDEV;
593
-    FTSENT *curr      = NULL;
594
-    FTSENT *childlist = NULL;
595
-
596
-    size_t len = strlen(pathname);
597
-    char *prnt = onas_get_parent(pathname, len);
598
-    if (prnt) onas_ht_add_child(ht, prnt, strlen(prnt), pathname, len);
599
-    free(prnt);
600
-
601
-    char *const pathargv[] = {(char *)pathname, NULL};
602
-    if (!(ftsp = _priv_fts_open(pathargv, ftspopts, NULL))) {
603
-        logg("!ScanOnAccess: Could not open '%s'\n", pathname);
604
-        return CL_EARG;
605
-    }
606
-
607
-    while ((curr = _priv_fts_read(ftsp))) {
608
-
609
-        struct onas_hnode *hnode = NULL;
610
-
611
-        /* May want to handle other options in the future. */
612
-        switch (curr->fts_info) {
613
-            case FTS_D:
614
-                hnode = onas_hashnode_init();
615
-                if (!hnode) return CL_EMEM;
616
-
617
-                hnode->pathlen  = curr->fts_pathlen;
618
-                hnode->pathname = cli_strndup(curr->fts_path, hnode->pathlen);
619
-
620
-                hnode->prnt_pathname = onas_get_parent(hnode->pathname, hnode->pathlen);
621
-                if (hnode->prnt_pathname)
622
-                    hnode->prnt_pathlen = strlen(hnode->prnt_pathname);
623
-                else
624
-                    hnode->prnt_pathlen = 0;
625
-                break;
626
-            default:
627
-                continue;
628
-        }
629
-
630
-        if ((childlist = _priv_fts_children(ftsp, 0))) {
631
-            do {
632
-                if (childlist->fts_info == FTS_D) {
633
-                    if (CL_EMEM == onas_add_hashnode_child(hnode, childlist->fts_name)) {
634
-                        onas_free_hashnode(hnode);
635
-                        return CL_EMEM;
636
-                    }
637
-                }
638
-
639
-            } while ((childlist = childlist->fts_link));
640
-        }
641
-
642
-        struct onas_element *elem = onas_element_init(hnode, hnode->pathname, hnode->pathlen);
643
-        if (!elem) return CL_EMEM;
644
-
645
-        if (onas_ht_insert(ht, elem)) {
646
-            onas_free_element(elem);
647
-            return CL_EMEM;
648
-        }
649
-    }
650
-
651
-    _priv_fts_close(ftsp);
652
-    return CL_SUCCESS;
653
-}
654
-
655
-/* Removes the underlying hierarchy from the tree and frees all associated memory. */
656
-int onas_ht_rm_hierarchy(struct onas_ht *ht, const char *pathname, size_t len, int level)
657
-{
658
-    if (!ht || !pathname || len <= 0) return CL_ENULLARG;
659
-
660
-    struct onas_hnode *hnode  = NULL;
661
-    struct onas_element *elem = NULL;
662
-    char *prntname            = NULL;
663
-    size_t prntlen            = 0;
664
-
665
-    if (onas_ht_get(ht, pathname, len, &elem)) return CL_EARG;
666
-
667
-    hnode = elem->data;
668
-
669
-    struct onas_lnode *curr = hnode->childhead;
670
-
671
-    if (level == 0) {
672
-        if (!(prntname = onas_get_parent(pathname, len))) return CL_EARG;
673
-
674
-        prntlen = strlen(prntname);
675
-        if (onas_ht_rm_child(ht, prntname, prntlen, pathname, len)) return CL_EARG;
676
-
677
-        free(prntname);
678
-    }
679
-
680
-    while (curr->next != hnode->childtail) {
681
-        curr = curr->next;
682
-
683
-        size_t size      = len + strlen(curr->dirname) + 2;
684
-        char *child_path = (char *)cli_malloc(size);
685
-        if (child_path == NULL)
686
-            return CL_EMEM;
687
-        if (hnode->pathname[len - 1] == '/')
688
-            snprintf(child_path, size, "%s%s", hnode->pathname, curr->dirname);
689
-        else
690
-            snprintf(child_path, size, "%s/%s", hnode->pathname, curr->dirname);
691
-        onas_ht_rm_hierarchy(ht, child_path, size, level + 1);
692
-        free(child_path);
693
-    }
694
-
695
-    onas_ht_remove(ht, pathname, len, NULL);
696
-    onas_free_element(elem);
697
-
698
-    return CL_SUCCESS;
699
-}
700
-#endif
701 1
deleted file mode 100644
... ...
@@ -1,109 +0,0 @@
1
-/*
2
- *  Copyright (C) 2015-2019 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
3
- *
4
- *  Authors: Mickey Sola
5
- *
6
- *  This program is free software; you can redistribute it and/or modify
7
- *  it under the terms of the GNU General Public License version 2 as
8
- *  published by the Free Software Foundation.
9
- *
10
- *  This program is distributed in the hope that it will be useful,
11
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
- *  GNU General Public License for more details.
14
- *
15
- *  You should have received a copy of the GNU General Public License
16
- *  along with this program; if not, write to the Free Software
17
- *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
18
- *  MA 02110-1301, USA.
19
- */
20
-
21
-#ifndef __ONAS_HASH_H
22
-#define __ONAS_HASH_H
23
-
24
-#define ONAS_FANWATCH 0x1
25
-#define ONAS_INWATCH 0x2
26
-#define ONAS_STOPWATCH 0x3
27
-
28
-#define ONAS_DEFAULT_HT_SIZE 1 << 18
29
-
30
-struct onas_element {
31
-
32
-    const char *key;
33
-    size_t klen;
34
-    struct onas_hnode *data;
35
-
36
-    struct onas_element *next;
37
-    struct onas_element *prev;
38
-};
39
-
40
-struct onas_bucket {
41
-
42
-    uint32_t size;
43
-
44
-    struct onas_element *head;
45
-    struct onas_element *tail;
46
-};
47
-
48
-struct onas_ht {
49
-
50
-    struct onas_bucket **htable;
51
-
52
-    /* Must be a sufficiently high power of two--will not grow. */
53
-    uint32_t size;
54
-    uint32_t nbckts;
55
-};
56
-
57
-/* Directory node struct for lists */
58
-struct onas_lnode {
59
-
60
-    /* List stuffs */
61
-    char *dirname;
62
-    struct onas_lnode *next;
63
-    struct onas_lnode *prev;
64
-};
65
-
66
-/* Directory node struct for hash tables */
67
-struct onas_hnode {
68
-
69
-    /* Path info */
70
-    int pathlen;
71
-    char *pathname;
72
-
73
-    /* Parent info */
74
-    int prnt_pathlen;
75
-    char *prnt_pathname;
76
-
77
-    /* Child head and tail are empty sentinels */
78
-    struct onas_lnode *childhead;
79
-    struct onas_lnode *childtail;
80
-
81
-    /* Inotify watch descriptor */
82
-    int wd;
83
-
84
-    /* Watched stuffs */
85
-    uint32_t watched;
86
-};
87
-
88
-void onas_free_ht(struct onas_ht *ht);
89
-int onas_ht_init(struct onas_ht **ht, uint32_t table_size);
90
-int onas_ht_insert(struct onas_ht *ht, struct onas_element *elem);
91
-int onas_ht_remove(struct onas_ht *ht, const char *key, size_t klen, struct onas_element **elem);
92
-int onas_ht_get(struct onas_ht *ht, const char *key, size_t klen, struct onas_element **elem);
93
-int onas_ht_rm_hierarchy(struct onas_ht *ht, const char *pathname, size_t len, int level);
94
-int onas_ht_add_hierarchy(struct onas_ht *ht, const char *pathname);
95
-int onas_ht_add_child(struct onas_ht *ht, const char *prntpath, size_t prntlen, const char *childpath, size_t childlen);
96
-int onas_ht_rm_child(struct onas_ht *ht, const char *prntpath, size_t prntlen, const char *childpath, size_t childlen);
97
-
98
-void onas_free_element(struct onas_element *elem);
99
-struct onas_element *onas_element_init(struct onas_hnode *value, const char *key, size_t klen);
100
-
101
-void onas_free_hashnode(struct onas_hnode *hnode);
102
-
103
-void onas_free_listnode(struct onas_lnode *lnode);
104
-int onas_add_listnode(struct onas_lnode *tail, struct onas_lnode *node);
105
-int onas_rm_listnode(struct onas_lnode *head, const char *dirname);
106
-
107
-void onas_free_dirlist(struct onas_lnode *head);
108
-
109
-#endif
110 1
deleted file mode 100644
... ...
@@ -1,120 +0,0 @@
1
-/*
2
- *  Copyright (C) 2017-2019 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
3
- *
4
- *  Authors: Mickey Sola
5
- *
6
- *  This program is free software; you can redistribute it and/or modify
7
- *  it under the terms of the GNU General Public License version 2 as
8
- *  published by the Free Software Foundation.
9
- *
10
- *  This program is distributed in the hope that it will be useful,
11
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
- *  GNU General Public License for more details.
14
- *
15
- *  You should have received a copy of the GNU General Public License
16
- *  along with this program; if not, write to the Free Software
17
- *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
18
- *  MA 02110-1301, USA.
19
- */
20
-
21
-#if HAVE_CONFIG_H
22
-#include "clamav-config.h"
23
-#endif
24
-
25
-#if defined(FANOTIFY)
26
-
27
-#include <stdio.h>
28
-#include <stdarg.h>
29
-#include <stdlib.h>
30
-#include <string.h>
31
-//#include <fcntl.h>
32
-#include <sys/stat.h>
33
-#include <errno.h>
34
-#include <pthread.h>
35
-//#include <limits.h>
36
-#include "libclamav/clamav.h"
37
-//#include "libclamav/scanners.h"
38
-#include "shared/optparser.h"
39
-#include "shared/output.h"
40
-//#include "shared/misc.h"
41
-//#include "libclamav/others.h"
42
-
43
-//#include "others.h"
44
-
45
-#include "onaccess_others.h"
46
-#include "clamd/scanner.h"
47
-
48
-static pthread_mutex_t onas_scan_lock = PTHREAD_MUTEX_INITIALIZER;
49
-
50
-int onas_fan_checkowner(int pid, const struct optstruct *opts)
51
-{
52
-    char path[32];
53
-    STATBUF sb;
54
-    const struct optstruct *opt      = NULL;
55
-    const struct optstruct *opt_root = NULL;
56
-
57
-    /* always ignore ourselves */
58
-    if (pid == (int)getpid()) {
59
-        return CHK_SELF;
60
-    }
61
-
62
-    /* look up options */
63
-    opt      = optget(opts, "OnAccessExcludeUID");
64
-    opt_root = optget(opts, "OnAccessExcludeRootUID");
65
-
66
-    /* we can return immediately if no uid exclusions were requested */
67
-    if (!(opt->enabled || opt_root->enabled))
68
-        return CHK_CLEAN;
69
-
70
-    /* perform exclusion checks if we can stat OK */
71
-    snprintf(path, sizeof(path), "/proc/%u", pid);
72
-    if (CLAMSTAT(path, &sb) == 0) {
73
-        /* check all our non-root UIDs first */
74
-        if (opt->enabled) {
75
-            while (opt) {
76
-                if (opt->numarg == (long long)sb.st_uid)
77
-                    return CHK_FOUND;
78
-                opt = opt->nextarg;
79
-            }
80
-        }
81
-        /* finally check root UID */
82
-        if (opt_root->enabled) {
83
-            if (0 == (long long)sb.st_uid)
84
-                return CHK_FOUND;
85
-        }
86
-    } else if (errno == EACCES) {
87
-        logg("*Permission denied to stat /proc/%d to exclude UIDs... perhaps SELinux denial?\n", pid);
88
-    } else if (errno == ENOENT) {
89
-        /* FIXME: should this be configurable? */
90
-        logg("$/proc/%d vanished before UIDs could be excluded; scanning anyway\n", pid);
91
-    }
92
-
93
-    return CHK_CLEAN;
94
-}
95
-
96
-int onas_scan(const char *fname, int fd, const char **virname, const struct cl_engine *engine, struct cl_scan_options *options, int extinfo)
97
-{
98
-    int ret = 0;
99
-    struct cb_context context;
100
-
101
-    pthread_mutex_lock(&onas_scan_lock);
102
-
103
-    context.filename = fname;
104
-    context.virsize  = 0;
105
-    context.scandata = NULL;
106
-
107
-    /*ret = cl_scandesc_callback(fd, fname, virname, NULL, engine, options, &context);*/
108
-
109
-    if (ret) {
110
-        if (extinfo && context.virsize)
111
-            logg("ScanOnAccess: %s: %s(%s:%llu) FOUND\n", fname, *virname, context.virhash, context.virsize);
112
-        else
113
-            logg("ScanOnAccess: %s: %s FOUND\n", fname, *virname);
114
-    }
115
-
116
-    pthread_mutex_unlock(&onas_scan_lock);
117
-
118
-    return ret;
119
-}
120
-#endif
121 1
deleted file mode 100644
... ...
@@ -1,36 +0,0 @@
1
-/*
2
- *  Copyright (C) 2017-2019 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
3
- *
4
- *  Authors: Mickey Sola
5
- *
6
- *  This program is free software; you can redistribute it and/or modify
7
- *  it under the terms of the GNU General Public License version 2 as
8
- *  published by the Free Software Foundation.
9
- *
10
- *  This program is distributed in the hope that it will be useful,
11
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
- *  GNU General Public License for more details.
14
- *
15
- *  You should have received a copy of the GNU General Public License
16
- *  along with this program; if not, write to the Free Software
17
- *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
18
- *  MA 02110-1301, USA.
19
- */
20
-
21
-#ifndef __CLAMD_ONAS_OTHERS_H
22
-#define __CLAMD_ONAS_OTHERS_H
23
-
24
-#include "shared/optparser.h"
25
-#include "libclamav/clamav.h"
26
-
27
-typedef enum {
28
-    CHK_CLEAN,
29
-    CHK_FOUND,
30
-    CHK_SELF
31
-} cli_check_t;
32
-
33
-int onas_fan_checkowner(int pid, const struct optstruct *opts);
34
-int onas_scan(const char *fname, int fd, const char **virname, const struct cl_engine *engine, struct cl_scan_options *options, int extinfo);
35
-
36
-#endif
37 1
deleted file mode 100644
... ...
@@ -1,691 +0,0 @@
1
-/*
2
- *  Copyright (C) 2015 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
3
- *  Copyright (C) 2009 Sourcefire, Inc.
4
- *
5
- *  Authors: Tomasz Kojm, aCaB
6
- *
7
- *  This program is free software; you can redistribute it and/or modify
8
- *  it under the terms of the GNU General Public License version 2 as
9
- *  published by the Free Software Foundation.
10
- *
11
- *  This program is distributed in the hope that it will be useful,
12
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
- *  GNU General Public License for more details.
15
- *
16
- *  You should have received a copy of the GNU General Public License
17
- *  along with this program; if not, write to the Free Software
18
- *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19
- *  MA 02110-1301, USA.
20
- */
21
-
22
-#if HAVE_CONFIG_H
23
-#include "clamav-config.h"
24
-#endif
25
-
26
-#if defined(C_SOLARIS)
27
-#ifndef __EXTENSIONS__
28
-#define __EXTENSIONS__
29
-#endif
30
-#endif
31
-
32
-/* must be first because it may define _XOPEN_SOURCE */
33
-#include "shared/fdpassing.h"
34
-#include <stdio.h>
35
-#ifdef HAVE_UNISTD_H
36
-#include <unistd.h>
37
-#endif
38
-#include <string.h>
39
-#include <errno.h>
40
-#include <stdlib.h>
41
-#include <sys/types.h>
42
-#include <sys/stat.h>
43
-#include <fcntl.h>
44
-#include <sys/types.h>
45
-#ifdef HAVE_SYS_SELECT_H
46
-#include <sys/select.h>
47
-#endif
48
-#ifndef _WIN32
49
-#include <arpa/inet.h>
50
-#include <sys/socket.h>
51
-#include <sys/un.h>
52
-#include <netdb.h>
53
-#endif
54
-
55
-#include "libclamav/clamav.h"
56
-#include "libclamav/others.h"
57
-#include "shared/actions.h"
58
-#include "shared/output.h"
59
-#include "shared/misc.h"
60
-#include "shared/clamdcom.h"
61
-
62
-#include "onaccess_proto.h"
63
-#include "onaccess_client.h"
64
-
65
-extern unsigned long int maxstream;
66
-int printinfected;
67
-extern struct optstruct *clamdopts;
68
-#ifndef _WIN32
69
-extern struct sockaddr_un nixsock;
70
-#endif
71
-
72
-static const char *scancmd[] = { "CONTSCAN", "MULTISCAN", "INSTREAM", "FILDES", "ALLMATCHSCAN" };
73
-
74
-/* Connects to clamd 
75
- * Returns a FD or -1 on error */
76
-int dconnect() {
77
-    int sockd, res;
78
-    const struct optstruct *opt;
79
-    struct addrinfo hints, *info, *p;
80
-    char port[10];
81
-    char *ipaddr;
82
-
83
-#ifndef _WIN32
84
-    opt = optget(clamdopts, "LocalSocket");
85
-    if (opt->enabled) {
86
-        if ((sockd = socket(AF_UNIX, SOCK_STREAM, 0)) >= 0) {
87
-            if (connect(sockd, (struct sockaddr *)&nixsock, sizeof(nixsock)) == 0)
88
-                return sockd;
89
-            else {
90
-                logg("!Could not connect to clamd on LocalSocket %s: %s\n", opt->strarg, strerror(errno));
91
-                close(sockd);
92
-            }
93
-        }
94
-    }
95
-#endif
96
-
97
-    snprintf(port, sizeof(port), "%lld", optget(clamdopts, "TCPSocket")->numarg);
98
-
99
-    opt = optget(clamdopts, "TCPAddr");
100
-    while (opt) {
101
-        if (opt->enabled) {
102
-            ipaddr = NULL;
103
-            if (opt->strarg)
104
-                ipaddr = (!strcmp(opt->strarg, "any") ? NULL : opt->strarg);
105
-
106
-            memset(&hints, 0x00, sizeof(struct addrinfo));
107
-            hints.ai_family = AF_UNSPEC;
108
-            hints.ai_socktype = SOCK_STREAM;
109
-
110
-            if ((res = getaddrinfo(ipaddr, port, &hints, &info))) {
111
-                logg("!Could not lookup %s: %s\n", ipaddr ? ipaddr : "", gai_strerror(res));
112
-                opt = opt->nextarg;
113
-                continue;
114
-            }
115
-
116
-            for (p = info; p != NULL; p = p->ai_next) {
117
-                if((sockd = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) < 0) {
118
-                    logg("!Can't create the socket: %s\n", strerror(errno));
119
-                    continue;
120
-                }
121
-
122
-                if(connect(sockd, p->ai_addr, p->ai_addrlen) < 0) {
123
-                    logg("!Could not connect to clamd on %s: %s\n", opt->strarg, strerror(errno));
124
-                    closesocket(sockd);
125
-                    continue;
126
-                }
127
-
128
-                freeaddrinfo(info);
129
-                return sockd;
130
-            }
131
-
132
-            freeaddrinfo(info);
133
-        }
134
-        opt = opt->nextarg;
135
-    }
136
-
137
-    return -1;
138
-}
139
-
140
-/* Issues an INSTREAM command to clamd and streams the given file
141
- * Returns >0 on success, 0 soft fail, -1 hard fail */
142
-static int send_stream(int sockd, const char *filename) {
143
-    uint32_t buf[BUFSIZ/sizeof(uint32_t)];
144
-    int fd, len;
145
-    unsigned long int todo = maxstream;
146
-
147
-    if(filename) {
148
-	if((fd = safe_open(filename, O_RDONLY | O_BINARY))<0) {
149
-	    logg("~%s: Access denied. ERROR\n", filename);
150
-	    return 0;
151
-	}
152
-    } else fd = 0;
153
-
154
-    if(sendln(sockd, "zINSTREAM", 10)) {
155
-	close(fd);
156
-	return -1;
157
-    }
158
-
159
-    while((len = read(fd, &buf[1], sizeof(buf) - sizeof(uint32_t))) > 0) {
160
-	if((unsigned int)len > todo) len = todo;
161
-	buf[0] = htonl(len);
162
-	if(sendln(sockd, (const char *)buf, len+sizeof(uint32_t))) {
163
-	    close(fd);
164
-	    return -1;
165
-	}
166
-	todo -= len;
167
-	if(!todo) {
168
-	    len = 0;
169
-	    break;
170
-	}
171
-    }
172
-    close(fd);
173
-    if(len) {
174
-	logg("!Failed to read from %s.\n", filename ? filename : "STDIN");
175
-	return 0;
176
-    }
177
-    *buf=0;
178
-    sendln(sockd, (const char *)buf, 4);
179
-    return 1;
180
-}
181
-
182
-#ifdef HAVE_FD_PASSING
183
-/* Issues a FILDES command and pass a FD to clamd
184
- * Returns >0 on success, 0 soft fail, -1 hard fail */
185
-static int send_fdpass(int sockd, const char *filename) {
186
-    struct iovec iov[1];
187
-    struct msghdr msg;
188
-    struct cmsghdr *cmsg;
189
-    unsigned char fdbuf[CMSG_SPACE(sizeof(int))];
190
-    char dummy[]="";
191
-    int fd;
192
-
193
-    if(filename) {
194
-	if((fd = open(filename, O_RDONLY))<0) {
195
-	    logg("~%s: Access denied. ERROR\n", filename);
196
-	    return 0;
197
-	}
198
-    } else fd = 0;
199
-    if(sendln(sockd, "zFILDES", 8)) {
200
-      close(fd);
201
-      return -1;
202
-    }
203
-
204
-    iov[0].iov_base = dummy;
205
-    iov[0].iov_len = 1;
206
-    memset(&msg, 0, sizeof(msg));
207
-    msg.msg_control = fdbuf;
208
-    msg.msg_iov = iov;
209
-    msg.msg_iovlen = 1;
210
-    msg.msg_controllen = CMSG_LEN(sizeof(int));
211
-    cmsg = CMSG_FIRSTHDR(&msg);
212
-    cmsg->cmsg_len = CMSG_LEN(sizeof(int));
213
-    cmsg->cmsg_level = SOL_SOCKET;
214
-    cmsg->cmsg_type = SCM_RIGHTS;
215
-    *(int *)CMSG_DATA(cmsg) = fd;
216
-    if(sendmsg(sockd, &msg, 0) == -1) {
217
-	logg("!FD send failed: %s\n", strerror(errno));
218
-	close(fd);
219
-	return -1;
220
-    }
221
-    close(fd);
222
-    return 1;
223
-}
224
-#endif
225
-
226
-/* 0: scan, 1: skip */
227
-static int chkpath(const char *path)
228
-{
229
-	const struct optstruct *opt;
230
-
231
-   if((opt = optget(clamdopts, "ExcludePath"))->enabled) {
232
-	while(opt) {
233
-	    if(match_regex(path, opt->strarg) == 1) {
234
-                if (printinfected != 1)
235
-                    logg("~%s: Excluded\n", path);
236
-		return 1;
237
-	    }
238
-	    opt = opt->nextarg;
239
-	}
240
-    }
241
-    return 0;
242
-}
243
-
244
-static int ftw_chkpath(const char *path, struct cli_ftw_cbdata *data)
245
-{
246
-    UNUSEDPARAM(data);
247
-    return chkpath(path);
248
-}
249
-
250
-/* Sends a proper scan request to clamd and parses its replies
251
- * This is used only in non IDSESSION mode
252
- * Returns the number of infected files or -1 on error
253
- * NOTE: filename may be NULL for STREAM scantype. */
254
-int dsresult(int sockd, int scantype, const char *filename, int *printok, int *errors) {
255
-    int infected = 0, len = 0, beenthere = 0;
256
-    char *bol, *eol;
257
-    struct RCVLN rcv;
258
-    STATBUF sb;
259
-
260
-    if(filename && chkpath(filename))
261
-	return 0;
262
-    recvlninit(&rcv, sockd);
263
-
264
-    switch(scantype) {
265
-    case MULTI:
266
-    case CONT:
267
-    case ALLMATCH:
268
-    if (!filename) {
269
-	logg("Filename cannot be NULL for MULTISCAN or CONTSCAN.\n");
270
-	return -1;
271
-    }
272
-    len = strlen(filename) + strlen(scancmd[scantype]) + 3;
273
-    if (!(bol = malloc(len))) {
274
-	logg("!Cannot allocate a command buffer: %s\n", strerror(errno));
275
-	return -1;
276
-    }
277
-    sprintf(bol, "z%s %s", scancmd[scantype], filename);
278
-    if(sendln(sockd, bol, len)) {
279
-	free(bol);
280
-	return -1;
281
-    }
282
-    free(bol);
283
-    break;
284
-
285
-    case STREAM:
286
-        /* NULL filename safe in send_stream() */
287
-	len = send_stream(sockd, filename);
288
-	break;
289
-#ifdef HAVE_FD_PASSING
290
-    case FILDES:
291
-        /* NULL filename safe in send_fdpass() */
292
-	len = send_fdpass(sockd, filename);
293
-	break;
294
-#endif
295
-    }
296
-
297
-    if(len <=0) {
298
-	*printok = 0;
299
-	if(errors)
300
-	    (*errors)++;
301
-	return len;
302
-    }
303
-
304
-    while((len = recvln(&rcv, &bol, &eol))) {
305
-	if(len == -1) return -1;
306
-	beenthere = 1;
307
-	if(!filename) logg("~%s\n", bol);
308
-	if(len > 7) {
309
-	    char *colon = strrchr(bol, ':');
310
-	    if(colon && colon[1] != ' ') {
311
-		char *br;
312
-		*colon = 0;
313
-		br = strrchr(bol, '(');
314
-		if(br)
315
-		    *br = 0;
316
-		colon = strrchr(bol, ':');
317
-	    }
318
-	    if(!colon) {
319
-		char * unkco = "UNKNOWN COMMAND";
320
-		if (!strncmp(bol, unkco, sizeof(unkco) - 1))
321
-		    logg("clamd replied \"UNKNOWN COMMAND\". Command was %s\n", 
322
-			 (scantype < 0 || scantype > MAX_SCANTYPE) ? "unidentified" :
323
-			                                             scancmd[scantype]);
324
-		else
325
-		    logg("Failed to parse reply: \"%s\"\n", bol);
326
-		return -1;
327
-	    } else if(!memcmp(eol - 7, " FOUND", 6)) {
328
-                static char last_filename[PATH_MAX+1] = {'\0'};
329
-		*(eol - 7) = 0;
330
-		*printok = 0;
331
-                if (scantype != ALLMATCH) {
332
-                    infected++;
333
-                } else {
334
-                    if (filename != NULL && strcmp(filename, last_filename)) {
335
-                        infected++;
336
-                        strncpy(last_filename, filename, PATH_MAX);
337
-                        last_filename[PATH_MAX] = '\0';
338
-                    }
339
-                }
340
-		if(filename) {
341
-		    if(scantype >= STREAM) {
342
-			logg("~%s%s FOUND\n", filename, colon);
343
-			if(action) action(filename);
344
-		    } else {
345
-			logg("~%s FOUND\n", bol);
346
-			*colon = '\0';
347
-			if(action)
348
-			    action(bol);
349
-		    }
350
-		}
351
-	    } else if(!memcmp(eol-7, " ERROR", 6)) {
352
-		if(errors)
353
-		    (*errors)++;
354
-		*printok = 0;
355
-		if(filename) {
356
-		    if(scantype >= STREAM)
357
-			logg("~%s%s\n", filename, colon);
358
-		    else
359
-			logg("~%s\n", bol);
360
-		}
361
-	    }
362
-	}
363
-    }
364
-    if(!beenthere) {
365
-        if (!filename) {
366
-	    logg("STDIN: noreply from clamd\n.");
367
-	    return -1;
368
-	}
369
-        if(CLAMSTAT(filename, &sb) == -1) {
370
-	    logg("~%s: stat() failed with %s, clamd may not be responding\n",
371
-		 filename, strerror(errno));
372
-	    return -1;
373
-	}
374
-	if(!S_ISDIR(sb.st_mode)) {
375
-	    logg("~%s: no reply from clamd\n", filename);
376
-	    return -1;
377
-	}
378
-    }
379
-    return infected;
380
-}
381
-
382
-/* Used by serial_callback() */
383
-struct client_serial_data {
384
-    int infected;
385
-    int scantype;
386
-    int printok;
387
-    int files;
388
-    int errors;
389
-};
390
-
391
-/* FTW callback for scanning in non IDSESSION mode
392
- * Returns SUCCESS or BREAK on success, CL_EXXX on error */
393
-static int serial_callback(STATBUF *sb, char *filename, const char *path, enum cli_ftw_reason reason, struct cli_ftw_cbdata *data) {
394
-    struct client_serial_data *c = (struct client_serial_data *)data->data;
395
-    int sockd, ret;
396
-    const char *f = filename;
397
-
398
-    UNUSEDPARAM(sb);
399
-
400
-    if(chkpath(path))
401
-	return CL_SUCCESS;
402
-    c->files++;
403
-    switch(reason) {
404
-    case error_stat:
405
-	logg("!Can't access file %s\n", path);
406
-	c->errors++;
407
-	return CL_SUCCESS;
408
-    case error_mem:
409
-	logg("!Memory allocation failed in ftw\n");
410
-	c->errors++;
411
-	return CL_EMEM;
412
-    case warning_skipped_dir:
413
-	logg("^Directory recursion limit reached\n");
414
-    case warning_skipped_link:
415
-	return CL_SUCCESS;
416
-    case warning_skipped_special:
417
-	logg("^%s: Not supported file type\n", path);
418
-	c->errors++;
419
-	return CL_SUCCESS;
420
-    case visit_directory_toplev:
421
-	if(c->scantype >= STREAM)
422
-	    return CL_SUCCESS;
423
-	f = path;
424
-	filename = NULL;
425
-    case visit_file:
426
-	break;
427
-    }
428
-
429
-    if((sockd = dconnect()) < 0) {
430
-	if(filename) free(filename);
431
-	c->errors++;
432
-	return CL_EOPEN;
433
-    }
434
-    ret = dsresult(sockd, c->scantype, f, &c->printok, &c->errors);
435
-    if(filename) free(filename);
436
-    closesocket(sockd);
437
-    if(ret < 0) {
438
-	c->errors++;
439
-	return CL_EOPEN;
440
-    }
441
-    c->infected += ret;
442
-    if(reason == visit_directory_toplev)
443
-	return CL_BREAK;
444
-    return CL_SUCCESS;
445
-}
446
-
447
-/* Non-IDSESSION handler
448
- * Returns non zero for serious errors, zero otherwise */
449
-int serial_client_scan(char *file, int scantype, int *infected, int *err, int maxlevel, int flags) {
450
-    struct cli_ftw_cbdata data;
451
-    struct client_serial_data cdata;
452
-    int ftw;
453
-
454
-    cdata.infected = 0;
455
-    cdata.files = 0;
456
-    cdata.errors = 0;
457
-    cdata.printok = printinfected^1;
458
-    cdata.scantype = scantype;
459
-    data.data = &cdata;
460
-
461
-    ftw = cli_ftw(file, flags, maxlevel ? maxlevel : INT_MAX, serial_callback, &data, ftw_chkpath);
462
-    *infected += cdata.infected;
463
-    *err += cdata.errors;
464
-
465
-    if(!cdata.errors && (ftw == CL_SUCCESS || ftw == CL_BREAK)) {
466
-	if(cdata.printok)
467
-	    logg("~%s: OK\n", file);
468
-	return 0;
469
-    } else if(!cdata.files) {
470
-	logg("~%s: No files scanned\n", file);
471
-	return 0;
472
-    }
473
-    return 1;
474
-}
475
-
476
-/* Used in IDSESSION mode */
477
-struct client_parallel_data {
478
-    int infected;
479
-    int files;
480
-    int errors;
481
-    int scantype;
482
-    int sockd;
483
-    int lastid;
484
-    int printok;
485
-    struct SCANID {
486
-	unsigned int id;
487
-	const char *file;
488
-	struct SCANID *next;
489
-    } *ids;
490
-};
491
-
492
-/* Sends a proper scan request to clamd and parses its replies
493
- * This is used only in IDSESSION mode
494
- * Returns 0 on success, 1 on hard failures, 2 on len == 0 (bb#1717) */
495
-static int dspresult(struct client_parallel_data *c) {
496
-    const char *filename;
497
-    char *bol, *eol;
498
-    unsigned int rid;
499
-    int len;
500
-    struct SCANID **id = NULL;
501
-    struct RCVLN rcv;
502
-
503
-    recvlninit(&rcv, c->sockd);
504
-    do {
505
-	len = recvln(&rcv, &bol, &eol);
506
-	if(len < 0) return 1;
507
-	if(!len) return 2;
508
-	if((rid = atoi(bol))) {
509
-	    id = &c->ids;
510
-	    while(*id) {
511
-		if((*id)->id == rid) break;
512
-		id = &((*id)->next);
513
-	    }
514
-	    if(!*id) id = NULL;
515
-	}
516
-	if(!id) {
517
-	    logg("!Bogus session id from clamd\n");
518
-	    return 1;
519
-	}
520
-	filename = (*id)->file;
521
-	if(len > 7) {
522
-	    char *colon = strrchr(bol, ':');
523
-	    if(!colon) {
524
-		logg("!Failed to parse reply\n");
525
-		free((void *)filename);
526
-		return 1;
527
-	    } else if(!memcmp(eol - 7, " FOUND", 6)) {
528
-		c->infected++;
529
-		c->printok = 0;
530
-		logg("~%s%s\n", filename, colon);
531
-		if(action) action(filename);
532
-	    } else if(!memcmp(eol-7, " ERROR", 6)) {
533
-		c->errors++;
534
-		c->printok = 0;
535
-		logg("~%s%s\n", filename, colon);
536
-	    }
537
-	}
538
-	free((void *)filename);
539
-	bol = (char *)*id;
540
-	*id = (*id)->next;
541
-	free(bol);
542
-    } while(rcv.cur != rcv.buf); /* clamd sends whole lines, so, on partial lines, we just assume
543
-				    more data can be recv()'d with close to zero latency */
544
-    return 0;
545
-}
546
-
547
-/* FTW callback for scanning in IDSESSION mode
548
- * Returns SUCCESS on success, CL_EXXX or BREAK on error */
549
-static int parallel_callback(STATBUF *sb, char *filename, const char *path, enum cli_ftw_reason reason, struct cli_ftw_cbdata *data) {
550
-    struct client_parallel_data *c = (struct client_parallel_data *)data->data;
551
-    struct SCANID *cid;
552
-    int res = CL_CLEAN;
553
-
554
-    UNUSEDPARAM(sb);
555
-
556
-    if(chkpath(path))
557
-	return CL_SUCCESS;
558
-    c->files++;
559
-    switch(reason) {
560
-    case error_stat:
561
-	logg("!Can't access file %s\n", path);
562
-	c->errors++;
563
-	return CL_SUCCESS;
564
-    case error_mem:
565
-	logg("!Memory allocation failed in ftw\n");
566
-	c->errors++;
567
-	return CL_EMEM;
568
-    case warning_skipped_dir:
569
-	logg("^Directory recursion limit reached\n");
570
-	return CL_SUCCESS;
571
-    case warning_skipped_special:
572
-	logg("^%s: Not supported file type\n", path);
573
-	c->errors++;
574
-    case warning_skipped_link:
575
-    case visit_directory_toplev:
576
-	return CL_SUCCESS;
577
-    case visit_file:
578
-	break;
579
-    }
580
-
581
-    while(1) {
582
-	/* consume all the available input to let some of the clamd
583
-	 * threads blocked on send() to be dead.
584
-	 * by doing so we shouldn't deadlock on the next recv() */
585
-	fd_set rfds, wfds;
586
-	FD_ZERO(&rfds);
587
-	FD_SET(c->sockd, &rfds);
588
-	FD_ZERO(&wfds);
589
-	FD_SET(c->sockd, &wfds);
590
-	if(select(c->sockd + 1, &rfds, &wfds, NULL, NULL) < 0) {
591
-	    if(errno == EINTR) continue;
592
-	    free(filename);
593
-	    logg("!select() failed during session: %s\n", strerror(errno));
594
-	    return CL_BREAK;
595
-	}
596
-	if(FD_ISSET(c->sockd, &rfds)) {
597
-	    if(dspresult(c)) {
598
-		free(filename);
599
-		return CL_BREAK;
600
-	    } else continue;
601
-	}
602
-	if(FD_ISSET(c->sockd, &wfds)) break;
603
-    }
604
-
605
-    cid = (struct SCANID *)malloc(sizeof(struct SCANID));
606
-    if(!cid) {
607
-	free(filename);
608
-	logg("!Failed to allocate scanid entry: %s\n", strerror(errno));
609
-	return CL_BREAK;
610
-    }
611
-    cid->id = ++c->lastid;
612
-    cid->file = filename;
613
-    cid->next = c->ids;
614
-    c->ids = cid;
615
-
616
-    switch(c->scantype) {
617
-#ifdef HAVE_FD_PASSING
618
-    case FILDES:
619
-	res = send_fdpass(c->sockd, filename);
620
-	break;
621
-#endif
622
-    case STREAM:
623
-	res = send_stream(c->sockd, filename);
624
-	break;
625
-    }
626
-    if(res <= 0) {
627
-	c->printok = 0;
628
-	c->errors++;
629
-	c->ids = cid->next;
630
-	c->lastid--;
631
-	free(cid);
632
-	free(filename);
633
-	return res ? CL_BREAK : CL_SUCCESS;
634
-    }
635
-    return CL_SUCCESS;
636
-}
637
-
638
-/* IDSESSION handler
639
- * Returns non zero for serious errors, zero otherwise */
640
-int parallel_client_scan(char *file, int scantype, int *infected, int *err, int maxlevel, int flags) {
641
-    struct cli_ftw_cbdata data;
642
-    struct client_parallel_data cdata;
643
-    int ftw;
644
-
645
-    if((cdata.sockd = dconnect()) < 0)
646
-	return 1;
647
-
648
-    if(sendln(cdata.sockd, "zIDSESSION", 11)) {
649
-	closesocket(cdata.sockd);
650
-	return 1;
651
-    }
652
-
653
-    cdata.infected = 0;
654
-    cdata.files = 0;
655
-    cdata.errors = 0;
656
-    cdata.scantype = scantype;
657
-    cdata.lastid = 0;
658
-    cdata.ids = NULL;
659
-    cdata.printok = printinfected^1;
660
-    data.data = &cdata;
661
-
662
-    ftw = cli_ftw(file, flags, maxlevel ? maxlevel : INT_MAX, parallel_callback, &data, ftw_chkpath);
663
-
664
-    if(ftw != CL_SUCCESS) {
665
-	*err += cdata.errors;
666
-	*infected += cdata.infected;
667
-	closesocket(cdata.sockd);
668
-	return 1;
669
-    }
670
-
671
-    sendln(cdata.sockd, "zEND", 5);
672
-    while(cdata.ids && !dspresult(&cdata));
673
-    closesocket(cdata.sockd);
674
-
675
-    *infected += cdata.infected;
676
-    *err += cdata.errors;
677
-
678
-    if(cdata.ids) {
679
-	logg("!Clamd closed the connection before scanning all files.\n");
680
-	return 1;
681
-    }
682
-    if(cdata.errors)
683
-	return 1;
684
-
685
-    if(!cdata.files)
686
-	return 0;
687
-
688
-    if(cdata.printok)
689
-	logg("~%s: OK\n", file);
690
-    return 0;
691
-}
692 1
deleted file mode 100644
... ...
@@ -1,30 +0,0 @@
1
-/*
2
- *  Copyright (C) 2015 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
3
- *  Copyright (C) 2009 Sourcefire, Inc.
4
- *
5
- *  Authors: Tomasz Kojm, aCaB
6
- *
7
- *  This program is free software; you can redistribute it and/or modify
8
- *  it under the terms of the GNU General Public License version 2 as
9
- *  published by the Free Software Foundation.
10
- *
11
- *  This program is distributed in the hope that it will be useful,
12
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
- *  GNU General Public License for more details.
15
- *
16
- *  You should have received a copy of the GNU General Public License
17
- *  along with this program; if not, write to the Free Software
18
- *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19
- *  MA 02110-1301, USA.
20
- */
21
-
22
-#ifndef ONAS_PROTO_H
23
-#define ONAS_PROTO_H
24
-#include "shared/misc.h"
25
-
26
-int dconnect(void);
27
-int serial_client_scan(char *file, int scantype, int *infected, int *err, int maxlevel, int flags);
28
-int parallel_client_scan(char *file, int scantype, int *infected, int *err, int maxlevel, int flags);
29
-int dsresult(int sockd, int scantype, const char *filename, int *printok, int *errors);
30
-#endif
31 1
deleted file mode 100644
... ...
@@ -1,167 +0,0 @@
1
-/*
2
- *  Copyright (C) 2015-2019 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
3
- *
4
- *  Authors: Mickey Sola
5
- *
6
- *  This program is free software; you can redistribute it and/or modify
7
- *  it under the terms of the GNU General Public License version 2 as
8
- *  published by the Free Software Foundation.
9
- *
10
- *  This program is distributed in the hope that it will be useful,
11
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
- *  GNU General Public License for more details.
14
- *
15
- *  You should have received a copy of the GNU General Public License
16
- *  along with this program; if not, write to the Free Software
17
- *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
18
- *  MA 02110-1301, USA.
19
- */
20
-
21
-#if HAVE_CONFIG_H
22
-#include "clamav-config.h"
23
-#endif
24
-
25
-#if defined(FANOTIFY)
26
-
27
-#include <stdio.h>
28
-#include <unistd.h>
29
-#include <string.h>
30
-#include <fcntl.h>
31
-#include <signal.h>
32
-#include <pthread.h>
33
-
34
-#include "shared/optparser.h"
35
-#include "shared/output.h"
36
-
37
-#include "others.h"
38
-#include "clamd/priv_fts.h"
39
-#include "onaccess_others.h"
40
-#include "onaccess_scth.h"
41
-#include "onaccess_others.h"
42
-
43
-#include "libclamav/clamav.h"
44
-
45
-static int onas_scth_scanfile(const char *fname, int fd, int extinfo, struct scth_thrarg *tharg);
46
-static int onas_scth_handle_dir(const char *pathname, struct scth_thrarg *tharg);
47
-static int onas_scth_handle_file(const char *pathname, struct scth_thrarg *tharg);
48
-
49
-static void onas_scth_exit(int sig);
50
-
51
-static void onas_scth_exit(int sig)
52
-{
53
-    logg("*ScanOnAccess: onas_scth_exit(), signal %d\n", sig);
54
-
55
-    pthread_exit(NULL);
56
-}
57
-
58
-static int onas_scth_scanfile(const char *fname, int fd, int extinfo, struct scth_thrarg *tharg)
59
-{
60
-    int ret             = 0;
61
-    const char *virname = NULL;
62
-
63
-    return onas_scan(fname, fd, &virname, tharg->engine, tharg->options, extinfo);
64
-}
65
-
66
-static int onas_scth_handle_dir(const char *pathname, struct scth_thrarg *tharg)
67
-{
68
-    FTS *ftsp = NULL;
69
-    int fd;
70
-    int ftspopts = FTS_PHYSICAL | FTS_XDEV;
71
-    int extinfo;
72
-    int ret;
73
-    FTSENT *curr = NULL;
74
-
75
-    extinfo = optget(tharg->opts, "ExtendedDetectionInfo")->enabled;
76
-
77
-    char *const pathargv[] = {(char *)pathname, NULL};
78
-    if (!(ftsp = _priv_fts_open(pathargv, ftspopts, NULL))) return CL_EOPEN;
79
-
80
-    while ((curr = _priv_fts_read(ftsp))) {
81
-        if (curr->fts_info != FTS_D) {
82
-            if ((fd = safe_open(curr->fts_path, O_RDONLY | O_BINARY)) == -1)
83
-                return CL_EOPEN;
84
-
85
-            if (onas_scth_scanfile(curr->fts_path, fd, extinfo, tharg) == CL_VIRUS)
86
-                ;
87
-            ret = CL_VIRUS;
88
-
89
-            close(fd);
90
-        }
91
-    }
92
-
93
-    return ret;
94
-}
95
-
96
-static int onas_scth_handle_file(const char *pathname, struct scth_thrarg *tharg)
97
-{
98
-    int fd;
99
-    int extinfo;
100
-    int ret;
101
-
102
-    if (!pathname) return CL_ENULLARG;
103
-
104
-    extinfo = optget(tharg->opts, "ExtendedDetectionInfo")->enabled;
105
-
106
-    if ((fd = safe_open(pathname, O_RDONLY | O_BINARY)) == -1)
107
-        return CL_EOPEN;
108
-    ret = onas_scth_scanfile(pathname, fd, extinfo, tharg);
109
-
110
-    close(fd);
111
-
112
-    return ret;
113
-}
114
-
115
-void *onas_scan_th(void *arg)
116
-{
117
-    struct scth_thrarg *tharg = (struct scth_thrarg *)arg;
118
-    sigset_t sigset;
119
-    struct sigaction act;
120
-
121
-    /* ignore all signals except SIGUSR1 */
122
-    sigfillset(&sigset);
123
-    sigdelset(&sigset, SIGUSR1);
124
-    /* The behavior of a process is undefined after it ignores a
125
-	 * SIGFPE, SIGILL, SIGSEGV, or SIGBUS signal */
126
-    sigdelset(&sigset, SIGFPE);
127
-    sigdelset(&sigset, SIGILL);
128
-    sigdelset(&sigset, SIGSEGV);
129
-#ifdef SIGBUS
130
-    sigdelset(&sigset, SIGBUS);
131
-#endif
132
-    pthread_sigmask(SIG_SETMASK, &sigset, NULL);
133
-    memset(&act, 0, sizeof(struct sigaction));
134
-    act.sa_handler = onas_scth_exit;
135
-    sigfillset(&(act.sa_mask));
136
-    sigaction(SIGUSR1, &act, NULL);
137
-    sigaction(SIGSEGV, &act, NULL);
138
-
139
-    if (NULL == tharg || NULL == tharg->pathname || NULL == tharg->opts || NULL == tharg->engine) {
140
-        logg("ScanOnAccess: Invalid thread arguments for extra scanning\n");
141
-        goto done;
142
-    }
143
-
144
-    if (tharg->extra_options & ONAS_SCTH_ISDIR) {
145
-        logg("*ScanOnAccess: Performing additional scanning on directory '%s'\n", tharg->pathname);
146
-        onas_scth_handle_dir(tharg->pathname, tharg);
147
-    } else if (tharg->extra_options & ONAS_SCTH_ISFILE) {
148
-        logg("*ScanOnAccess: Performing additional scanning on file '%s'\n", tharg->pathname);
149
-        onas_scth_handle_file(tharg->pathname, tharg);
150
-    }
151
-
152
-done:
153
-    if (NULL != tharg->pathname) {
154
-        free(tharg->pathname);
155
-        tharg->pathname = NULL;
156
-    }
157
-    if (NULL != tharg->options) {
158
-        free(tharg->options);
159
-        tharg->options = NULL;
160
-    }
161
-    if (NULL != tharg) {
162
-        free(tharg);
163
-    }
164
-
165
-    return NULL;
166
-}
167
-#endif
168 1
deleted file mode 100644
... ...
@@ -1,40 +0,0 @@
1
-/*
2
- *  Copyright (C) 2015-2019 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
3
- *
4
- *  Authors: Mickey Sola
5
- *
6
- *  This program is free software; you can redistribute it and/or modify
7
- *  it under the terms of the GNU General Public License version 2 as
8
- *  published by the Free Software Foundation.
9
- *
10
- *  This program is distributed in the hope that it will be useful,
11
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
- *  GNU General Public License for more details.
14
- *
15
- *  You should have received a copy of the GNU General Public License
16
- *  along with this program; if not, write to the Free Software
17
- *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
18
- *  MA 02110-1301, USA.
19
- */
20
-
21
-#ifndef __ONAS_SCTH_H
22
-#define __ONAS_SCTH_H
23
-
24
-#include "shared/optparser.h"
25
-#include "libclamav/clamav.h"
26
-
27
-#define ONAS_SCTH_ISDIR 0x01
28
-#define ONAS_SCTH_ISFILE 0x02
29
-
30
-struct scth_thrarg {
31
-    uint32_t extra_options;
32
-    struct cl_scan_options *options;
33
-    const struct optstruct *opts;
34
-    const struct cl_engine *engine;
35
-    char *pathname;
36
-};
37
-
38
-void *onas_scan_th(void *arg);
39
-
40
-#endif
41 1
new file mode 100644
... ...
@@ -0,0 +1,167 @@
0
+/*
1
+ *  Copyright (C) 2015-2019 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
2
+ *
3
+ *  Authors: Mickey Sola
4
+ *
5
+ *  This program is free software; you can redistribute it and/or modify
6
+ *  it under the terms of the GNU General Public License version 2 as
7
+ *  published by the Free Software Foundation.
8
+ *
9
+ *  This program is distributed in the hope that it will be useful,
10
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
+ *  GNU General Public License for more details.
13
+ *
14
+ *  You should have received a copy of the GNU General Public License
15
+ *  along with this program; if not, write to the Free Software
16
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
17
+ *  MA 02110-1301, USA.
18
+ */
19
+
20
+#if HAVE_CONFIG_H
21
+#include "clamav-config.h"
22
+#endif
23
+
24
+#if defined(FANOTIFY)
25
+
26
+#include <stdio.h>
27
+#include <unistd.h>
28
+#include <string.h>
29
+#include <fcntl.h>
30
+#include <signal.h>
31
+#include <pthread.h>
32
+
33
+#include "shared/optparser.h"
34
+#include "shared/output.h"
35
+
36
+#include "others.h"
37
+#include "clamd/priv_fts.h"
38
+#include "../misc/onaccess_others.h"
39
+#include "onaccess_scth.h"
40
+//#include "onaccess_others.h"
41
+
42
+#include "libclamav/clamav.h"
43
+
44
+static int onas_scth_scanfile(const char *fname, int fd, int extinfo, struct scth_thrarg *tharg);
45
+static int onas_scth_handle_dir(const char *pathname, struct scth_thrarg *tharg);
46
+static int onas_scth_handle_file(const char *pathname, struct scth_thrarg *tharg);
47
+
48
+static void onas_scth_exit(int sig);
49
+
50
+static void onas_scth_exit(int sig)
51
+{
52
+    logg("*ScanOnAccess: onas_scth_exit(), signal %d\n", sig);
53
+
54
+    pthread_exit(NULL);
55
+}
56
+
57
+static int onas_scth_scanfile(const char *fname, int fd, int extinfo, struct scth_thrarg *tharg)
58
+{
59
+    int ret             = 0;
60
+    const char *virname = NULL;
61
+
62
+    return onas_scan(fname, fd, &virname, tharg->engine, tharg->options, extinfo);
63
+}
64
+
65
+static int onas_scth_handle_dir(const char *pathname, struct scth_thrarg *tharg)
66
+{
67
+    FTS *ftsp = NULL;
68
+    int fd;
69
+    int ftspopts = FTS_PHYSICAL | FTS_XDEV;
70
+    int extinfo;
71
+    int ret;
72
+    FTSENT *curr = NULL;
73
+
74
+    extinfo = optget(tharg->opts, "ExtendedDetectionInfo")->enabled;
75
+
76
+    char *const pathargv[] = {(char *)pathname, NULL};
77
+    if (!(ftsp = _priv_fts_open(pathargv, ftspopts, NULL))) return CL_EOPEN;
78
+
79
+    while ((curr = _priv_fts_read(ftsp))) {
80
+        if (curr->fts_info != FTS_D) {
81
+            if ((fd = safe_open(curr->fts_path, O_RDONLY | O_BINARY)) == -1)
82
+                return CL_EOPEN;
83
+
84
+            if (onas_scth_scanfile(curr->fts_path, fd, extinfo, tharg) == CL_VIRUS)
85
+                ;
86
+            ret = CL_VIRUS;
87
+
88
+            close(fd);
89
+        }
90
+    }
91
+
92
+    return ret;
93
+}
94
+
95
+static int onas_scth_handle_file(const char *pathname, struct scth_thrarg *tharg)
96
+{
97
+    int fd;
98
+    int extinfo;
99
+    int ret;
100
+
101
+    if (!pathname) return CL_ENULLARG;
102
+
103
+    extinfo = optget(tharg->opts, "ExtendedDetectionInfo")->enabled;
104
+
105
+    if ((fd = safe_open(pathname, O_RDONLY | O_BINARY)) == -1)
106
+        return CL_EOPEN;
107
+    ret = onas_scth_scanfile(pathname, fd, extinfo, tharg);
108
+
109
+    close(fd);
110
+
111
+    return ret;
112
+}
113
+
114
+void *onas_scan_th(void *arg)
115
+{
116
+    struct scth_thrarg *tharg = (struct scth_thrarg *)arg;
117
+    sigset_t sigset;
118
+    struct sigaction act;
119
+
120
+    /* ignore all signals except SIGUSR1 */
121
+    sigfillset(&sigset);
122
+    sigdelset(&sigset, SIGUSR1);
123
+    /* The behavior of a process is undefined after it ignores a
124
+	 * SIGFPE, SIGILL, SIGSEGV, or SIGBUS signal */
125
+    sigdelset(&sigset, SIGFPE);
126
+    sigdelset(&sigset, SIGILL);
127
+    sigdelset(&sigset, SIGSEGV);
128
+#ifdef SIGBUS
129
+    sigdelset(&sigset, SIGBUS);
130
+#endif
131
+    pthread_sigmask(SIG_SETMASK, &sigset, NULL);
132
+    memset(&act, 0, sizeof(struct sigaction));
133
+    act.sa_handler = onas_scth_exit;
134
+    sigfillset(&(act.sa_mask));
135
+    sigaction(SIGUSR1, &act, NULL);
136
+    sigaction(SIGSEGV, &act, NULL);
137
+
138
+    if (NULL == tharg || NULL == tharg->pathname || NULL == tharg->opts || NULL == tharg->engine) {
139
+        logg("ScanOnAccess: Invalid thread arguments for extra scanning\n");
140
+        goto done;
141
+    }
142
+
143
+    if (tharg->extra_options & ONAS_SCTH_ISDIR) {
144
+        logg("*ScanOnAccess: Performing additional scanning on directory '%s'\n", tharg->pathname);
145
+        onas_scth_handle_dir(tharg->pathname, tharg);
146
+    } else if (tharg->extra_options & ONAS_SCTH_ISFILE) {
147
+        logg("*ScanOnAccess: Performing additional scanning on file '%s'\n", tharg->pathname);
148
+        onas_scth_handle_file(tharg->pathname, tharg);
149
+    }
150
+
151
+done:
152
+    if (NULL != tharg->pathname) {
153
+        free(tharg->pathname);
154
+        tharg->pathname = NULL;
155
+    }
156
+    if (NULL != tharg->options) {
157
+        free(tharg->options);
158
+        tharg->options = NULL;
159
+    }
160
+    if (NULL != tharg) {
161
+        free(tharg);
162
+    }
163
+
164
+    return NULL;
165
+}
166
+#endif
0 167
new file mode 100644
... ...
@@ -0,0 +1,40 @@
0
+/*
1
+ *  Copyright (C) 2015-2019 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
2
+ *
3
+ *  Authors: Mickey Sola
4
+ *
5
+ *  This program is free software; you can redistribute it and/or modify
6
+ *  it under the terms of the GNU General Public License version 2 as
7
+ *  published by the Free Software Foundation.
8
+ *
9
+ *  This program is distributed in the hope that it will be useful,
10
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
+ *  GNU General Public License for more details.
13
+ *
14
+ *  You should have received a copy of the GNU General Public License
15
+ *  along with this program; if not, write to the Free Software
16
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
17
+ *  MA 02110-1301, USA.
18
+ */
19
+
20
+#ifndef __ONAS_SCTH_H
21
+#define __ONAS_SCTH_H
22
+
23
+#include "shared/optparser.h"
24
+#include "libclamav/clamav.h"
25
+
26
+#define ONAS_SCTH_ISDIR 0x01
27
+#define ONAS_SCTH_ISFILE 0x02
28
+
29
+struct scth_thrarg {
30
+    uint32_t extra_options;
31
+    struct cl_scan_options *options;
32
+    const struct optstruct *opts;
33
+    const struct cl_engine *engine;
34
+    char *pathname;
35
+};
36
+
37
+void *onas_scan_th(void *arg);
38
+
39
+#endif