1- /*
2- This file is used to populate an array of files in the system
1+ /*
2+ This file is used to populate an array of files in the system
33 each file stored in the array will have permissions etc. We can
44 use this to find SUID binaries and writeable config files etc
55*/
2626/* ============================ PROTOTYPES ============================== */
2727
2828void walk_file_system (char * entry_location , All_Results * all_results , Args * cmdline , vec_void_t * users );
29+ unsigned char get_d_type (struct dirent * entry , const char * location );
2930
3031bool has_extension (File_Info * f , char * extension );
3132bool has_global_write (File_Info * f );
@@ -46,15 +47,67 @@ bool is_folder_writable(char *path);
4647static void add_file_to_thread_pool (char * file_location , char * file_name , All_Results * all_results , Args * cmdline , vec_void_t * users );
4748
4849/* ============================ FUNCTIONS ============================== */
50+ /** Extracts the d_type form file direct structures, even if not provided directly.
51+ * This is the case when calling readdir, as :
52+ * "The only fields in the dirent structure that are mandated by POSIX.1 are d_name and d_ino. The other fields are unstandardized, and not present on all systems"
53+ * However:
54+ * " Currently, only some filesystems have full support for returning the file type in d_type.
55+ * All applications must properly handle areturn of DT_UNKNOWN. "
56+ * In this case lstat is used.
57+ *
58+ * Note this version uses lstat as is consisten with the d_type entry. A seperate version would be needed for following links.
59+ */
60+
61+ unsigned char get_d_type (struct dirent * entry , const char * location ) {
62+ struct stat statbuf ;
63+ unsigned char rv = DT_UNKNOWN ;
64+
65+ if (DT_UNKNOWN == entry -> d_type ){
66+ char filepath [MAXSIZE ];
67+ strncpy (filepath , location , MAXSIZE - 1 );
68+ strncat (filepath , entry -> d_name , MAXSIZE - 1 );
69+ // The call to lstat here might not be thread safe, if the call is being made on the same file at the same time.
70+ // I think there ius no way that this happens at the moment, but am not sure at all.
71+ // Could globally lock this or do some sort of filesystem hash to make this more fine-grained etc.
72+
73+ if (-1 != lstat (entry -> d_name , & statbuf ))
74+ {
75+ // Her would be a good place to sanity check that the inode numbers match.
76+ if (S_ISLNK (statbuf .st_mode )) {
77+ rv = DT_LNK ;
78+ }
79+ else if (S_ISDIR (statbuf .st_mode )) {
80+ rv = DT_DIR ;
81+ }
82+ else if (S_ISREG (statbuf .st_mode )) {
83+ rv = DT_REG ;
84+ }
85+ // Repeat if wanted for: DT_BLK, DT_CHR, DT_FIFO, DT_SOCK
86+ // i.e.:
87+ //else if (S_ISCHR(statbuf.st_mode)) {
88+ // rv = DT_CHR;
89+ //}
90+ } else {
91+ rv = DT_UNKNOWN ;
92+ }
93+ } else {
94+ // The likely case is that the d_type is set.
95+ // Here it can just be read.
96+ rv = entry -> d_type ;
97+ }
98+
99+ return rv ;
100+ }
101+
49102
50103/**
51104 * Walks the file system, will skip files in ignore directory (cmdline arguments)
52- * For each path encountered it will pass the file to a thread pool
53- * The thread pool will perform scans on the file
54- * Note this scan will not walk the proc file system
55- * @param entry_location the root location to walk
56- * @param all_results a pointer to structure containinng all the future enumy findings
57- * @param cmdline a pointer to the run time arguments
105+ * For each path encountered it will pass the file to a thread pool
106+ * The thread pool will perform scans on the file
107+ * Note this scan will not walk the proc file system
108+ * @param entry_location the root location to walk
109+ * @param all_results a pointer to structure containinng all the future enumy findings
110+ * @param cmdline a pointer to the run time arguments
58111 * @param users This is the parsed /etc/passwd file
59112 */
60113void walk_file_system (char * entry_location , All_Results * all_results , Args * cmdline , vec_void_t * users )
@@ -75,13 +128,13 @@ void walk_file_system(char *entry_location, All_Results *all_results, Args *cmdl
75128 {
76129 if (strcmp (entry -> d_name , "." ) != 0 && strcmp (entry -> d_name , ".." ) != 0 )
77130 {
78- if (entry -> d_type & DT_REG )
131+ if (get_d_type ( entry , entry_location ) & DT_REG )
79132 {
80133 strncpy (file_location , entry_location , sizeof (file_location ) - 1 );
81134 strncat (file_location , entry -> d_name , sizeof (file_location ) - 1 - strlen (file_location ));
82135 add_file_to_thread_pool (file_location , entry -> d_name , all_results , cmdline , users );
83136 }
84- else if (entry -> d_type & DT_DIR )
137+ else if (get_d_type ( entry , entry_location ) & DT_DIR )
85138 {
86139 strncpy (file_location , entry_location , sizeof (file_location ) - 1 );
87140 strncat (file_location , entry -> d_name , sizeof (file_location ) - 1 - strlen (file_location ));
@@ -107,53 +160,53 @@ void walk_file_system(char *entry_location, All_Results *all_results, Args *cmdl
107160/* ============================ has_* FUNCTIONS ============================== */
108161
109162/**
110- * Tests to see if other read is enabled
111- * @param fi this is the current file that's being scanned
163+ * Tests to see if other read is enabled
164+ * @param fi this is the current file that's being scanned
112165 */
113166bool has_global_read (File_Info * f )
114167{
115168 return f -> stat -> st_mode & S_IROTH ;
116169}
117170
118171/**
119- * Tests to see if other write is enabled
120- * @param fi this is the current file that's being scanned
172+ * Tests to see if other write is enabled
173+ * @param fi this is the current file that's being scanned
121174 */
122175bool has_global_write (File_Info * f )
123176{
124177 return f -> stat -> st_mode & S_IWOTH ;
125178}
126179
127180/**
128- * Tests to see if other execute is enabled
129- * @param fi this is the current file that's being scanned
181+ * Tests to see if other execute is enabled
182+ * @param fi this is the current file that's being scanned
130183 */
131184bool has_global_execute (File_Info * f )
132185{
133186 return f -> stat -> st_mode & S_IXOTH ;
134187}
135188
136189/**
137- * Tests to see if group execute is enabled
138- * @param fi this is the current file that's being scanned
190+ * Tests to see if group execute is enabled
191+ * @param fi this is the current file that's being scanned
139192 */
140193bool has_group_execute (File_Info * f )
141194{
142195 return f -> stat -> st_mode & S_IXGRP ;
143196}
144197
145198/**
146- * Tests to see if group write is enabled
147- * @param fi this is the current file that's being scanned
199+ * Tests to see if group write is enabled
200+ * @param fi this is the current file that's being scanned
148201 */
149202bool has_group_write (File_Info * f )
150203{
151204 return f -> stat -> st_mode & S_IWGRP ;
152205}
153206
154207/**
155- * Tests to see if the current file has SUID bit enabled
156- * @param fi this is the current file that's being scanned
208+ * Tests to see if the current file has SUID bit enabled
209+ * @param fi this is the current file that's being scanned
157210 */
158211bool has_suid (File_Info * f )
159212{
@@ -162,7 +215,7 @@ bool has_suid(File_Info *f)
162215
163216/**
164217 * Tests to see if the current file has GUID bit enabled
165- * @param fi this is the current file that's being scanned
218+ * @param fi this is the current file that's being scanned
166219 */
167220bool has_guid (File_Info * f )
168221{
@@ -171,7 +224,7 @@ bool has_guid(File_Info *f)
171224
172225/**
173226 * Tests to see if the current file has a matching extension
174- * @param fi this is the current file that's being scanned
227+ * @param fi this is the current file that's being scanned
175228 * @param extension this is the extension to check against
176229 */
177230bool has_extension (File_Info * f , char * extension )
@@ -180,17 +233,17 @@ bool has_extension(File_Info *f, char *extension)
180233}
181234
182235/**
183- * Tests to see if the group or other can execute the file
184- * @param fi this is the current file that's being scanned
236+ * Tests to see if the group or other can execute the file
237+ * @param fi this is the current file that's being scanned
185238 */
186239bool has_executable (File_Info * f )
187240{
188241 return (has_group_execute (f ) || has_global_execute (f ));
189242}
190243
191244/**
192- * Tests to see if the file is readable by the current process
193- * @param fi this is the current file that's being scanned
245+ * Tests to see if the file is readable by the current process
246+ * @param fi this is the current file that's being scanned
194247 */
195248bool can_read (File_Info * fi )
196249{
@@ -204,7 +257,7 @@ bool can_read(File_Info *fi)
204257* abc.tar.gz would return .gz not .tar.gz
205258* The extensions is saved in lowercase
206259* @param buffer location to save the file extension
207- * @param f_name the files name
260+ * @param f_name the files name
208261*/
209262void get_file_extension (char * buf , char * f_name )
210263{
@@ -235,7 +288,7 @@ void get_file_extension(char *buf, char *f_name)
235288}
236289
237290/**
238- * Given a full path this function returns the file path
291+ * Given a full path this function returns the file path
239292 * @param full_path the files full path
240293 * @return a heap pointer containing the file's name
241294 */
@@ -256,10 +309,10 @@ char *get_file_name(char *full_path)
256309}
257310
258311/**
259- * Given a full path this function will return all the files parent directorys
260- * DONT forget to free the returned pointer
261- * @param full_path the files full path
262- * @return a heap pointer containing the files's directory name
312+ * Given a full path this function will return all the files parent directorys
313+ * DONT forget to free the returned pointer
314+ * @param full_path the files full path
315+ * @return a heap pointer containing the files's directory name
263316 */
264317char * get_dir_name (char * full_path )
265318{
@@ -269,8 +322,8 @@ char *get_dir_name(char *full_path)
269322/* ============================ is_* FUNCTIONS ============================== */
270323
271324/**
272- * Given a directory returns true if the current process
273- * can write to that directory
325+ * Given a directory returns true if the current process
326+ * can write to that directory
274327 * @param path location to test if writable
275328 */
276329bool is_folder_writable (char * path )
@@ -282,9 +335,9 @@ bool is_folder_writable(char *path)
282335
283336/**
284337 * Adds the file at to the thread pool of scans to perform
285- * This function blocks if the thread pool is at maxiumum capacity
286- * @param file_location the file to be scaned
287- * @param file_name the name of the file that is going to be ccaned
338+ * This function blocks if the thread pool is at maxiumum capacity
339+ * @param file_location the file to be scaned
340+ * @param file_name the name of the file that is going to be ccaned
288341 */
289342static void add_file_to_thread_pool (char * file_location , char * file_name , All_Results * all_results , Args * cmdline , vec_void_t * users )
290343{
@@ -310,4 +363,4 @@ static void add_file_to_thread_pool(char *file_location, char *file_name, All_Re
310363 usleep (200 );
311364
312365 thpool_add_work (cmdline -> fs_threadpool , (void * )scan_file_for_issues , (void * )args );
313- }
366+ }
0 commit comments