Changeset 131 for trunk/src/sh_suidchk.c
- Timestamp:
- Oct 22, 2007, 11:19:15 PM (17 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/sh_suidchk.c
r119 r131 71 71 72 72 #include "samhain.h" 73 #include "sh_pthread.h" 73 74 #include "sh_utils.h" 74 75 #include "sh_error.h" … … 842 843 char fileHash[2*(KEY_LEN + 1)]; 843 844 845 struct sh_dirent * dirlist = NULL; 846 struct sh_dirent * dirlist_orig = NULL; 844 847 845 848 SL_ENTER(_("sh_suidchk_check_internal")); … … 870 873 /* Loop over directory entries 871 874 */ 875 SH_MUTEX_LOCK(readdir_lock); 876 872 877 do { 873 878 … … 886 891 continue; 887 892 888 tmpcat = SH_ALLOC(PATH_MAX); 889 (void) sl_strlcpy(tmpcat, iname, PATH_MAX); 890 891 if ((sl_strlen(tmpcat) != sl_strlen(iname)) || (tmpcat[0] == '\0')) 892 { 893 sl_status = SL_ETRUNC; 894 } 895 else 896 { 897 if (tmpcat[1] != '\0') 898 sl_status = sl_strlcat(tmpcat, "/", PATH_MAX); 899 } 900 901 if (! SL_ISERROR(sl_status)) 902 sl_status = sl_strlcat(tmpcat, thisEntry->d_name, PATH_MAX); 903 904 if (SL_ISERROR(sl_status)) 905 { 906 tmp = sh_util_safe_name(tmpcat); 907 sh_error_handle ((-1), FIL__, __LINE__, (int) sl_status, 908 MSG_E_SUBGPATH, 909 _("path too long"), 910 _("sh_suidchk_check_internal"), tmp ); 911 SH_FREE(tmp); 912 continue; 913 } 914 915 ++FileLimNum; 916 ++FileLimTotal; 917 918 /* Rate limit (Fps == Files per second) 919 */ 920 if ((ShSuidchkFps > 0 && FileLimNum > ShSuidchkFps && FileLimTotal > 0)&& 921 (ShSuidchkYield == S_FALSE)) 922 { 923 FileLimNum = 0; 924 FileLimNow = time(NULL); 925 926 if ( (FileLimNow - FileLimStart) > 0 && 927 FileLimTotal/(FileLimNow - FileLimStart) > ShSuidchkFps ) 928 (void) retry_msleep((int)((FileLimTotal/(FileLimNow-FileLimStart))/ 929 ShSuidchkFps) , 0); 930 } 893 dirlist = addto_sh_dirlist (thisEntry, dirlist); 894 } 895 896 } while (thisEntry != NULL); 897 898 SH_MUTEX_UNLOCK(readdir_lock); 899 900 closedir(thisDir); 901 902 dirlist_orig = dirlist; 903 904 do { 905 906 /* If the directory is empty, dirlist = NULL 907 */ 908 if (!dirlist) 909 break; 910 911 tmpcat = SH_ALLOC(PATH_MAX); 912 (void) sl_strlcpy(tmpcat, iname, PATH_MAX); 913 914 if ((sl_strlen(tmpcat) != sl_strlen(iname)) || (tmpcat[0] == '\0')) 915 { 916 sl_status = SL_ETRUNC; 917 } 918 else 919 { 920 if (tmpcat[1] != '\0') 921 sl_status = sl_strlcat(tmpcat, "/", PATH_MAX); 922 } 923 924 if (! SL_ISERROR(sl_status)) 925 sl_status = sl_strlcat(tmpcat, dirlist->sh_d_name, PATH_MAX); 926 927 if (SL_ISERROR(sl_status)) 928 { 929 tmp = sh_util_safe_name(tmpcat); 930 sh_error_handle ((-1), FIL__, __LINE__, (int) sl_status, 931 MSG_E_SUBGPATH, 932 _("path too long"), 933 _("sh_suidchk_check_internal"), tmp ); 934 SH_FREE(tmp); 935 dirlist = dirlist->next; 936 continue; 937 } 938 939 ++FileLimNum; 940 ++FileLimTotal; 941 942 /* Rate limit (Fps == Files per second) 943 */ 944 if ((ShSuidchkFps > 0 && FileLimNum > ShSuidchkFps && FileLimTotal > 0)&& 945 (ShSuidchkYield == S_FALSE)) 946 { 947 FileLimNum = 0; 948 FileLimNow = time(NULL); 949 950 if ( (FileLimNow - FileLimStart) > 0 && 951 FileLimTotal/(FileLimNow - FileLimStart) > ShSuidchkFps ) 952 (void) retry_msleep((int)((FileLimTotal/(FileLimNow-FileLimStart))/ 953 ShSuidchkFps) , 0); 954 } 931 955 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 956 status = (int) retry_lstat(FIL__, __LINE__, tmpcat, &buf); 957 958 if (status != 0) 959 { 960 status = errno; 961 tmp = sh_util_safe_name(tmpcat); 962 sh_error_handle (SH_ERR_ERR, FIL__, __LINE__, status, MSG_ERR_LSTAT, 963 sh_error_message(status), 964 tmpcat ); 965 SH_FREE(tmp); 966 } 967 else 968 { 969 if (/*@-usedef@*/S_ISDIR(buf.st_mode)/*@+usedef@*/ && 970 (ShSuidchkExclude == NULL || 971 0 != strcmp(tmpcat, ShSuidchkExclude))) 972 { 973 /* fs is a STATIC string or NULL 974 */ 975 fs = filesystem_type (tmpcat, tmpcat, &buf); 976 if (fs != NULL 953 977 #ifndef SH_SUIDTESTDIR 954 955 956 957 958 959 960 961 962 963 978 && 979 0 != strncmp (_("afs"), fs, 3) && 980 0 != strncmp (_("devfs"), fs, 5) && 981 0 != strncmp (_("iso9660"), fs, 7) && 982 0 != strncmp (_("lustre"), fs, 6) && 983 0 != strncmp (_("mmfs"), fs, 4) && 984 0 != strncmp (_("msdos"), fs, 5) && 985 0 != strncmp (_("nfs"), fs, 3) && 986 0 != strncmp (_("proc"), fs, 4) && 987 0 != strncmp (_("vfat"), fs, 4) 964 988 #endif 989 ) 990 { 991 if ((ShSuidchkNosuid == S_TRUE) || 992 (0 != strncmp (_("nosuid"), fs, 6))) 993 /* fprintf(stderr, "%s: %s\n", fs, tmpcat); */ 994 (void) sh_suidchk_check_internal(tmpcat); 995 } 996 } 997 else if (S_ISREG(buf.st_mode) && 998 (0 !=(S_ISUID & buf.st_mode) || 999 #if defined(HOST_IS_LINUX) 1000 (0 !=(S_ISGID & buf.st_mode) && 1001 0 !=(S_IXGRP & buf.st_mode)) 1002 #else 1003 0 !=(S_ISGID & buf.st_mode) 1004 #endif 965 1005 ) 966 { 967 if ((ShSuidchkNosuid == S_TRUE) || 968 (0 != strncmp (_("nosuid"), fs, 6))) 969 /* fprintf(stderr, "%s: %s\n", fs, tmpcat); */ 970 (void) sh_suidchk_check_internal(tmpcat); 971 } 972 } 973 else if (S_ISREG(buf.st_mode) && 974 (0 !=(S_ISUID & buf.st_mode) || 975 #if defined(HOST_IS_LINUX) 976 (0 !=(S_ISGID & buf.st_mode) && 977 0 !=(S_IXGRP & buf.st_mode)) 978 #else 979 0 !=(S_ISGID & buf.st_mode) 980 #endif 981 ) 982 ) 983 { 984 985 (void) sl_strlcpy (theFile.fullpath, tmpcat, PATH_MAX); 986 theFile.check_mask = sh_files_maskof(SH_LEVEL_READONLY); 987 CLEAR_SH_FFLAG_REPORTED(theFile.file_reported); 988 theFile.attr_string = NULL; 989 990 status = sh_unix_getinfo (ShDFLevel[SH_ERR_T_RO], 991 thisEntry->d_name, 992 &theFile, fileHash, 0); 993 994 tmp = sh_util_safe_name(tmpcat); 995 996 if (status != 0) 997 { 998 sh_error_handle (ShSuidchkSeverity, FIL__, __LINE__, 999 0, MSG_E_SUBGPATH, 1000 _("Could not check suid/sgid file"), 1001 _("sh_suidchk_check_internal"), 1002 tmp); 1003 } 1004 else 1005 { 1006 1007 if ( sh.flag.update == S_TRUE && 1008 (sh.flag.checkSum == SH_CHECK_INIT || 1009 sh.flag.checkSum == SH_CHECK_CHECK)) 1010 { 1011 /* Updating database. Report new files that 1012 * are not in database already. Then compare 1013 * to database and report changes. 1014 */ 1015 if (-1 == sh_hash_have_it (tmpcat)) 1016 { 1017 sh_error_handle ((-1), FIL__, __LINE__, 1018 0, MSG_SUID_FOUND, tmp ); 1019 } 1020 else 1021 { 1022 sh_error_handle (SH_ERR_ALL, FIL__, __LINE__, 1023 0, MSG_SUID_FOUND, tmp ); 1024 } 1025 1026 if (0 == sh_hash_compdata (SH_LEVEL_READONLY, 1006 ) 1007 { 1008 1009 (void) sl_strlcpy (theFile.fullpath, tmpcat, PATH_MAX); 1010 theFile.check_mask = sh_files_maskof(SH_LEVEL_READONLY); 1011 CLEAR_SH_FFLAG_REPORTED(theFile.file_reported); 1012 theFile.attr_string = NULL; 1013 1014 status = sh_unix_getinfo (ShDFLevel[SH_ERR_T_RO], 1015 thisEntry->d_name, 1016 &theFile, fileHash, 0); 1017 1018 tmp = sh_util_safe_name(tmpcat); 1019 1020 if (status != 0) 1021 { 1022 sh_error_handle (ShSuidchkSeverity, FIL__, __LINE__, 1023 0, MSG_E_SUBGPATH, 1024 _("Could not check suid/sgid file"), 1025 _("sh_suidchk_check_internal"), 1026 tmp); 1027 } 1028 else 1029 { 1030 1031 if ( sh.flag.update == S_TRUE && 1032 (sh.flag.checkSum == SH_CHECK_INIT || 1033 sh.flag.checkSum == SH_CHECK_CHECK)) 1034 { 1035 /* Updating database. Report new files that 1036 * are not in database already. Then compare 1037 * to database and report changes. 1038 */ 1039 if (-1 == sh_hash_have_it (tmpcat)) 1040 { 1041 sh_error_handle ((-1), FIL__, __LINE__, 1042 0, MSG_SUID_FOUND, tmp ); 1043 } 1044 else 1045 { 1046 sh_error_handle (SH_ERR_ALL, FIL__, __LINE__, 1047 0, MSG_SUID_FOUND, tmp ); 1048 } 1049 1050 if (0 == sh_hash_compdata (SH_LEVEL_READONLY, 1051 &theFile, fileHash, 1052 _("[SuidCheck]"), 1053 ShSuidchkSeverity)) 1054 { 1055 sh_hash_pushdata_memory (&theFile, fileHash); 1056 } 1057 1058 sh_hash_addflag(tmpcat, SH_FFLAG_SUIDCHK); 1059 1060 } 1061 1062 else if (sh.flag.checkSum == SH_CHECK_INIT && 1063 sh.flag.update == S_FALSE ) 1064 { 1065 /* Running init. Report on files detected. 1066 */ 1067 sh_hash_pushdata (&theFile, fileHash); 1068 sh_error_handle ((-1), FIL__, __LINE__, 1069 0, MSG_SUID_FOUND, tmp ); 1070 } 1071 1072 else if (sh.flag.checkSum == SH_CHECK_CHECK ) 1073 { 1074 /* Running file check. Report on new files 1075 * detected, and quarantine them. 1076 */ 1077 sh_error_handle (SH_ERR_ALL, FIL__, __LINE__, 1078 0, MSG_SUID_FOUND, tmp ); 1079 1080 fflags = sh_hash_getflags(tmpcat); 1081 1082 if ( (-1 == fflags) || (!SH_FFLAG_SUIDCHK_SET(fflags))) 1083 { 1084 if (-1 == fflags) 1085 report_file(tmpcat, &theFile, timestrc, timestra, timestrm); 1086 1087 /* Quarantine file according to configured method 1088 */ 1089 if (ShSuidchkQEnable == S_TRUE) 1090 { 1091 switch (ShSuidchkQMethod) 1092 { 1093 case SH_Q_DELETE: 1094 sh_q_delete(theFile.fullpath); 1095 break; 1096 case SH_Q_CHANGEPERM: 1097 sh_q_changeperm(theFile.fullpath); 1098 break; 1099 case SH_Q_MOVE: 1100 sh_q_move(theFile.fullpath, &theFile, timestrc, timestra, timestrm); 1101 break; 1102 default: 1103 sh_error_handle (ShSuidchkSeverity, FIL__, 1104 __LINE__, 0, MSG_SUID_QREPORT, 1105 _("Bad quarantine method"), tmp); 1106 break; 1107 } 1108 } 1109 else 1110 { 1111 /* 1.8.1 push file to in-memory database 1112 */ 1113 (void) sh_hash_compdata (SH_LEVEL_READONLY, 1114 &theFile, fileHash, 1115 _("[SuidCheck]"), 1116 ShSuidchkSeverity); 1117 1118 sh_hash_addflag(tmpcat, SH_FFLAG_SUIDCHK); 1119 1120 } 1121 } 1122 else 1123 { 1124 /* File exists. Check for modifications. 1125 */ 1126 (void) sh_hash_compdata (SH_LEVEL_READONLY, 1027 1127 &theFile, fileHash, 1028 _("[SuidCheck]"), 1029 ShSuidchkSeverity)) 1030 { 1031 sh_hash_pushdata_memory (&theFile, fileHash); 1032 } 1033 1034 sh_hash_addflag(tmpcat, SH_FFLAG_SUIDCHK); 1035 1036 } 1037 1038 else if (sh.flag.checkSum == SH_CHECK_INIT && 1039 sh.flag.update == S_FALSE ) 1040 { 1041 /* Running init. Report on files detected. 1042 */ 1043 sh_hash_pushdata (&theFile, fileHash); 1044 sh_error_handle ((-1), FIL__, __LINE__, 1045 0, MSG_SUID_FOUND, tmp ); 1046 } 1047 1048 else if (sh.flag.checkSum == SH_CHECK_CHECK ) 1049 { 1050 /* Running file check. Report on new files 1051 * detected, and quarantine them. 1052 */ 1053 sh_error_handle (SH_ERR_ALL, FIL__, __LINE__, 1054 0, MSG_SUID_FOUND, tmp ); 1055 1056 fflags = sh_hash_getflags(tmpcat); 1057 1058 if ( (-1 == fflags) || (!SH_FFLAG_SUIDCHK_SET(fflags))) 1059 { 1060 if (-1 == fflags) 1061 report_file(tmpcat, &theFile, timestrc, timestra, timestrm); 1062 1063 /* Quarantine file according to configured method 1064 */ 1065 if (ShSuidchkQEnable == S_TRUE) 1066 { 1067 switch (ShSuidchkQMethod) 1068 { 1069 case SH_Q_DELETE: 1070 sh_q_delete(theFile.fullpath); 1071 break; 1072 case SH_Q_CHANGEPERM: 1073 sh_q_changeperm(theFile.fullpath); 1074 break; 1075 case SH_Q_MOVE: 1076 sh_q_move(theFile.fullpath, &theFile, timestrc, timestra, timestrm); 1077 break; 1078 default: 1079 sh_error_handle (ShSuidchkSeverity, FIL__, 1080 __LINE__, 0, MSG_SUID_QREPORT, 1081 _("Bad quarantine method"), tmp); 1082 break; 1083 } 1084 } 1085 else 1086 { 1087 /* 1.8.1 push file to in-memory database 1088 */ 1089 (void) sh_hash_compdata (SH_LEVEL_READONLY, 1090 &theFile, fileHash, 1091 _("[SuidCheck]"), 1092 ShSuidchkSeverity); 1093 1094 sh_hash_addflag(tmpcat, SH_FFLAG_SUIDCHK); 1095 1096 } 1097 } 1098 else 1099 { 1100 /* File exists. Check for modifications. 1101 */ 1102 (void) sh_hash_compdata (SH_LEVEL_READONLY, 1103 &theFile, fileHash, 1104 _("[SuidCheck]"), 1105 ShSuidchkSeverity); 1106 1107 sh_hash_addflag(tmpcat, SH_FFLAG_SUIDCHK); 1108 1109 } 1110 } 1111 } 1112 SH_FREE(tmp); 1113 if (theFile.attr_string) 1114 SH_FREE(theFile.attr_string); 1115 } 1116 } 1117 SH_FREE(tmpcat); 1118 } 1119 1128 _("[SuidCheck]"), 1129 ShSuidchkSeverity); 1130 1131 sh_hash_addflag(tmpcat, SH_FFLAG_SUIDCHK); 1132 1133 } 1134 } 1135 } 1136 SH_FREE(tmp); 1137 if (theFile.attr_string) 1138 SH_FREE(theFile.attr_string); 1139 } 1140 } 1141 SH_FREE(tmpcat); 1142 1143 1120 1144 #ifdef HAVE_SCHED_YIELD 1121 1145 if (ShSuidchkYield == S_TRUE) … … 1125 1149 status = errno; 1126 1150 sh_error_handle ((-1), FIL__, __LINE__, status, MSG_E_SUBGEN, 1127 1151 _("Failed to release time slice"), 1128 1152 _("sh_suidchk_check_internal") ); 1129 1153 } 1130 1154 } 1131 1155 #endif 1132 1133 } while (thisEntry != NULL); 1134 1135 (void) closedir (thisDir); 1156 1157 dirlist = dirlist->next; 1158 1159 } while (dirlist != NULL); 1160 1161 1162 kill_sh_dirlist (dirlist_orig); 1163 1136 1164 SL_RETURN( (0), _("sh_suidchk_check_internal")); 1137 1165 }
Note:
See TracChangeset
for help on using the changeset viewer.