| [1] | 1 | /* SAMHAIN file system integrity testing                                   */ | 
|---|
|  | 2 | /* Copyright (C) 2001 Rainer Wichmann                                      */ | 
|---|
|  | 3 | /*                                                                         */ | 
|---|
|  | 4 | /*  This program is free software; you can redistribute it                 */ | 
|---|
|  | 5 | /*  and/or modify                                                          */ | 
|---|
|  | 6 | /*  it under the terms of the GNU General Public License as                */ | 
|---|
|  | 7 | /*  published by                                                           */ | 
|---|
|  | 8 | /*  the Free Software Foundation; either version 2 of the License, or      */ | 
|---|
|  | 9 | /*  (at your option) any later version.                                    */ | 
|---|
|  | 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., 675 Mass Ave, Cambridge, MA 02139, USA.              */ | 
|---|
|  | 19 |  | 
|---|
|  | 20 | #include "config_xor.h" | 
|---|
|  | 21 |  | 
|---|
|  | 22 |  | 
|---|
|  | 23 | #include <stdio.h> | 
|---|
|  | 24 | #include <stdlib.h> | 
|---|
|  | 25 | #include <string.h> | 
|---|
|  | 26 | #include <sys/types.h> | 
|---|
|  | 27 | #include <sys/stat.h> | 
|---|
|  | 28 | #include <fcntl.h> | 
|---|
|  | 29 | #include <unistd.h> | 
|---|
|  | 30 | #include <errno.h> | 
|---|
|  | 31 | #include <limits.h> | 
|---|
| [94] | 32 |  | 
|---|
| [1] | 33 | #ifdef HAVE_SCHED_H | 
|---|
|  | 34 | #include <sched.h> | 
|---|
|  | 35 | #endif | 
|---|
|  | 36 |  | 
|---|
|  | 37 | #ifdef SH_USE_SUIDCHK | 
|---|
|  | 38 |  | 
|---|
|  | 39 | #undef  FIL__ | 
|---|
|  | 40 | #define FIL__  _("sh_suidchk.c") | 
|---|
|  | 41 |  | 
|---|
|  | 42 | #if defined (SH_WITH_CLIENT) || defined (SH_STANDALONE) | 
|---|
|  | 43 |  | 
|---|
|  | 44 | #if TIME_WITH_SYS_TIME | 
|---|
|  | 45 | #include <sys/time.h> | 
|---|
|  | 46 | #include <time.h> | 
|---|
|  | 47 | #else | 
|---|
|  | 48 | #if HAVE_SYS_TIME_H | 
|---|
|  | 49 | #include <sys/time.h> | 
|---|
|  | 50 | #else | 
|---|
|  | 51 | #include <time.h> | 
|---|
|  | 52 | #endif | 
|---|
|  | 53 | #endif | 
|---|
|  | 54 |  | 
|---|
|  | 55 | #ifdef HAVE_DIRENT_H | 
|---|
|  | 56 | #include <dirent.h> | 
|---|
|  | 57 | #define NAMLEN(dirent) sl_strlen((dirent)->d_name) | 
|---|
|  | 58 | #else | 
|---|
|  | 59 | #define dirent direct | 
|---|
|  | 60 | #define NAMLEN(dirent) (dirent)->d_namlen | 
|---|
|  | 61 | #ifdef HAVE_SYS_NDIR_H | 
|---|
|  | 62 | #include <sys/ndir.h> | 
|---|
|  | 63 | #endif | 
|---|
|  | 64 | #ifdef HAVE_SYS_DIR_H | 
|---|
|  | 65 | #include <sys/dir.h> | 
|---|
|  | 66 | #endif | 
|---|
|  | 67 | #ifdef HAVE_NDIR_H | 
|---|
|  | 68 | #include <ndir.h> | 
|---|
|  | 69 | #endif | 
|---|
|  | 70 | #endif | 
|---|
| [137] | 71 | #define NEED_ADD_DIRENT | 
|---|
| [1] | 72 |  | 
|---|
|  | 73 | #include "samhain.h" | 
|---|
| [131] | 74 | #include "sh_pthread.h" | 
|---|
| [1] | 75 | #include "sh_utils.h" | 
|---|
|  | 76 | #include "sh_error.h" | 
|---|
|  | 77 | #include "sh_modules.h" | 
|---|
|  | 78 | #include "sh_suidchk.h" | 
|---|
|  | 79 | #include "sh_hash.h" | 
|---|
|  | 80 | #include "sh_unix.h" | 
|---|
|  | 81 | #include "sh_files.h" | 
|---|
|  | 82 | #include "sh_schedule.h" | 
|---|
|  | 83 | #include "sh_calls.h" | 
|---|
|  | 84 |  | 
|---|
|  | 85 |  | 
|---|
|  | 86 | sh_rconf sh_suidchk_table[] = { | 
|---|
|  | 87 | { | 
|---|
|  | 88 | N_("severitysuidcheck"), | 
|---|
|  | 89 | sh_suidchk_set_severity | 
|---|
|  | 90 | }, | 
|---|
|  | 91 | { | 
|---|
|  | 92 | N_("suidcheckactive"), | 
|---|
|  | 93 | sh_suidchk_set_activate | 
|---|
|  | 94 | }, | 
|---|
|  | 95 | { | 
|---|
|  | 96 | N_("suidcheckinterval"), | 
|---|
|  | 97 | sh_suidchk_set_timer | 
|---|
|  | 98 | }, | 
|---|
|  | 99 | { | 
|---|
|  | 100 | N_("suidcheckschedule"), | 
|---|
|  | 101 | sh_suidchk_set_schedule | 
|---|
|  | 102 | }, | 
|---|
|  | 103 | { | 
|---|
|  | 104 | N_("suidcheckexclude"), | 
|---|
|  | 105 | sh_suidchk_set_exclude | 
|---|
|  | 106 | }, | 
|---|
|  | 107 | { | 
|---|
|  | 108 | N_("suidcheckfps"), | 
|---|
|  | 109 | sh_suidchk_set_fps | 
|---|
|  | 110 | }, | 
|---|
|  | 111 | { | 
|---|
|  | 112 | N_("suidcheckyield"), | 
|---|
|  | 113 | sh_suidchk_set_yield | 
|---|
|  | 114 | }, | 
|---|
|  | 115 | { | 
|---|
| [119] | 116 | N_("suidchecknosuid"), | 
|---|
|  | 117 | sh_suidchk_set_nosuid | 
|---|
|  | 118 | }, | 
|---|
|  | 119 | { | 
|---|
| [1] | 120 | N_("suidcheckquarantinefiles"), | 
|---|
|  | 121 | sh_suidchk_set_quarantine | 
|---|
|  | 122 | }, | 
|---|
|  | 123 | { | 
|---|
|  | 124 | N_("suidcheckquarantinemethod"), | 
|---|
|  | 125 | sh_suidchk_set_qmethod | 
|---|
|  | 126 | }, | 
|---|
|  | 127 | { | 
|---|
|  | 128 | N_("suidcheckquarantinedelete"), | 
|---|
|  | 129 | sh_suidchk_set_qdelete | 
|---|
|  | 130 | }, | 
|---|
|  | 131 | { | 
|---|
|  | 132 | NULL, | 
|---|
|  | 133 | NULL | 
|---|
|  | 134 | }, | 
|---|
|  | 135 | }; | 
|---|
|  | 136 |  | 
|---|
|  | 137 |  | 
|---|
|  | 138 | static time_t  lastcheck         = (time_t) 0; | 
|---|
|  | 139 | static int     ShSuidchkActive   = S_TRUE; | 
|---|
|  | 140 | static time_t  ShSuidchkInterval = 7200; | 
|---|
|  | 141 | static long    ShSuidchkFps      = 0; | 
|---|
| [119] | 142 | static int     ShSuidchkNosuid   = S_FALSE; | 
|---|
| [1] | 143 | static int     ShSuidchkYield    = S_FALSE; | 
|---|
|  | 144 | static int     ShSuidchkQEnable  = S_FALSE; | 
|---|
|  | 145 | static int     ShSuidchkQMethod  = SH_Q_CHANGEPERM; | 
|---|
|  | 146 | static int     ShSuidchkQDelete  = S_FALSE; | 
|---|
|  | 147 | static int     ShSuidchkSeverity = SH_ERR_SEVERE; | 
|---|
|  | 148 | static char *  ShSuidchkExclude  = NULL; | 
|---|
| [68] | 149 | static size_t  ExcludeLen        = 0; | 
|---|
| [1] | 150 |  | 
|---|
|  | 151 | static time_t  FileLimNow        = 0; | 
|---|
|  | 152 | static time_t  FileLimStart      = 0; | 
|---|
|  | 153 | static long    FileLimNum        = 0; | 
|---|
|  | 154 | static long    FileLimTotal      = 0; | 
|---|
|  | 155 |  | 
|---|
|  | 156 | static sh_schedule_t * ShSuidchkSched = NULL; | 
|---|
|  | 157 |  | 
|---|
|  | 158 | static char * | 
|---|
|  | 159 | filesystem_type (char * path, char * relpath, struct stat * statp); | 
|---|
|  | 160 |  | 
|---|
|  | 161 | #ifndef PATH_MAX | 
|---|
|  | 162 | #define PATH_MAX 1024 | 
|---|
|  | 163 | #endif | 
|---|
|  | 164 |  | 
|---|
|  | 165 | extern unsigned long sh_files_maskof (int class); | 
|---|
|  | 166 |  | 
|---|
| [149] | 167 | static void set_defaults (void) | 
|---|
|  | 168 | { | 
|---|
|  | 169 | ShSuidchkActive   = S_TRUE; | 
|---|
|  | 170 | ShSuidchkInterval = 7200; | 
|---|
|  | 171 | ShSuidchkFps      = 0; | 
|---|
|  | 172 | ShSuidchkNosuid   = S_FALSE; | 
|---|
|  | 173 | ShSuidchkYield    = S_FALSE; | 
|---|
|  | 174 | ShSuidchkQEnable  = S_FALSE; | 
|---|
|  | 175 | ShSuidchkQMethod  = SH_Q_CHANGEPERM; | 
|---|
|  | 176 | ShSuidchkQDelete  = S_FALSE; | 
|---|
|  | 177 | ShSuidchkSeverity = SH_ERR_SEVERE; | 
|---|
|  | 178 | if (ShSuidchkExclude != NULL) | 
|---|
|  | 179 | SH_FREE(ShSuidchkExclude); | 
|---|
|  | 180 | ShSuidchkExclude  = NULL; | 
|---|
|  | 181 | ExcludeLen        = 0; | 
|---|
|  | 182 |  | 
|---|
|  | 183 | FileLimNow        = 0; | 
|---|
|  | 184 | FileLimStart      = 0; | 
|---|
|  | 185 | FileLimNum        = 0; | 
|---|
|  | 186 | FileLimTotal      = 0; | 
|---|
|  | 187 |  | 
|---|
|  | 188 | return; | 
|---|
|  | 189 | } | 
|---|
|  | 190 |  | 
|---|
| [1] | 191 | /* Recursively descend into the directory to make sure that | 
|---|
|  | 192 | * there is no symlink in the path. | 
|---|
|  | 193 | */ | 
|---|
|  | 194 | static int do_truncate_int (char * path, int depth) | 
|---|
|  | 195 | { | 
|---|
|  | 196 | char      * q; | 
|---|
|  | 197 | struct stat one; | 
|---|
|  | 198 | struct stat two; | 
|---|
|  | 199 | int         fd; | 
|---|
| [132] | 200 | char errbuf[SH_ERRBUF_SIZE]; | 
|---|
| [1] | 201 |  | 
|---|
|  | 202 | if (depth > 99) | 
|---|
|  | 203 | { | 
|---|
|  | 204 | sh_error_handle ((-1), FIL__, __LINE__, EINVAL, | 
|---|
|  | 205 | MSG_SUID_ERROR, | 
|---|
|  | 206 | _("do_truncate: max depth 99 exceeded")); | 
|---|
|  | 207 | return -1; | 
|---|
|  | 208 | } | 
|---|
|  | 209 | ++depth; | 
|---|
|  | 210 | if (path[0] != '/') | 
|---|
|  | 211 | { | 
|---|
|  | 212 | sh_error_handle ((-1), FIL__, __LINE__, EINVAL, | 
|---|
|  | 213 | MSG_SUID_ERROR, | 
|---|
|  | 214 | _("do_truncate: not an absolute path")); | 
|---|
|  | 215 | return -1; | 
|---|
|  | 216 | } | 
|---|
|  | 217 | ++path; | 
|---|
|  | 218 | q = strchr(path, '/'); | 
|---|
|  | 219 | if (q) | 
|---|
|  | 220 | { | 
|---|
|  | 221 | *q = '\0'; | 
|---|
|  | 222 | if (0 != retry_lstat(FIL__, __LINE__, path, &one)) | 
|---|
|  | 223 | { | 
|---|
|  | 224 | sh_error_handle ((-1), FIL__, __LINE__, errno, | 
|---|
|  | 225 | MSG_SUID_ERROR, | 
|---|
| [132] | 226 | sh_error_message(errno, errbuf, sizeof(errbuf))); | 
|---|
| [1] | 227 | *q = '/'; | 
|---|
|  | 228 | return -1; | 
|---|
|  | 229 | } | 
|---|
|  | 230 | if (/*@-usedef@*/!S_ISDIR(one.st_mode)/*@+usedef@*/) | 
|---|
|  | 231 |  | 
|---|
|  | 232 | { | 
|---|
|  | 233 | sh_error_handle ((-1), FIL__, __LINE__, EINVAL, | 
|---|
|  | 234 | MSG_SUID_ERROR, | 
|---|
|  | 235 | _("Possible race: not a directory")); | 
|---|
|  | 236 | *q = '/'; | 
|---|
|  | 237 | return -1; | 
|---|
|  | 238 | } | 
|---|
|  | 239 |  | 
|---|
|  | 240 |  | 
|---|
|  | 241 | if (0 != chdir(path)) | 
|---|
|  | 242 | { | 
|---|
|  | 243 | sh_error_handle ((-1), FIL__, __LINE__, errno, | 
|---|
|  | 244 | MSG_SUID_ERROR, | 
|---|
| [132] | 245 | sh_error_message(errno, errbuf, sizeof(errbuf))); | 
|---|
| [1] | 246 | *q = '/'; | 
|---|
|  | 247 | return -1; | 
|---|
|  | 248 | } | 
|---|
|  | 249 | *q = '/'; | 
|---|
|  | 250 | if (0 != retry_lstat(FIL__, __LINE__, ".", &two)) | 
|---|
|  | 251 | { | 
|---|
|  | 252 | sh_error_handle ((-1), FIL__, __LINE__, errno, | 
|---|
|  | 253 | MSG_SUID_ERROR, | 
|---|
| [132] | 254 | sh_error_message(errno, errbuf, sizeof(errbuf))); | 
|---|
| [1] | 255 | return -1; | 
|---|
|  | 256 | } | 
|---|
|  | 257 | if (/*@-usedef@*/(one.st_dev != two.st_dev) || | 
|---|
|  | 258 | (one.st_ino != two.st_ino) || | 
|---|
|  | 259 | (!S_ISDIR(two.st_mode))/*@+usedef@*/) | 
|---|
|  | 260 | { | 
|---|
|  | 261 | sh_error_handle ((-1), FIL__, __LINE__, EINVAL, | 
|---|
|  | 262 | MSG_SUID_ERROR, | 
|---|
|  | 263 | _("Possible race: lstat(dir) != lstat(.)")); | 
|---|
|  | 264 | return -1; | 
|---|
|  | 265 | } | 
|---|
|  | 266 |  | 
|---|
|  | 267 |  | 
|---|
|  | 268 | return (do_truncate_int(q, depth)); | 
|---|
|  | 269 | } | 
|---|
|  | 270 | else | 
|---|
|  | 271 | { | 
|---|
|  | 272 | /* no more '/', so this is the file | 
|---|
|  | 273 | */ | 
|---|
|  | 274 | if (*path == '\0') | 
|---|
|  | 275 | return -1; | 
|---|
|  | 276 | if (0 != retry_lstat(FIL__, __LINE__, path, &one)) | 
|---|
|  | 277 | { | 
|---|
|  | 278 | sh_error_handle ((-1), FIL__, __LINE__, errno, | 
|---|
|  | 279 | MSG_SUID_ERROR, | 
|---|
| [132] | 280 | sh_error_message(errno, errbuf, sizeof(errbuf))); | 
|---|
| [1] | 281 | return -1; | 
|---|
|  | 282 | } | 
|---|
|  | 283 | fd = open(path, O_RDWR); | 
|---|
|  | 284 | if (-1 == fd) | 
|---|
|  | 285 | { | 
|---|
|  | 286 | sh_error_handle ((-1), FIL__, __LINE__, errno, | 
|---|
|  | 287 | MSG_SUID_ERROR, | 
|---|
| [132] | 288 | sh_error_message(errno, errbuf, sizeof(errbuf))); | 
|---|
| [1] | 289 | return -1; | 
|---|
|  | 290 | } | 
|---|
|  | 291 | if (0 != retry_fstat(FIL__, __LINE__, fd, &two)) | 
|---|
|  | 292 | { | 
|---|
|  | 293 | sh_error_handle ((-1), FIL__, __LINE__, errno, | 
|---|
|  | 294 | MSG_SUID_ERROR, | 
|---|
| [132] | 295 | sh_error_message(errno, errbuf, sizeof(errbuf))); | 
|---|
| [1] | 296 | (void) close(fd); | 
|---|
|  | 297 | return -1; | 
|---|
|  | 298 | } | 
|---|
|  | 299 | if (/*@-usedef@*/(one.st_dev != two.st_dev) || | 
|---|
|  | 300 | (one.st_ino != two.st_ino)/*@+usedef@*/) | 
|---|
|  | 301 | { | 
|---|
|  | 302 | sh_error_handle ((-1), FIL__, __LINE__, EINVAL, | 
|---|
|  | 303 | MSG_SUID_ERROR, | 
|---|
|  | 304 | _("Possible race: lstat != fstat")); | 
|---|
|  | 305 | (void) close(fd); | 
|---|
|  | 306 | return -1; | 
|---|
|  | 307 | } | 
|---|
|  | 308 | if (!S_ISREG(two.st_mode)) | 
|---|
|  | 309 | { | 
|---|
|  | 310 | sh_error_handle ((-1), FIL__, __LINE__, EINVAL, | 
|---|
|  | 311 | MSG_SUID_ERROR, | 
|---|
|  | 312 | _("Possible race: not a regular file")); | 
|---|
|  | 313 | (void) close(fd); | 
|---|
|  | 314 | return -1; | 
|---|
|  | 315 | } | 
|---|
|  | 316 | if ((0 == (two.st_mode & S_ISUID)) && (0 == (two.st_mode & S_ISGID))) | 
|---|
|  | 317 | { | 
|---|
|  | 318 | sh_error_handle ((-1), FIL__, __LINE__, EINVAL, | 
|---|
|  | 319 | MSG_SUID_ERROR, | 
|---|
|  | 320 | _("Possible race: not a suid/sgid file")); | 
|---|
|  | 321 | (void) close(fd); | 
|---|
|  | 322 | return -1; | 
|---|
|  | 323 | } | 
|---|
|  | 324 | if (ShSuidchkQDelete == S_FALSE) | 
|---|
|  | 325 | { | 
|---|
|  | 326 | if ((two.st_mode & S_ISUID) > 0) | 
|---|
|  | 327 | two.st_mode -= S_ISUID; | 
|---|
|  | 328 | if ((two.st_mode & S_ISGID) > 0) | 
|---|
|  | 329 | two.st_mode -= S_ISGID; | 
|---|
|  | 330 | #ifdef HAVE_FCHMOD | 
|---|
|  | 331 | if (-1 == /*@-unrecog@*/fchmod(fd, two.st_mode)/*@+unrecog@*/) | 
|---|
|  | 332 | { | 
|---|
|  | 333 | sh_error_handle ((-1), FIL__, __LINE__, errno, | 
|---|
|  | 334 | MSG_SUID_ERROR, | 
|---|
| [132] | 335 | sh_error_message(errno, errbuf, sizeof(errbuf))); | 
|---|
| [1] | 336 | (void) close(fd); | 
|---|
|  | 337 | return -1; | 
|---|
|  | 338 | } | 
|---|
|  | 339 | #else | 
|---|
|  | 340 | sh_error_handle ((-1), FIL__, __LINE__, errno, | 
|---|
|  | 341 | MSG_SUID_ERROR, | 
|---|
|  | 342 | _("The fchmod() function is not available")); | 
|---|
|  | 343 | (void) close(fd); | 
|---|
|  | 344 | return -1; | 
|---|
|  | 345 | #endif | 
|---|
|  | 346 | if (two.st_nlink > 1) | 
|---|
|  | 347 | { | 
|---|
|  | 348 | sh_error_handle ((-1), FIL__, __LINE__, 0, | 
|---|
|  | 349 | MSG_SUID_ERROR, | 
|---|
|  | 350 | _("Not truncated because hardlink count gt 1")); | 
|---|
|  | 351 | (void) close(fd); | 
|---|
|  | 352 | return -1; | 
|---|
|  | 353 | } | 
|---|
|  | 354 | /* The man page says: 'POSIX has ftruncate' | 
|---|
|  | 355 | */ | 
|---|
|  | 356 | if (-1 == /*@-unrecog@*/ftruncate(fd, 0)/*@+unrecog@*/) | 
|---|
|  | 357 | { | 
|---|
|  | 358 | sh_error_handle ((-1), FIL__, __LINE__, errno, | 
|---|
|  | 359 | MSG_SUID_ERROR, | 
|---|
| [132] | 360 | sh_error_message(errno, errbuf, sizeof(errbuf))); | 
|---|
| [1] | 361 | (void) close(fd); | 
|---|
|  | 362 | return -1; | 
|---|
|  | 363 | } | 
|---|
|  | 364 | } | 
|---|
|  | 365 | else | 
|---|
|  | 366 | { | 
|---|
|  | 367 | if (-1 == retry_aud_unlink(FIL__, __LINE__, path)) | 
|---|
|  | 368 | { | 
|---|
|  | 369 | sh_error_handle ((-1), FIL__, __LINE__, errno, | 
|---|
|  | 370 | MSG_SUID_ERROR, | 
|---|
| [132] | 371 | sh_error_message(errno, errbuf, sizeof(errbuf))); | 
|---|
| [1] | 372 | (void) close(fd); | 
|---|
|  | 373 | return -1; | 
|---|
|  | 374 | } | 
|---|
|  | 375 | } | 
|---|
|  | 376 | (void) close (fd); | 
|---|
|  | 377 | return (0); | 
|---|
|  | 378 | } | 
|---|
|  | 379 | } | 
|---|
|  | 380 |  | 
|---|
| [94] | 381 | static int do_truncate (const char * path_in) | 
|---|
| [1] | 382 | { | 
|---|
| [94] | 383 | int    caperr; | 
|---|
|  | 384 | int    result; | 
|---|
|  | 385 | char * path; | 
|---|
| [132] | 386 | char errbuf[SH_ERRBUF_SIZE]; | 
|---|
| [1] | 387 |  | 
|---|
|  | 388 | if (0 != chdir("/")) | 
|---|
|  | 389 | { | 
|---|
|  | 390 | sh_error_handle ((-1), FIL__, __LINE__, errno, | 
|---|
|  | 391 | MSG_SUID_ERROR, | 
|---|
| [132] | 392 | sh_error_message(errno, errbuf, sizeof(errbuf))); | 
|---|
| [1] | 393 | } | 
|---|
|  | 394 |  | 
|---|
|  | 395 | if (0 != (caperr = sl_get_cap_qdel())) | 
|---|
|  | 396 | { | 
|---|
|  | 397 | sh_error_handle((-1), FIL__, __LINE__, caperr, MSG_E_SUBGEN, | 
|---|
| [132] | 398 | sh_error_message (caperr, errbuf, sizeof(errbuf)), | 
|---|
| [1] | 399 | _("sl_get_cap_qdel")); | 
|---|
|  | 400 | } | 
|---|
|  | 401 |  | 
|---|
| [94] | 402 | path   = sh_util_strdup  (path_in); | 
|---|
| [1] | 403 | result = do_truncate_int (path, 0); | 
|---|
| [94] | 404 | SH_FREE(path); | 
|---|
| [1] | 405 |  | 
|---|
|  | 406 | if (0 != (caperr = sl_drop_cap_qdel())) | 
|---|
|  | 407 | { | 
|---|
|  | 408 | sh_error_handle((-1), FIL__, __LINE__, caperr, MSG_E_SUBGEN, | 
|---|
| [132] | 409 | sh_error_message (caperr, errbuf, sizeof(errbuf)), | 
|---|
| [1] | 410 | _("sl_drop_cap_qdel")); | 
|---|
|  | 411 | } | 
|---|
|  | 412 |  | 
|---|
|  | 413 | if (0 != chdir("/")) | 
|---|
|  | 414 | { | 
|---|
|  | 415 | sh_error_handle ((-1), FIL__, __LINE__, errno, | 
|---|
|  | 416 | MSG_SUID_ERROR, | 
|---|
| [132] | 417 | sh_error_message(errno, errbuf, sizeof(errbuf))); | 
|---|
| [1] | 418 | } | 
|---|
|  | 419 | return result; | 
|---|
|  | 420 | } | 
|---|
|  | 421 |  | 
|---|
| [94] | 422 | static void sh_q_delete(const char * fullpath) | 
|---|
|  | 423 | { | 
|---|
|  | 424 | int    status; | 
|---|
|  | 425 | char * msg; | 
|---|
|  | 426 | char * tmp; | 
|---|
|  | 427 |  | 
|---|
|  | 428 | if (do_truncate (fullpath) == -1) | 
|---|
|  | 429 | { | 
|---|
|  | 430 | status = errno; | 
|---|
|  | 431 | msg    = SH_ALLOC(SH_BUFSIZE); | 
|---|
|  | 432 | tmp    = sh_util_safe_name(fullpath); | 
|---|
|  | 433 |  | 
|---|
|  | 434 | (void) sl_snprintf(msg, SH_BUFSIZE, | 
|---|
|  | 435 | _("Problem quarantining file.  File NOT quarantined.  errno = %ld"), | 
|---|
|  | 436 | status); | 
|---|
|  | 437 | sh_error_handle (ShSuidchkSeverity, | 
|---|
|  | 438 | FIL__, __LINE__, | 
|---|
|  | 439 | status, | 
|---|
|  | 440 | MSG_SUID_QREPORT, msg, | 
|---|
|  | 441 | tmp ); | 
|---|
|  | 442 | SH_FREE(tmp); | 
|---|
|  | 443 | SH_FREE(msg); | 
|---|
|  | 444 | } | 
|---|
|  | 445 | else | 
|---|
|  | 446 | { | 
|---|
|  | 447 | tmp    = sh_util_safe_name(fullpath); | 
|---|
|  | 448 | sh_error_handle (ShSuidchkSeverity, | 
|---|
|  | 449 | FIL__, __LINE__, 0, | 
|---|
|  | 450 | MSG_SUID_QREPORT, | 
|---|
|  | 451 | _("Quarantine method applied"), | 
|---|
|  | 452 | tmp ); | 
|---|
|  | 453 | SH_FREE(tmp); | 
|---|
|  | 454 | } | 
|---|
|  | 455 | return; | 
|---|
|  | 456 | } | 
|---|
|  | 457 |  | 
|---|
|  | 458 | static void sh_q_move(const char * fullpath, file_type * theFile, | 
|---|
|  | 459 | const char * timestrc, const char * timestra, | 
|---|
|  | 460 | const char * timestrm) | 
|---|
|  | 461 | { | 
|---|
|  | 462 | int           status; | 
|---|
|  | 463 | int           readFile  = -1; | 
|---|
|  | 464 | int           writeFile = -1;; | 
|---|
|  | 465 | struct stat   fileInfo; | 
|---|
|  | 466 | ssize_t       count; | 
|---|
|  | 467 | char        * msg; | 
|---|
|  | 468 | char        * tmp; | 
|---|
|  | 469 | char        * basetmp; | 
|---|
|  | 470 | char        * filetmp; | 
|---|
|  | 471 | char          buffer[1024]; | 
|---|
|  | 472 | char        * dir = SH_ALLOC(PATH_MAX+1); | 
|---|
|  | 473 | mode_t        umask_old; | 
|---|
|  | 474 | FILE *        filePtr = NULL; | 
|---|
|  | 475 |  | 
|---|
|  | 476 | (void) sl_strlcpy (dir, DEFAULT_QDIR, PATH_MAX+1); | 
|---|
|  | 477 |  | 
|---|
|  | 478 | if (retry_stat (FIL__, __LINE__, dir, &fileInfo) != 0) | 
|---|
|  | 479 | { | 
|---|
|  | 480 | /* Quarantine directory does not exist, | 
|---|
|  | 481 | */ | 
|---|
|  | 482 | status = errno; | 
|---|
|  | 483 | msg    = SH_ALLOC(SH_BUFSIZE); | 
|---|
|  | 484 | tmp    = sh_util_safe_name(fullpath); | 
|---|
|  | 485 |  | 
|---|
|  | 486 | (void) sl_snprintf(msg, SH_BUFSIZE, | 
|---|
|  | 487 | _("Problem quarantining file.  File NOT quarantined.  errno = %ld (stat)"), | 
|---|
|  | 488 | status); | 
|---|
|  | 489 | sh_error_handle (ShSuidchkSeverity, | 
|---|
|  | 490 | FIL__, __LINE__, | 
|---|
|  | 491 | status, | 
|---|
|  | 492 | MSG_SUID_QREPORT, msg, | 
|---|
|  | 493 | tmp ); | 
|---|
|  | 494 | SH_FREE(tmp); | 
|---|
|  | 495 | SH_FREE(msg); | 
|---|
|  | 496 | } | 
|---|
|  | 497 | else | 
|---|
|  | 498 | { | 
|---|
|  | 499 | if (retry_lstat (FIL__, __LINE__, | 
|---|
|  | 500 | fullpath, &fileInfo) == -1) | 
|---|
|  | 501 | { | 
|---|
|  | 502 | status = errno; | 
|---|
|  | 503 | msg    = SH_ALLOC(SH_BUFSIZE); | 
|---|
|  | 504 | tmp    = sh_util_safe_name(fullpath); | 
|---|
|  | 505 |  | 
|---|
|  | 506 | (void) sl_snprintf(msg, SH_BUFSIZE, _("I/O error.  errno = %ld(stat)"), status); | 
|---|
|  | 507 | sh_error_handle (ShSuidchkSeverity, | 
|---|
|  | 508 | FIL__, __LINE__, | 
|---|
|  | 509 | status, | 
|---|
|  | 510 | MSG_SUID_QREPORT, | 
|---|
|  | 511 | msg, tmp ); | 
|---|
|  | 512 | SH_FREE(tmp); | 
|---|
|  | 513 | SH_FREE(msg); | 
|---|
|  | 514 | } | 
|---|
|  | 515 | else | 
|---|
|  | 516 | { | 
|---|
|  | 517 | basetmp = sh_util_strdup(fullpath); | 
|---|
|  | 518 | filetmp = SH_ALLOC(PATH_MAX+1); | 
|---|
|  | 519 | tmp     = sh_util_basename(basetmp); | 
|---|
|  | 520 |  | 
|---|
|  | 521 | (void) sl_snprintf(filetmp, PATH_MAX+1, "%s/%s", | 
|---|
|  | 522 | DEFAULT_QDIR, tmp); | 
|---|
|  | 523 | SH_FREE(tmp); | 
|---|
|  | 524 | SH_FREE(basetmp); | 
|---|
|  | 525 |  | 
|---|
|  | 526 | readFile  = open (fullpath, O_RDONLY); | 
|---|
|  | 527 | if (readFile != -1) | 
|---|
| [166] | 528 | writeFile = open (filetmp, O_WRONLY|O_CREAT, S_IRUSR|S_IWUSR|S_IXUSR); | 
|---|
| [94] | 529 |  | 
|---|
|  | 530 | if ((readFile == -1) || (writeFile == -1)) | 
|---|
|  | 531 | { | 
|---|
|  | 532 | status = errno; | 
|---|
|  | 533 | msg    = SH_ALLOC(SH_BUFSIZE); | 
|---|
|  | 534 | tmp    = sh_util_safe_name(fullpath); | 
|---|
|  | 535 |  | 
|---|
|  | 536 | (void) sl_snprintf(msg, SH_BUFSIZE, _("Problem quarantining file.  File NOT quarantined.  errno = %ld (open)"), status); | 
|---|
|  | 537 | sh_error_handle (ShSuidchkSeverity, | 
|---|
|  | 538 | FIL__, __LINE__, status, | 
|---|
|  | 539 | MSG_SUID_QREPORT, | 
|---|
|  | 540 | msg, tmp ); | 
|---|
|  | 541 | SH_FREE(tmp); | 
|---|
|  | 542 | SH_FREE(msg); | 
|---|
|  | 543 | } | 
|---|
|  | 544 | else | 
|---|
|  | 545 | { | 
|---|
|  | 546 | /* sizeof(buffer) is 1024 | 
|---|
|  | 547 | */ | 
|---|
|  | 548 | while ((count = (int) read (readFile, buffer, sizeof (buffer))) > 0) | 
|---|
|  | 549 | { | 
|---|
|  | 550 | if ((int) write (writeFile, buffer, (size_t) count) != count) | 
|---|
|  | 551 | { | 
|---|
|  | 552 | status = errno; | 
|---|
|  | 553 | msg    = SH_ALLOC(SH_BUFSIZE); | 
|---|
|  | 554 | tmp    = sh_util_safe_name(fullpath); | 
|---|
|  | 555 |  | 
|---|
|  | 556 | (void) sl_snprintf(msg, SH_BUFSIZE, | 
|---|
|  | 557 | _("I/O error.  errno = %ld (write)"), status); | 
|---|
|  | 558 | sh_error_handle (ShSuidchkSeverity, | 
|---|
|  | 559 | FIL__, | 
|---|
|  | 560 | __LINE__, | 
|---|
|  | 561 | status, | 
|---|
|  | 562 | MSG_SUID_QREPORT, | 
|---|
|  | 563 | msg, tmp ); | 
|---|
|  | 564 | SH_FREE(tmp); | 
|---|
|  | 565 | SH_FREE(msg); | 
|---|
|  | 566 | } | 
|---|
|  | 567 | } | 
|---|
|  | 568 | } | 
|---|
|  | 569 |  | 
|---|
|  | 570 | (void) close (readFile); | 
|---|
|  | 571 | (void) fchmod(writeFile, S_IRUSR | S_IWUSR | S_IXUSR); | 
|---|
|  | 572 | (void) close (writeFile); | 
|---|
|  | 573 |  | 
|---|
|  | 574 | if (do_truncate (fullpath) == -1) | 
|---|
|  | 575 | { | 
|---|
|  | 576 | status = errno; | 
|---|
|  | 577 | msg    = SH_ALLOC(SH_BUFSIZE); | 
|---|
|  | 578 | tmp    = sh_util_safe_name(fullpath); | 
|---|
|  | 579 |  | 
|---|
|  | 580 | (void) sl_snprintf(msg, SH_BUFSIZE, | 
|---|
|  | 581 | _("Problem quarantining file.  File NOT quarantined.  errno = %ld"), | 
|---|
|  | 582 | status); | 
|---|
|  | 583 | sh_error_handle (ShSuidchkSeverity, | 
|---|
|  | 584 | FIL__, __LINE__, status, | 
|---|
|  | 585 | MSG_SUID_QREPORT, | 
|---|
|  | 586 | msg, tmp ); | 
|---|
|  | 587 | SH_FREE(tmp); | 
|---|
|  | 588 | SH_FREE(msg); | 
|---|
|  | 589 | } | 
|---|
|  | 590 | else | 
|---|
|  | 591 | { | 
|---|
|  | 592 | tmp = sh_util_basename(fullpath); | 
|---|
|  | 593 |  | 
|---|
|  | 594 | (void) sl_snprintf(filetmp, PATH_MAX+1, "%s/%s.info", | 
|---|
|  | 595 | DEFAULT_QDIR, | 
|---|
|  | 596 | tmp); | 
|---|
|  | 597 |  | 
|---|
|  | 598 | SH_FREE(tmp); | 
|---|
|  | 599 | /* | 
|---|
|  | 600 | * avoid chmod by setting umask | 
|---|
|  | 601 | */ | 
|---|
|  | 602 | umask_old = umask (0077); | 
|---|
|  | 603 | filePtr   = fopen (filetmp, "w+"); | 
|---|
|  | 604 |  | 
|---|
|  | 605 | /*@-usedef@*/ | 
|---|
|  | 606 | if (filePtr) | 
|---|
|  | 607 | { | 
|---|
|  | 608 | fprintf(filePtr, | 
|---|
|  | 609 | _("File Info:\n filename=%s\n size=%lu\n owner=%s(%d)\n group=%s(%d)\n ctime=%s\n atime=%s\n mtime=%s\n"), | 
|---|
|  | 610 | fullpath, | 
|---|
|  | 611 | (unsigned long) theFile->size, | 
|---|
|  | 612 | theFile->c_owner, (int) theFile->owner, | 
|---|
|  | 613 | theFile->c_group, (int) theFile->group, | 
|---|
|  | 614 | timestrc, timestra, timestrm); | 
|---|
|  | 615 | (void) fclose (filePtr); | 
|---|
|  | 616 | } | 
|---|
|  | 617 | /*@+usedef@*/ | 
|---|
|  | 618 | umask (umask_old); | 
|---|
|  | 619 |  | 
|---|
|  | 620 | tmp    = sh_util_safe_name(fullpath); | 
|---|
|  | 621 | sh_error_handle (ShSuidchkSeverity, | 
|---|
|  | 622 | FIL__,__LINE__, | 
|---|
|  | 623 | 0, MSG_SUID_QREPORT, | 
|---|
|  | 624 | _("Quarantine method applied"), | 
|---|
|  | 625 | tmp ); | 
|---|
|  | 626 | SH_FREE(tmp); | 
|---|
|  | 627 | } | 
|---|
|  | 628 | SH_FREE(filetmp); | 
|---|
|  | 629 | } | 
|---|
|  | 630 | } | 
|---|
|  | 631 | SH_FREE(dir); | 
|---|
|  | 632 | return; | 
|---|
|  | 633 | } | 
|---|
|  | 634 |  | 
|---|
|  | 635 | static void sh_q_changeperm(const char * fullpath) | 
|---|
|  | 636 | { | 
|---|
|  | 637 | int             caperr; | 
|---|
|  | 638 | int             status; | 
|---|
|  | 639 | char          * msg; | 
|---|
|  | 640 | char          * tmp; | 
|---|
|  | 641 | struct stat     fileInfo; | 
|---|
|  | 642 | struct stat     fileInfo_F; | 
|---|
|  | 643 | int             cperm_status = 0; | 
|---|
|  | 644 | int             file_d       = -1; | 
|---|
| [132] | 645 | char errbuf[SH_ERRBUF_SIZE]; | 
|---|
| [94] | 646 |  | 
|---|
|  | 647 | if (retry_lstat(FIL__, __LINE__, fullpath, &fileInfo) == -1) | 
|---|
|  | 648 | { | 
|---|
|  | 649 | status = errno; | 
|---|
|  | 650 | msg    = SH_ALLOC(SH_BUFSIZE); | 
|---|
|  | 651 | tmp    = sh_util_safe_name(fullpath); | 
|---|
|  | 652 |  | 
|---|
|  | 653 | (void) sl_snprintf(msg, SH_BUFSIZE, _("I/O error.  errno = %ld"), status); | 
|---|
|  | 654 | sh_error_handle (ShSuidchkSeverity, | 
|---|
|  | 655 | FIL__, __LINE__, | 
|---|
|  | 656 | status, | 
|---|
|  | 657 | MSG_SUID_QREPORT, msg, | 
|---|
|  | 658 | tmp ); | 
|---|
|  | 659 | SH_FREE(tmp); | 
|---|
|  | 660 | SH_FREE(msg); | 
|---|
|  | 661 | cperm_status = -1; | 
|---|
|  | 662 | } | 
|---|
|  | 663 |  | 
|---|
|  | 664 | if (cperm_status == 0) | 
|---|
|  | 665 | { | 
|---|
|  | 666 | if (0 != (caperr = sl_get_cap_qdel())) | 
|---|
|  | 667 | { | 
|---|
|  | 668 | sh_error_handle((-1), FIL__, __LINE__, | 
|---|
|  | 669 | caperr, MSG_E_SUBGEN, | 
|---|
| [132] | 670 | sh_error_message (caperr, errbuf, sizeof(errbuf)), | 
|---|
| [94] | 671 | _("sl_get_cap_qdel")); | 
|---|
|  | 672 | cperm_status = -1; | 
|---|
|  | 673 | } | 
|---|
|  | 674 | } | 
|---|
|  | 675 |  | 
|---|
|  | 676 | if (cperm_status == 0) | 
|---|
|  | 677 | { | 
|---|
|  | 678 | file_d = aud_open (FIL__, __LINE__, SL_YESPRIV, | 
|---|
|  | 679 | fullpath, O_RDONLY, 0); | 
|---|
|  | 680 | if (-1 == file_d) | 
|---|
|  | 681 | { | 
|---|
|  | 682 | status = errno; | 
|---|
|  | 683 | msg    = SH_ALLOC(SH_BUFSIZE); | 
|---|
|  | 684 | tmp    = sh_util_safe_name(fullpath); | 
|---|
|  | 685 |  | 
|---|
|  | 686 | (void) sl_snprintf(msg, SH_BUFSIZE, _("I/O error.  errno = %ld"), status); | 
|---|
|  | 687 | sh_error_handle (ShSuidchkSeverity, | 
|---|
|  | 688 | FIL__, __LINE__, | 
|---|
|  | 689 | status, | 
|---|
|  | 690 | MSG_SUID_QREPORT, msg, | 
|---|
|  | 691 | tmp ); | 
|---|
|  | 692 | SH_FREE(tmp); | 
|---|
|  | 693 | SH_FREE(msg); | 
|---|
|  | 694 | cperm_status = -1; | 
|---|
|  | 695 | } | 
|---|
|  | 696 | } | 
|---|
|  | 697 |  | 
|---|
|  | 698 | if (cperm_status == 0) | 
|---|
|  | 699 | { | 
|---|
|  | 700 | if (retry_fstat(FIL__, __LINE__, file_d, &fileInfo_F) == -1) | 
|---|
|  | 701 | { | 
|---|
|  | 702 | status = errno; | 
|---|
|  | 703 | msg    = SH_ALLOC(SH_BUFSIZE); | 
|---|
|  | 704 | tmp    = sh_util_safe_name(fullpath); | 
|---|
|  | 705 |  | 
|---|
|  | 706 | (void) sl_snprintf(msg, SH_BUFSIZE, | 
|---|
|  | 707 | _("I/O error.  errno = %ld"), status); | 
|---|
|  | 708 | sh_error_handle (ShSuidchkSeverity, | 
|---|
|  | 709 | FIL__, __LINE__, | 
|---|
|  | 710 | status, | 
|---|
|  | 711 | MSG_SUID_QREPORT, msg, | 
|---|
|  | 712 | tmp ); | 
|---|
|  | 713 | SH_FREE(tmp); | 
|---|
|  | 714 | SH_FREE(msg); | 
|---|
|  | 715 | cperm_status = -1; | 
|---|
|  | 716 | } | 
|---|
|  | 717 | } | 
|---|
|  | 718 |  | 
|---|
|  | 719 | if (cperm_status == 0) | 
|---|
|  | 720 | { | 
|---|
|  | 721 | if (fileInfo_F.st_ino  != fileInfo.st_ino || | 
|---|
|  | 722 | fileInfo_F.st_dev  != fileInfo.st_dev || | 
|---|
|  | 723 | fileInfo_F.st_mode != fileInfo.st_mode) | 
|---|
|  | 724 | { | 
|---|
|  | 725 | status = errno; | 
|---|
|  | 726 | msg    = SH_ALLOC(SH_BUFSIZE); | 
|---|
|  | 727 | tmp    = sh_util_safe_name(fullpath); | 
|---|
|  | 728 |  | 
|---|
|  | 729 | (void) sl_snprintf(msg, SH_BUFSIZE, | 
|---|
|  | 730 | _("Race detected.  errno = %ld"), status); | 
|---|
|  | 731 | sh_error_handle (ShSuidchkSeverity, | 
|---|
|  | 732 | FIL__, __LINE__, | 
|---|
|  | 733 | status, | 
|---|
|  | 734 | MSG_SUID_QREPORT, msg, | 
|---|
|  | 735 | tmp ); | 
|---|
|  | 736 | SH_FREE(tmp); | 
|---|
|  | 737 | SH_FREE(msg); | 
|---|
|  | 738 | cperm_status = -1; | 
|---|
|  | 739 | } | 
|---|
|  | 740 | } | 
|---|
|  | 741 |  | 
|---|
|  | 742 | if ((fileInfo.st_mode & S_ISUID) > 0) | 
|---|
|  | 743 | fileInfo.st_mode -= S_ISUID; | 
|---|
|  | 744 | if ((fileInfo.st_mode & S_ISGID) > 0) | 
|---|
|  | 745 | fileInfo.st_mode -= S_ISGID; | 
|---|
|  | 746 |  | 
|---|
|  | 747 | if (cperm_status == 0) | 
|---|
|  | 748 | { | 
|---|
|  | 749 | if (fchmod(file_d, fileInfo.st_mode) == -1) | 
|---|
|  | 750 | { | 
|---|
|  | 751 | status = errno; | 
|---|
|  | 752 | msg    = SH_ALLOC(SH_BUFSIZE); | 
|---|
|  | 753 | tmp    = sh_util_safe_name(fullpath); | 
|---|
|  | 754 |  | 
|---|
|  | 755 | (void) sl_snprintf(msg, SH_BUFSIZE, | 
|---|
|  | 756 | _("Problem quarantining file.  File NOT quarantined.  errno = %ld"), | 
|---|
|  | 757 | status); | 
|---|
|  | 758 | sh_error_handle (ShSuidchkSeverity, | 
|---|
|  | 759 | FIL__, __LINE__, | 
|---|
|  | 760 | status, | 
|---|
|  | 761 | MSG_SUID_QREPORT, | 
|---|
|  | 762 | msg, tmp ); | 
|---|
|  | 763 | SH_FREE(tmp); | 
|---|
|  | 764 | SH_FREE(msg); | 
|---|
|  | 765 | } | 
|---|
|  | 766 | else | 
|---|
|  | 767 | { | 
|---|
|  | 768 | tmp    = sh_util_safe_name(fullpath); | 
|---|
|  | 769 | sh_error_handle (ShSuidchkSeverity, | 
|---|
|  | 770 | FIL__, __LINE__, | 
|---|
|  | 771 | 0, | 
|---|
|  | 772 | MSG_SUID_QREPORT, | 
|---|
|  | 773 | _("Quarantine method applied"), | 
|---|
|  | 774 | tmp ); | 
|---|
|  | 775 | SH_FREE(tmp); | 
|---|
|  | 776 | } | 
|---|
|  | 777 | } | 
|---|
|  | 778 |  | 
|---|
|  | 779 | if (0 != (caperr = sl_drop_cap_qdel())) | 
|---|
|  | 780 | { | 
|---|
|  | 781 | sh_error_handle((-1), FIL__, __LINE__, | 
|---|
|  | 782 | caperr, MSG_E_SUBGEN, | 
|---|
| [132] | 783 | sh_error_message (caperr, errbuf, sizeof(errbuf)), | 
|---|
| [94] | 784 | _("sl_drop_cap_qdel")); | 
|---|
|  | 785 | } | 
|---|
|  | 786 |  | 
|---|
|  | 787 | if (file_d != -1) | 
|---|
|  | 788 | { | 
|---|
|  | 789 | do { | 
|---|
|  | 790 | status = close (file_d); | 
|---|
|  | 791 | } while (status == -1 && errno == EINTR); | 
|---|
|  | 792 |  | 
|---|
|  | 793 | if (-1 == status) | 
|---|
|  | 794 | { | 
|---|
|  | 795 | status = errno; | 
|---|
|  | 796 | msg    = SH_ALLOC(SH_BUFSIZE); | 
|---|
|  | 797 | tmp    = sh_util_safe_name(fullpath); | 
|---|
|  | 798 |  | 
|---|
|  | 799 | (void) sl_snprintf(msg, SH_BUFSIZE, | 
|---|
|  | 800 | _("I/O error.  errno = %ld"), status); | 
|---|
|  | 801 | sh_error_handle (ShSuidchkSeverity, | 
|---|
|  | 802 | FIL__, __LINE__, | 
|---|
|  | 803 | status, | 
|---|
|  | 804 | MSG_SUID_QREPORT, msg, | 
|---|
|  | 805 | tmp ); | 
|---|
|  | 806 | SH_FREE(tmp); | 
|---|
|  | 807 | SH_FREE(msg); | 
|---|
|  | 808 | cperm_status = -1; | 
|---|
|  | 809 | } | 
|---|
|  | 810 | } | 
|---|
|  | 811 | return; | 
|---|
|  | 812 | } | 
|---|
|  | 813 |  | 
|---|
|  | 814 | static void report_file (const char * tmpcat, file_type * theFile, | 
|---|
|  | 815 | char * timestrc, char * timestra, char * timestrm) | 
|---|
|  | 816 | { | 
|---|
|  | 817 | char * msg = SH_ALLOC(SH_BUFSIZE); | 
|---|
|  | 818 | char * tmp = sh_util_safe_name(tmpcat); | 
|---|
|  | 819 |  | 
|---|
|  | 820 | msg[0] = '\0'; | 
|---|
|  | 821 | /*@-usedef@*/ | 
|---|
| [132] | 822 |  | 
|---|
| [94] | 823 | #ifdef SH_USE_XML | 
|---|
|  | 824 | (void) sl_snprintf(msg, SH_BUFSIZE, _("owner_new=\"%s\" iowner_new=\"%ld\" group_new=\"%s\" igroup_new=\"%ld\" size_new=\"%lu\" ctime_new=\"%s\" atime_new=\"%s\" mtime_new=\"%s\""), | 
|---|
|  | 825 | theFile->c_owner, theFile->owner, | 
|---|
|  | 826 | theFile->c_group, theFile->group, | 
|---|
|  | 827 | (unsigned long) theFile->size, | 
|---|
|  | 828 | timestrc, timestra, timestrm); | 
|---|
|  | 829 | #else | 
|---|
|  | 830 | (void) sl_snprintf(msg, SH_BUFSIZE, _("owner_new=<%s>, iowner_new=<%ld>, group_new=<%s>, igroup_new=<%ld>, filesize=<%lu>, ctime=<%s>, atime=<%s>, mtime=<%s>"), | 
|---|
|  | 831 | theFile->c_owner, theFile->owner, | 
|---|
|  | 832 | theFile->c_group, theFile->group, | 
|---|
|  | 833 | (unsigned long) theFile->size, | 
|---|
|  | 834 | timestrc, timestra, timestrm); | 
|---|
|  | 835 | #endif | 
|---|
|  | 836 | /*@+usedef@*/ | 
|---|
|  | 837 |  | 
|---|
|  | 838 | sh_error_handle (ShSuidchkSeverity, FIL__, __LINE__, | 
|---|
|  | 839 | 0, MSG_SUID_POLICY, | 
|---|
|  | 840 | _("suid/sgid file not in database"), | 
|---|
|  | 841 | tmp, msg ); | 
|---|
|  | 842 | SH_FREE(tmp); | 
|---|
|  | 843 | SH_FREE(msg); | 
|---|
|  | 844 | return; | 
|---|
|  | 845 | } | 
|---|
|  | 846 |  | 
|---|
| [1] | 847 | static | 
|---|
|  | 848 | int sh_suidchk_check_internal (char * iname) | 
|---|
|  | 849 | { | 
|---|
|  | 850 | DIR *           thisDir = NULL; | 
|---|
|  | 851 | struct dirent * thisEntry; | 
|---|
|  | 852 | char          * tmpcat; | 
|---|
|  | 853 | char          * tmp; | 
|---|
|  | 854 | char            timestrc[32]; | 
|---|
|  | 855 | char            timestra[32]; | 
|---|
|  | 856 | char            timestrm[32]; | 
|---|
|  | 857 | struct stat     buf; | 
|---|
|  | 858 | int             status; | 
|---|
| [115] | 859 | int             fflags; | 
|---|
| [1] | 860 | char          * fs; | 
|---|
| [170] | 861 | long            sl_status; | 
|---|
| [1] | 862 | file_type       theFile; | 
|---|
| [19] | 863 | char            fileHash[2*(KEY_LEN + 1)]; | 
|---|
| [1] | 864 |  | 
|---|
| [170] | 865 | struct sh_dirent * dirlist; | 
|---|
|  | 866 | struct sh_dirent * dirlist_orig; | 
|---|
| [132] | 867 | char errbuf[SH_ERRBUF_SIZE]; | 
|---|
| [22] | 868 |  | 
|---|
| [1] | 869 | SL_ENTER(_("sh_suidchk_check_internal")); | 
|---|
|  | 870 |  | 
|---|
|  | 871 | if (iname == NULL) | 
|---|
|  | 872 | { | 
|---|
|  | 873 | TPT((0, FIL__, __LINE__ , _("msg=<directory name is NULL>\n"))); | 
|---|
|  | 874 | SL_RETURN( (-1), _("sh_suidchk_check_internal")); | 
|---|
|  | 875 | } | 
|---|
|  | 876 |  | 
|---|
|  | 877 | if (sig_urgent > 0) { | 
|---|
|  | 878 | SL_RETURN( (0), _("sh_suidchk_check_internal")); | 
|---|
|  | 879 | } | 
|---|
|  | 880 |  | 
|---|
|  | 881 | thisDir = opendir (iname); | 
|---|
|  | 882 |  | 
|---|
|  | 883 | if (thisDir == NULL) | 
|---|
|  | 884 | { | 
|---|
|  | 885 | status = errno; | 
|---|
|  | 886 | tmp = sh_util_safe_name(iname); | 
|---|
|  | 887 | sh_error_handle (ShDFLevel[SH_ERR_T_DIR], FIL__, __LINE__, status, | 
|---|
|  | 888 | MSG_E_OPENDIR, | 
|---|
| [132] | 889 | sh_error_message (status, errbuf, sizeof(errbuf)), tmp); | 
|---|
| [1] | 890 | SH_FREE(tmp); | 
|---|
|  | 891 | SL_RETURN( (-1), _("sh_suidchk_check_internal")); | 
|---|
|  | 892 | } | 
|---|
|  | 893 |  | 
|---|
| [94] | 894 | /* Loop over directory entries | 
|---|
|  | 895 | */ | 
|---|
| [137] | 896 | SH_MUTEX_LOCK(mutex_readdir); | 
|---|
| [131] | 897 |  | 
|---|
| [170] | 898 | dirlist      = NULL; | 
|---|
|  | 899 | dirlist_orig = NULL; | 
|---|
|  | 900 |  | 
|---|
| [1] | 901 | do { | 
|---|
|  | 902 |  | 
|---|
|  | 903 | thisEntry = readdir (thisDir); | 
|---|
|  | 904 |  | 
|---|
|  | 905 | if (thisEntry != NULL) { | 
|---|
|  | 906 |  | 
|---|
|  | 907 | if (sl_strcmp (thisEntry->d_name, ".") == 0) | 
|---|
|  | 908 | continue; | 
|---|
|  | 909 |  | 
|---|
|  | 910 | if (sl_strcmp (thisEntry->d_name, "..") == 0) | 
|---|
|  | 911 | continue; | 
|---|
|  | 912 |  | 
|---|
| [131] | 913 | dirlist = addto_sh_dirlist (thisEntry, dirlist); | 
|---|
|  | 914 | } | 
|---|
| [1] | 915 |  | 
|---|
| [131] | 916 | } while (thisEntry != NULL); | 
|---|
| [94] | 917 |  | 
|---|
| [137] | 918 | SH_MUTEX_UNLOCK(mutex_readdir); | 
|---|
| [94] | 919 |  | 
|---|
| [131] | 920 | closedir(thisDir); | 
|---|
| [1] | 921 |  | 
|---|
| [131] | 922 | dirlist_orig = dirlist; | 
|---|
| [1] | 923 |  | 
|---|
| [170] | 924 | sl_status = SL_ENONE; | 
|---|
|  | 925 |  | 
|---|
| [131] | 926 | do { | 
|---|
|  | 927 |  | 
|---|
|  | 928 | /* If the directory is empty, dirlist = NULL | 
|---|
|  | 929 | */ | 
|---|
|  | 930 | if (!dirlist) | 
|---|
|  | 931 | break; | 
|---|
|  | 932 |  | 
|---|
| [143] | 933 | if (sig_urgent > 0) { | 
|---|
|  | 934 | SL_RETURN( (0), _("sh_suidchk_check_internal")); | 
|---|
|  | 935 | } | 
|---|
|  | 936 |  | 
|---|
| [131] | 937 | tmpcat = SH_ALLOC(PATH_MAX); | 
|---|
|  | 938 | (void) sl_strlcpy(tmpcat, iname, PATH_MAX); | 
|---|
|  | 939 |  | 
|---|
|  | 940 | if ((sl_strlen(tmpcat) != sl_strlen(iname)) || (tmpcat[0] == '\0')) | 
|---|
|  | 941 | { | 
|---|
|  | 942 | sl_status = SL_ETRUNC; | 
|---|
|  | 943 | } | 
|---|
|  | 944 | else | 
|---|
|  | 945 | { | 
|---|
|  | 946 | if (tmpcat[1] != '\0') | 
|---|
|  | 947 | sl_status = sl_strlcat(tmpcat, "/",                 PATH_MAX); | 
|---|
|  | 948 | } | 
|---|
|  | 949 |  | 
|---|
|  | 950 | if (! SL_ISERROR(sl_status)) | 
|---|
|  | 951 | sl_status = sl_strlcat(tmpcat, dirlist->sh_d_name,   PATH_MAX); | 
|---|
|  | 952 |  | 
|---|
|  | 953 | if (SL_ISERROR(sl_status)) | 
|---|
|  | 954 | { | 
|---|
|  | 955 | tmp = sh_util_safe_name(tmpcat); | 
|---|
|  | 956 | sh_error_handle ((-1), FIL__, __LINE__, (int) sl_status, | 
|---|
|  | 957 | MSG_E_SUBGPATH, | 
|---|
|  | 958 | _("path too long"), | 
|---|
|  | 959 | _("sh_suidchk_check_internal"), tmp ); | 
|---|
|  | 960 | SH_FREE(tmp); | 
|---|
|  | 961 | dirlist = dirlist->next; | 
|---|
|  | 962 | continue; | 
|---|
|  | 963 | } | 
|---|
|  | 964 |  | 
|---|
|  | 965 | ++FileLimNum; | 
|---|
|  | 966 | ++FileLimTotal; | 
|---|
|  | 967 |  | 
|---|
|  | 968 | /* Rate limit (Fps == Files per second) | 
|---|
|  | 969 | */ | 
|---|
|  | 970 | if ((ShSuidchkFps > 0 && FileLimNum > ShSuidchkFps && FileLimTotal > 0)&& | 
|---|
|  | 971 | (ShSuidchkYield == S_FALSE)) | 
|---|
|  | 972 | { | 
|---|
|  | 973 | FileLimNum  = 0; | 
|---|
|  | 974 | FileLimNow  = time(NULL); | 
|---|
|  | 975 |  | 
|---|
|  | 976 | if ( (FileLimNow  - FileLimStart) > 0 && | 
|---|
|  | 977 | FileLimTotal/(FileLimNow  - FileLimStart) > ShSuidchkFps ) | 
|---|
|  | 978 | (void) retry_msleep((int)((FileLimTotal/(FileLimNow-FileLimStart))/ | 
|---|
|  | 979 | ShSuidchkFps) , 0); | 
|---|
|  | 980 | } | 
|---|
| [1] | 981 |  | 
|---|
| [131] | 982 | status = (int) retry_lstat(FIL__, __LINE__, tmpcat, &buf); | 
|---|
| [1] | 983 |  | 
|---|
| [131] | 984 | if (status != 0) | 
|---|
|  | 985 | { | 
|---|
|  | 986 | status = errno; | 
|---|
|  | 987 | tmp = sh_util_safe_name(tmpcat); | 
|---|
|  | 988 | sh_error_handle (SH_ERR_ERR, FIL__, __LINE__, status, MSG_ERR_LSTAT, | 
|---|
| [132] | 989 | sh_error_message(status, errbuf, sizeof(errbuf)), | 
|---|
| [131] | 990 | tmpcat ); | 
|---|
|  | 991 | SH_FREE(tmp); | 
|---|
|  | 992 | } | 
|---|
|  | 993 | else | 
|---|
|  | 994 | { | 
|---|
|  | 995 | if (/*@-usedef@*/S_ISDIR(buf.st_mode)/*@+usedef@*/ && | 
|---|
|  | 996 | (ShSuidchkExclude == NULL || | 
|---|
|  | 997 | 0 != strcmp(tmpcat, ShSuidchkExclude))) | 
|---|
|  | 998 | { | 
|---|
|  | 999 | /* fs is a STATIC string or NULL | 
|---|
|  | 1000 | */ | 
|---|
|  | 1001 | fs = filesystem_type (tmpcat, tmpcat, &buf); | 
|---|
|  | 1002 | if (fs != NULL | 
|---|
| [30] | 1003 | #ifndef SH_SUIDTESTDIR | 
|---|
| [131] | 1004 | && | 
|---|
|  | 1005 | 0 != strncmp (_("afs"),     fs, 3) && | 
|---|
|  | 1006 | 0 != strncmp (_("devfs"),   fs, 5) && | 
|---|
|  | 1007 | 0 != strncmp (_("iso9660"), fs, 7) && | 
|---|
|  | 1008 | 0 != strncmp (_("lustre"),  fs, 6) && | 
|---|
|  | 1009 | 0 != strncmp (_("mmfs"),    fs, 4) && | 
|---|
|  | 1010 | 0 != strncmp (_("msdos"),   fs, 5) && | 
|---|
|  | 1011 | 0 != strncmp (_("nfs"),     fs, 3) && | 
|---|
|  | 1012 | 0 != strncmp (_("proc"),    fs, 4) && | 
|---|
|  | 1013 | 0 != strncmp (_("vfat"),    fs, 4) | 
|---|
| [30] | 1014 | #endif | 
|---|
| [131] | 1015 | ) | 
|---|
|  | 1016 | { | 
|---|
|  | 1017 | if ((ShSuidchkNosuid == S_TRUE) || | 
|---|
|  | 1018 | (0 != strncmp (_("nosuid"),  fs, 6))) | 
|---|
|  | 1019 | /* fprintf(stderr, "%s: %s\n", fs, tmpcat); */ | 
|---|
|  | 1020 | (void) sh_suidchk_check_internal(tmpcat); | 
|---|
|  | 1021 | } | 
|---|
|  | 1022 | } | 
|---|
|  | 1023 | else if (S_ISREG(buf.st_mode) && | 
|---|
|  | 1024 | (0 !=(S_ISUID & buf.st_mode) || | 
|---|
| [1] | 1025 | #if defined(HOST_IS_LINUX) | 
|---|
| [131] | 1026 | (0 !=(S_ISGID & buf.st_mode) && | 
|---|
|  | 1027 | 0 !=(S_IXGRP & buf.st_mode)) | 
|---|
| [1] | 1028 | #else | 
|---|
| [131] | 1029 | 0 !=(S_ISGID & buf.st_mode) | 
|---|
| [1] | 1030 | #endif | 
|---|
| [131] | 1031 | ) | 
|---|
|  | 1032 | ) | 
|---|
|  | 1033 | { | 
|---|
|  | 1034 |  | 
|---|
|  | 1035 | (void) sl_strlcpy (theFile.fullpath, tmpcat, PATH_MAX); | 
|---|
|  | 1036 | theFile.check_mask  = sh_files_maskof(SH_LEVEL_READONLY); | 
|---|
|  | 1037 | CLEAR_SH_FFLAG_REPORTED(theFile.file_reported); | 
|---|
|  | 1038 | theFile.attr_string = NULL; | 
|---|
| [167] | 1039 | theFile.link_path   = NULL; | 
|---|
| [131] | 1040 |  | 
|---|
|  | 1041 | status = sh_unix_getinfo (ShDFLevel[SH_ERR_T_RO], | 
|---|
| [138] | 1042 | dirlist->sh_d_name, | 
|---|
| [131] | 1043 | &theFile, fileHash, 0); | 
|---|
|  | 1044 |  | 
|---|
|  | 1045 | tmp = sh_util_safe_name(tmpcat); | 
|---|
|  | 1046 |  | 
|---|
|  | 1047 | if (status != 0) | 
|---|
|  | 1048 | { | 
|---|
|  | 1049 | sh_error_handle (ShSuidchkSeverity, FIL__, __LINE__, | 
|---|
|  | 1050 | 0, MSG_E_SUBGPATH, | 
|---|
|  | 1051 | _("Could not check suid/sgid file"), | 
|---|
|  | 1052 | _("sh_suidchk_check_internal"), | 
|---|
|  | 1053 | tmp); | 
|---|
|  | 1054 | } | 
|---|
|  | 1055 | else | 
|---|
|  | 1056 | { | 
|---|
|  | 1057 |  | 
|---|
|  | 1058 | if ( sh.flag.update   == S_TRUE && | 
|---|
|  | 1059 | (sh.flag.checkSum == SH_CHECK_INIT  || | 
|---|
|  | 1060 | sh.flag.checkSum == SH_CHECK_CHECK)) | 
|---|
|  | 1061 | { | 
|---|
|  | 1062 | /* Updating database. Report new files that | 
|---|
|  | 1063 | * are not in database already. Then compare | 
|---|
|  | 1064 | * to database and report changes. | 
|---|
|  | 1065 | */ | 
|---|
|  | 1066 | if (-1 == sh_hash_have_it (tmpcat)) | 
|---|
|  | 1067 | { | 
|---|
|  | 1068 | sh_error_handle ((-1), FIL__, __LINE__, | 
|---|
|  | 1069 | 0, MSG_SUID_FOUND, tmp ); | 
|---|
|  | 1070 | } | 
|---|
|  | 1071 | else | 
|---|
|  | 1072 | { | 
|---|
|  | 1073 | sh_error_handle (SH_ERR_ALL, FIL__, __LINE__, | 
|---|
|  | 1074 | 0, MSG_SUID_FOUND, tmp ); | 
|---|
|  | 1075 | } | 
|---|
|  | 1076 |  | 
|---|
|  | 1077 | if (0 == sh_hash_compdata (SH_LEVEL_READONLY, | 
|---|
|  | 1078 | &theFile, fileHash, | 
|---|
|  | 1079 | _("[SuidCheck]"), | 
|---|
|  | 1080 | ShSuidchkSeverity)) | 
|---|
|  | 1081 | { | 
|---|
|  | 1082 | sh_hash_pushdata_memory (&theFile, fileHash); | 
|---|
|  | 1083 | } | 
|---|
|  | 1084 |  | 
|---|
|  | 1085 | sh_hash_addflag(tmpcat, SH_FFLAG_SUIDCHK); | 
|---|
|  | 1086 |  | 
|---|
|  | 1087 | } | 
|---|
|  | 1088 |  | 
|---|
|  | 1089 | else if (sh.flag.checkSum == SH_CHECK_INIT  && | 
|---|
|  | 1090 | sh.flag.update == S_FALSE ) | 
|---|
|  | 1091 | { | 
|---|
|  | 1092 | /* Running init. Report on files detected. | 
|---|
|  | 1093 | */ | 
|---|
|  | 1094 | sh_hash_pushdata (&theFile, fileHash); | 
|---|
|  | 1095 | sh_error_handle ((-1), FIL__, __LINE__, | 
|---|
|  | 1096 | 0, MSG_SUID_FOUND, tmp ); | 
|---|
|  | 1097 | } | 
|---|
|  | 1098 |  | 
|---|
|  | 1099 | else if (sh.flag.checkSum == SH_CHECK_CHECK ) | 
|---|
|  | 1100 | { | 
|---|
|  | 1101 | /* Running file check. Report on new files | 
|---|
|  | 1102 | * detected, and quarantine them. | 
|---|
|  | 1103 | */ | 
|---|
|  | 1104 | sh_error_handle (SH_ERR_ALL, FIL__, __LINE__, | 
|---|
|  | 1105 | 0, MSG_SUID_FOUND, tmp ); | 
|---|
|  | 1106 |  | 
|---|
|  | 1107 | fflags = sh_hash_getflags(tmpcat); | 
|---|
|  | 1108 |  | 
|---|
|  | 1109 | if ( (-1 == fflags) || (!SH_FFLAG_SUIDCHK_SET(fflags))) | 
|---|
|  | 1110 | { | 
|---|
|  | 1111 | if (-1 == fflags) | 
|---|
| [132] | 1112 | { | 
|---|
| [137] | 1113 | (void) sh_unix_gmttime (theFile.ctime, timestrc, sizeof(timestrc)); | 
|---|
|  | 1114 | (void) sh_unix_gmttime (theFile.atime, timestra, sizeof(timestra)); | 
|---|
|  | 1115 | (void) sh_unix_gmttime (theFile.mtime, timestrm, sizeof(timestrm)); | 
|---|
| [132] | 1116 |  | 
|---|
|  | 1117 | report_file(tmpcat, &theFile, timestrc, timestra, timestrm); | 
|---|
|  | 1118 | } | 
|---|
| [131] | 1119 | /* Quarantine file according to configured method | 
|---|
|  | 1120 | */ | 
|---|
|  | 1121 | if (ShSuidchkQEnable == S_TRUE) | 
|---|
|  | 1122 | { | 
|---|
|  | 1123 | switch (ShSuidchkQMethod) | 
|---|
|  | 1124 | { | 
|---|
|  | 1125 | case SH_Q_DELETE: | 
|---|
|  | 1126 | sh_q_delete(theFile.fullpath); | 
|---|
|  | 1127 | break; | 
|---|
|  | 1128 | case SH_Q_CHANGEPERM: | 
|---|
|  | 1129 | sh_q_changeperm(theFile.fullpath); | 
|---|
|  | 1130 | break; | 
|---|
|  | 1131 | case SH_Q_MOVE: | 
|---|
|  | 1132 | sh_q_move(theFile.fullpath, &theFile, timestrc, timestra, timestrm); | 
|---|
|  | 1133 | break; | 
|---|
|  | 1134 | default: | 
|---|
|  | 1135 | sh_error_handle (ShSuidchkSeverity, FIL__, | 
|---|
|  | 1136 | __LINE__, 0, MSG_SUID_QREPORT, | 
|---|
|  | 1137 | _("Bad quarantine method"), tmp); | 
|---|
|  | 1138 | break; | 
|---|
|  | 1139 | } | 
|---|
|  | 1140 | } | 
|---|
|  | 1141 | else | 
|---|
|  | 1142 | { | 
|---|
|  | 1143 | /* 1.8.1 push file to in-memory database | 
|---|
|  | 1144 | */ | 
|---|
|  | 1145 | (void) sh_hash_compdata (SH_LEVEL_READONLY, | 
|---|
|  | 1146 | &theFile, fileHash, | 
|---|
|  | 1147 | _("[SuidCheck]"), | 
|---|
|  | 1148 | ShSuidchkSeverity); | 
|---|
|  | 1149 |  | 
|---|
|  | 1150 | sh_hash_addflag(tmpcat, SH_FFLAG_SUIDCHK); | 
|---|
|  | 1151 |  | 
|---|
|  | 1152 | } | 
|---|
|  | 1153 | } | 
|---|
|  | 1154 | else | 
|---|
|  | 1155 | { | 
|---|
|  | 1156 | /* File exists. Check for modifications. | 
|---|
|  | 1157 | */ | 
|---|
|  | 1158 | (void) sh_hash_compdata (SH_LEVEL_READONLY, | 
|---|
| [1] | 1159 | &theFile, fileHash, | 
|---|
| [131] | 1160 | _("[SuidCheck]"), | 
|---|
|  | 1161 | ShSuidchkSeverity); | 
|---|
|  | 1162 |  | 
|---|
|  | 1163 | sh_hash_addflag(tmpcat, SH_FFLAG_SUIDCHK); | 
|---|
|  | 1164 |  | 
|---|
|  | 1165 | } | 
|---|
|  | 1166 | } | 
|---|
|  | 1167 | } | 
|---|
|  | 1168 | SH_FREE(tmp); | 
|---|
| [167] | 1169 | if (theFile.attr_string) SH_FREE(theFile.attr_string); | 
|---|
|  | 1170 | if (theFile.link_path)   SH_FREE(theFile.link_path); | 
|---|
| [131] | 1171 | } | 
|---|
|  | 1172 | } | 
|---|
|  | 1173 | SH_FREE(tmpcat); | 
|---|
| [115] | 1174 |  | 
|---|
| [131] | 1175 |  | 
|---|
| [1] | 1176 | #ifdef HAVE_SCHED_YIELD | 
|---|
|  | 1177 | if (ShSuidchkYield == S_TRUE) | 
|---|
|  | 1178 | { | 
|---|
|  | 1179 | if (sched_yield() == -1) | 
|---|
|  | 1180 | { | 
|---|
|  | 1181 | status = errno; | 
|---|
|  | 1182 | sh_error_handle ((-1), FIL__, __LINE__, status, MSG_E_SUBGEN, | 
|---|
| [131] | 1183 | _("Failed to release time slice"), | 
|---|
| [1] | 1184 | _("sh_suidchk_check_internal") ); | 
|---|
|  | 1185 | } | 
|---|
|  | 1186 | } | 
|---|
|  | 1187 | #endif | 
|---|
| [131] | 1188 |  | 
|---|
|  | 1189 | dirlist = dirlist->next; | 
|---|
| [68] | 1190 |  | 
|---|
| [131] | 1191 | }  while (dirlist != NULL); | 
|---|
| [1] | 1192 |  | 
|---|
| [131] | 1193 |  | 
|---|
|  | 1194 | kill_sh_dirlist (dirlist_orig); | 
|---|
|  | 1195 |  | 
|---|
| [1] | 1196 | SL_RETURN( (0), _("sh_suidchk_check_internal")); | 
|---|
|  | 1197 | } | 
|---|
|  | 1198 |  | 
|---|
|  | 1199 | /************* | 
|---|
|  | 1200 | * | 
|---|
|  | 1201 | * module init | 
|---|
|  | 1202 | * | 
|---|
|  | 1203 | *************/ | 
|---|
| [140] | 1204 | int sh_suidchk_init (struct mod_type * arg) | 
|---|
| [1] | 1205 | { | 
|---|
| [140] | 1206 | (void) arg; | 
|---|
| [1] | 1207 | if (ShSuidchkActive == S_FALSE) | 
|---|
|  | 1208 | return (-1); | 
|---|
|  | 1209 |  | 
|---|
|  | 1210 | return (0); | 
|---|
|  | 1211 | } | 
|---|
|  | 1212 |  | 
|---|
|  | 1213 |  | 
|---|
|  | 1214 | /************* | 
|---|
|  | 1215 | * | 
|---|
|  | 1216 | * module cleanup | 
|---|
|  | 1217 | * | 
|---|
|  | 1218 | *************/ | 
|---|
|  | 1219 | int sh_suidchk_end () | 
|---|
|  | 1220 | { | 
|---|
|  | 1221 | return (0); | 
|---|
|  | 1222 | } | 
|---|
|  | 1223 |  | 
|---|
|  | 1224 |  | 
|---|
|  | 1225 | /************* | 
|---|
|  | 1226 | * | 
|---|
|  | 1227 | * module timer | 
|---|
|  | 1228 | * | 
|---|
|  | 1229 | *************/ | 
|---|
|  | 1230 | int sh_suidchk_timer (time_t tcurrent) | 
|---|
|  | 1231 | { | 
|---|
|  | 1232 | if (sh.flag.checkSum == SH_CHECK_INIT) | 
|---|
|  | 1233 | return -1; | 
|---|
|  | 1234 |  | 
|---|
|  | 1235 | /* One-shot (not daemon and not loop forever) | 
|---|
|  | 1236 | */ | 
|---|
|  | 1237 | if (sh.flag.isdaemon != S_TRUE && sh.flag.loop == S_FALSE) | 
|---|
|  | 1238 | return -1; | 
|---|
|  | 1239 |  | 
|---|
|  | 1240 | if (ShSuidchkSched != NULL) | 
|---|
|  | 1241 | { | 
|---|
|  | 1242 | return test_sched(ShSuidchkSched); | 
|---|
|  | 1243 | } | 
|---|
|  | 1244 | if ((time_t) (tcurrent - lastcheck) >= ShSuidchkInterval) | 
|---|
|  | 1245 | { | 
|---|
|  | 1246 | lastcheck  = tcurrent; | 
|---|
|  | 1247 | return (-1); | 
|---|
|  | 1248 | } | 
|---|
|  | 1249 | return 0; | 
|---|
|  | 1250 | } | 
|---|
|  | 1251 |  | 
|---|
|  | 1252 | /************* | 
|---|
|  | 1253 | * | 
|---|
|  | 1254 | * module check | 
|---|
|  | 1255 | * | 
|---|
|  | 1256 | *************/ | 
|---|
|  | 1257 |  | 
|---|
|  | 1258 | int sh_suidchk_check () | 
|---|
|  | 1259 | { | 
|---|
|  | 1260 | int status; | 
|---|
|  | 1261 |  | 
|---|
|  | 1262 | SL_ENTER(_("sh_suidchk_check")); | 
|---|
|  | 1263 |  | 
|---|
|  | 1264 | sh_error_handle (SH_ERR_NOTICE, FIL__, __LINE__, EINVAL, MSG_E_SUBGEN, | 
|---|
|  | 1265 | _("Checking for SUID programs"), | 
|---|
|  | 1266 | _("suidchk_check") ); | 
|---|
|  | 1267 |  | 
|---|
|  | 1268 | FileLimNow        = time(NULL); | 
|---|
|  | 1269 | FileLimStart      = FileLimNow; | 
|---|
|  | 1270 | FileLimNum        = 0; | 
|---|
|  | 1271 | FileLimTotal      = 0; | 
|---|
|  | 1272 |  | 
|---|
| [22] | 1273 | #ifdef SH_SUIDTESTDIR | 
|---|
|  | 1274 | status = sh_suidchk_check_internal (SH_SUIDTESTDIR); | 
|---|
|  | 1275 | #else | 
|---|
| [1] | 1276 | status = sh_suidchk_check_internal ("/"); | 
|---|
| [22] | 1277 | #endif | 
|---|
| [1] | 1278 |  | 
|---|
|  | 1279 | sh_error_handle ((-1), FIL__, __LINE__, EINVAL, MSG_SUID_SUMMARY, | 
|---|
|  | 1280 | FileLimTotal, | 
|---|
|  | 1281 | (long) (time(NULL) - FileLimStart) ); | 
|---|
|  | 1282 |  | 
|---|
|  | 1283 | SL_RETURN(status, _("sh_suidchk_check")); | 
|---|
|  | 1284 | } | 
|---|
|  | 1285 |  | 
|---|
|  | 1286 | /************* | 
|---|
|  | 1287 | * | 
|---|
|  | 1288 | * module setup | 
|---|
|  | 1289 | * | 
|---|
|  | 1290 | *************/ | 
|---|
|  | 1291 |  | 
|---|
| [68] | 1292 | int sh_suidchk_set_severity  (const char * c) | 
|---|
| [1] | 1293 | { | 
|---|
|  | 1294 | int retval; | 
|---|
|  | 1295 | char tmp[32]; | 
|---|
|  | 1296 |  | 
|---|
|  | 1297 | SL_ENTER(_("sh_suidchk_set_severity")); | 
|---|
|  | 1298 | tmp[0] = '='; tmp[1] = '\0'; | 
|---|
|  | 1299 | (void) sl_strlcat (tmp, c, 32); | 
|---|
|  | 1300 | retval = sh_error_set_level (tmp, &ShSuidchkSeverity); | 
|---|
|  | 1301 | SL_RETURN(retval, _("sh_suidchk_set_severity")); | 
|---|
|  | 1302 | } | 
|---|
|  | 1303 |  | 
|---|
| [68] | 1304 | int sh_suidchk_set_exclude (const char * c) | 
|---|
| [1] | 1305 | { | 
|---|
|  | 1306 | SL_ENTER(_("sh_suidchk_set_exclude")); | 
|---|
| [68] | 1307 |  | 
|---|
| [1] | 1308 | if (c == NULL || c[0] == '\0') | 
|---|
|  | 1309 | { | 
|---|
|  | 1310 | SL_RETURN(-1, _("sh_suidchk_set_exclude")); | 
|---|
|  | 1311 | } | 
|---|
|  | 1312 |  | 
|---|
|  | 1313 | if (0 == sl_strncmp(c, _("NULL"), 4)) | 
|---|
|  | 1314 | { | 
|---|
|  | 1315 | if (ShSuidchkExclude != NULL) | 
|---|
|  | 1316 | SH_FREE(ShSuidchkExclude); | 
|---|
|  | 1317 | ShSuidchkExclude = NULL; | 
|---|
|  | 1318 | SL_RETURN(0, _("sh_suidchk_set_exclude")); | 
|---|
|  | 1319 | } | 
|---|
|  | 1320 |  | 
|---|
|  | 1321 | if (ShSuidchkExclude != NULL) | 
|---|
|  | 1322 | SH_FREE(ShSuidchkExclude); | 
|---|
|  | 1323 |  | 
|---|
| [68] | 1324 | ShSuidchkExclude = sh_util_strdup (c); | 
|---|
|  | 1325 | ExcludeLen       = sl_strlen (ShSuidchkExclude); | 
|---|
|  | 1326 | if (ShSuidchkExclude[ExcludeLen-1] == '/') | 
|---|
| [1] | 1327 | { | 
|---|
| [68] | 1328 | ShSuidchkExclude[ExcludeLen-1] = '\0'; | 
|---|
| [55] | 1329 | ExcludeLen--; | 
|---|
| [1] | 1330 | } | 
|---|
|  | 1331 | SL_RETURN(0, _("sh_suidchk_set_exclude")); | 
|---|
|  | 1332 | } | 
|---|
|  | 1333 |  | 
|---|
| [68] | 1334 | int sh_suidchk_set_timer (const char * c) | 
|---|
| [1] | 1335 | { | 
|---|
|  | 1336 | long val; | 
|---|
|  | 1337 |  | 
|---|
|  | 1338 | SL_ENTER(_("sh_suidchk_set_timer")); | 
|---|
|  | 1339 |  | 
|---|
|  | 1340 | val = strtol (c, (char **)NULL, 10); | 
|---|
|  | 1341 | if (val <= 0) | 
|---|
|  | 1342 | sh_error_handle ((-1), FIL__, __LINE__, EINVAL, MSG_EINVALS, | 
|---|
|  | 1343 | _("suidchk timer"), c); | 
|---|
|  | 1344 |  | 
|---|
|  | 1345 | val = (val <= 0 ? 7200 : val); | 
|---|
|  | 1346 |  | 
|---|
|  | 1347 | ShSuidchkInterval = (time_t) val; | 
|---|
|  | 1348 | SL_RETURN( 0, _("sh_suidchk_set_timer")); | 
|---|
|  | 1349 | } | 
|---|
|  | 1350 |  | 
|---|
|  | 1351 |  | 
|---|
| [170] | 1352 | static void sh_suidchk_free_schedule (void) | 
|---|
| [1] | 1353 | { | 
|---|
|  | 1354 | sh_schedule_t * current = ShSuidchkSched; | 
|---|
|  | 1355 | sh_schedule_t * next    = NULL; | 
|---|
|  | 1356 |  | 
|---|
|  | 1357 | while (current != NULL) | 
|---|
|  | 1358 | { | 
|---|
|  | 1359 | next = current->next; | 
|---|
|  | 1360 | SH_FREE(current); | 
|---|
|  | 1361 | current = next; | 
|---|
|  | 1362 | } | 
|---|
|  | 1363 | ShSuidchkSched = NULL; | 
|---|
| [149] | 1364 | return; | 
|---|
| [1] | 1365 | } | 
|---|
|  | 1366 |  | 
|---|
| [149] | 1367 | int sh_suidchk_reconf () | 
|---|
|  | 1368 | { | 
|---|
|  | 1369 | sh_suidchk_free_schedule(); | 
|---|
|  | 1370 | set_defaults(); | 
|---|
| [150] | 1371 | return 0; | 
|---|
| [149] | 1372 | } | 
|---|
|  | 1373 |  | 
|---|
| [68] | 1374 | int sh_suidchk_set_schedule (const char * str) | 
|---|
| [1] | 1375 | { | 
|---|
|  | 1376 | int status; | 
|---|
|  | 1377 | sh_schedule_t * newSched = NULL; | 
|---|
|  | 1378 |  | 
|---|
|  | 1379 | SL_ENTER(_("sh_suidchk_set_schedule")); | 
|---|
|  | 1380 |  | 
|---|
|  | 1381 | /* | 
|---|
|  | 1382 | if (ShSuidchkSched != NULL) | 
|---|
|  | 1383 | { | 
|---|
|  | 1384 | SH_FREE(ShSuidchkSched); | 
|---|
|  | 1385 | ShSuidchkSched = NULL; | 
|---|
|  | 1386 | } | 
|---|
|  | 1387 | */ | 
|---|
|  | 1388 |  | 
|---|
|  | 1389 | if (0 == sl_strncmp(str, _("NULL"), 4)) | 
|---|
|  | 1390 | { | 
|---|
|  | 1391 | (void) sh_suidchk_free_schedule (); | 
|---|
|  | 1392 | return 0; | 
|---|
|  | 1393 | } | 
|---|
|  | 1394 |  | 
|---|
|  | 1395 | newSched = SH_ALLOC(sizeof(sh_schedule_t)); | 
|---|
|  | 1396 | status = create_sched(str, newSched); | 
|---|
|  | 1397 | if (status != 0) | 
|---|
|  | 1398 | { | 
|---|
|  | 1399 | SH_FREE(newSched); | 
|---|
|  | 1400 | newSched = NULL; | 
|---|
|  | 1401 | } | 
|---|
|  | 1402 | else | 
|---|
|  | 1403 | { | 
|---|
|  | 1404 | newSched->next = ShSuidchkSched; | 
|---|
|  | 1405 | ShSuidchkSched = newSched; | 
|---|
|  | 1406 | } | 
|---|
|  | 1407 | SL_RETURN( status, _("sh_suidchk_set_schedule")); | 
|---|
|  | 1408 | } | 
|---|
|  | 1409 |  | 
|---|
|  | 1410 |  | 
|---|
|  | 1411 |  | 
|---|
| [68] | 1412 | int sh_suidchk_set_fps (const char * c) | 
|---|
| [1] | 1413 | { | 
|---|
|  | 1414 | long val; | 
|---|
|  | 1415 |  | 
|---|
|  | 1416 | SL_ENTER(_("sh_suidchk_set_fps")); | 
|---|
|  | 1417 |  | 
|---|
|  | 1418 | val = strtol (c, (char **)NULL, 10); | 
|---|
|  | 1419 | if (val < 0) | 
|---|
|  | 1420 | sh_error_handle ((-1), FIL__, __LINE__, EINVAL, MSG_EINVALS, | 
|---|
|  | 1421 | _("suidchk fps"), c); | 
|---|
|  | 1422 |  | 
|---|
|  | 1423 | val = (val < 0 ? 0 : val); | 
|---|
|  | 1424 |  | 
|---|
|  | 1425 | ShSuidchkFps = val; | 
|---|
|  | 1426 | SL_RETURN( 0, _("sh_suidchk_set_fps")); | 
|---|
|  | 1427 | } | 
|---|
|  | 1428 |  | 
|---|
| [68] | 1429 | int sh_suidchk_set_yield (const char * c) | 
|---|
| [1] | 1430 | { | 
|---|
|  | 1431 | int i; | 
|---|
|  | 1432 | SL_ENTER(_("sh_suidchk_set_yield")); | 
|---|
|  | 1433 | #ifdef HAVE_SCHED_YIELD | 
|---|
|  | 1434 | i = sh_util_flagval(c, &ShSuidchkYield); | 
|---|
|  | 1435 | #else | 
|---|
|  | 1436 | (void) c; /* cast to void to avoid compiler warning */ | 
|---|
|  | 1437 | i = -1; | 
|---|
|  | 1438 | #endif | 
|---|
|  | 1439 | SL_RETURN(i, _("sh_suidchk_set_yield")); | 
|---|
|  | 1440 | } | 
|---|
|  | 1441 |  | 
|---|
| [68] | 1442 | int sh_suidchk_set_activate (const char * c) | 
|---|
| [1] | 1443 | { | 
|---|
|  | 1444 | int i; | 
|---|
|  | 1445 | SL_ENTER(_("sh_suidchk_set_activate")); | 
|---|
|  | 1446 | i = sh_util_flagval(c, &ShSuidchkActive); | 
|---|
|  | 1447 | SL_RETURN(i, _("sh_suidchk_set_activate")); | 
|---|
|  | 1448 | } | 
|---|
|  | 1449 |  | 
|---|
| [119] | 1450 | int sh_suidchk_set_nosuid (const char * c) | 
|---|
|  | 1451 | { | 
|---|
|  | 1452 | int i; | 
|---|
|  | 1453 | SL_ENTER(_("sh_suidchk_set_nosuid")); | 
|---|
|  | 1454 | i = sh_util_flagval(c, &ShSuidchkNosuid); | 
|---|
|  | 1455 | SL_RETURN(i, _("sh_suidchk_set_nosuid")); | 
|---|
|  | 1456 | } | 
|---|
|  | 1457 |  | 
|---|
| [68] | 1458 | int sh_suidchk_set_quarantine (const char * c) | 
|---|
| [1] | 1459 | { | 
|---|
|  | 1460 | int i; | 
|---|
|  | 1461 | SL_ENTER(_("sh_suidchk_set_quarantine")); | 
|---|
|  | 1462 | i = sh_util_flagval(c, &ShSuidchkQEnable); | 
|---|
|  | 1463 | SL_RETURN(i, _("sh_suidchk_set_quarantine")); | 
|---|
|  | 1464 | } | 
|---|
|  | 1465 |  | 
|---|
| [68] | 1466 | int sh_suidchk_set_qdelete (const char * c) | 
|---|
| [1] | 1467 | { | 
|---|
|  | 1468 | int i; | 
|---|
|  | 1469 | SL_ENTER(_("sh_suidchk_set_qdelete")); | 
|---|
|  | 1470 | i = sh_util_flagval(c, &ShSuidchkQDelete); | 
|---|
|  | 1471 | SL_RETURN(i, _("sh_suidchk_set_qdelete")); | 
|---|
|  | 1472 | } | 
|---|
|  | 1473 |  | 
|---|
| [68] | 1474 | int sh_suidchk_set_qmethod (const char * c) | 
|---|
| [1] | 1475 | { | 
|---|
|  | 1476 | long val; | 
|---|
|  | 1477 | int  ret = 0; | 
|---|
| [22] | 1478 | struct stat buf; | 
|---|
| [1] | 1479 |  | 
|---|
|  | 1480 | SL_ENTER(_("sh_suidchk_set_qmethod")); | 
|---|
|  | 1481 |  | 
|---|
|  | 1482 | val = strtol (c, (char **)NULL, 10); | 
|---|
|  | 1483 | if (val < 0) | 
|---|
|  | 1484 | { | 
|---|
|  | 1485 | sh_error_handle ((-1), FIL__, __LINE__, EINVAL, MSG_EINVALS, | 
|---|
|  | 1486 | _("suidchk qmethod"), c); | 
|---|
|  | 1487 | ret = -1; | 
|---|
|  | 1488 | } | 
|---|
|  | 1489 | else | 
|---|
|  | 1490 | { | 
|---|
|  | 1491 | switch (val) | 
|---|
|  | 1492 | { | 
|---|
|  | 1493 | case SH_Q_DELETE: | 
|---|
|  | 1494 | ShSuidchkQMethod = SH_Q_DELETE; | 
|---|
|  | 1495 | break; | 
|---|
|  | 1496 | case SH_Q_CHANGEPERM: | 
|---|
|  | 1497 | ShSuidchkQMethod = SH_Q_CHANGEPERM; | 
|---|
|  | 1498 | break; | 
|---|
|  | 1499 | case SH_Q_MOVE: | 
|---|
| [22] | 1500 | if (retry_stat (FIL__, __LINE__, DEFAULT_QDIR, &buf) != 0) | 
|---|
| [1] | 1501 | { | 
|---|
|  | 1502 | if (mkdir (DEFAULT_QDIR, 0750) == -1) | 
|---|
|  | 1503 | { | 
|---|
|  | 1504 | sh_error_handle ((-1), FIL__, __LINE__, EINVAL, | 
|---|
|  | 1505 | MSG_SUID_ERROR, | 
|---|
|  | 1506 | _("Unable to create quarantine directory")); | 
|---|
|  | 1507 | } | 
|---|
|  | 1508 | } | 
|---|
|  | 1509 | ShSuidchkQMethod = SH_Q_MOVE; | 
|---|
|  | 1510 | break; | 
|---|
|  | 1511 | default: | 
|---|
|  | 1512 | sh_error_handle ((-1), FIL__, __LINE__, EINVAL, MSG_EINVALS, | 
|---|
|  | 1513 | _("suidchk qmethod"), c); | 
|---|
|  | 1514 | ShSuidchkQMethod = -1; | 
|---|
|  | 1515 | ret = -1; | 
|---|
|  | 1516 | break; | 
|---|
|  | 1517 | } | 
|---|
|  | 1518 | } | 
|---|
|  | 1519 |  | 
|---|
|  | 1520 | SL_RETURN( ret, _("sh_suidchk_set_qmethod")); | 
|---|
|  | 1521 | } | 
|---|
|  | 1522 |  | 
|---|
|  | 1523 | #if defined(FSTYPE_STATFS) || defined(FSTYPE_AIX_STATFS) | 
|---|
|  | 1524 | /* dirname.c -- return all but the last element in a path | 
|---|
|  | 1525 | Copyright (C) 1990 Free Software Foundation, Inc. | 
|---|
|  | 1526 |  | 
|---|
|  | 1527 | This program is free software; you can redistribute it and/or modify | 
|---|
|  | 1528 | it under the terms of the GNU General Public License as published by | 
|---|
|  | 1529 | the Free Software Foundation; either version 2, or (at your option) | 
|---|
|  | 1530 | any later version. | 
|---|
|  | 1531 |  | 
|---|
|  | 1532 | This program is distributed in the hope that it will be useful, | 
|---|
|  | 1533 | but WITHOUT ANY WARRANTY; without even the implied warranty of | 
|---|
|  | 1534 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 
|---|
|  | 1535 | GNU General Public License for more details. | 
|---|
|  | 1536 |  | 
|---|
|  | 1537 | You should have received a copy of the GNU General Public License | 
|---|
|  | 1538 | along with this program; if not, write to the Free Software Foundation, | 
|---|
|  | 1539 | Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */ | 
|---|
|  | 1540 |  | 
|---|
|  | 1541 | /* Return the leading directories part of PATH, | 
|---|
|  | 1542 | allocated with malloc.  If out of memory, return 0. | 
|---|
|  | 1543 | Assumes that trailing slashes have already been | 
|---|
|  | 1544 | removed.  */ | 
|---|
|  | 1545 |  | 
|---|
|  | 1546 | char * sh_dirname (const char * path) | 
|---|
|  | 1547 | { | 
|---|
|  | 1548 | char *newpath; | 
|---|
|  | 1549 | char *slash; | 
|---|
|  | 1550 | int length;                   /* Length of result, not including NUL.  */ | 
|---|
|  | 1551 |  | 
|---|
|  | 1552 | slash = strrchr (path, '/'); | 
|---|
|  | 1553 | if (slash == NULL) | 
|---|
|  | 1554 | { | 
|---|
|  | 1555 | /* File is in the current directory.  */ | 
|---|
|  | 1556 | path = "."; | 
|---|
|  | 1557 | length = 1; | 
|---|
|  | 1558 | } | 
|---|
|  | 1559 | else | 
|---|
|  | 1560 | { | 
|---|
|  | 1561 | /* Remove any trailing slashes from the result.  */ | 
|---|
|  | 1562 | while (slash > path && *slash == '/') | 
|---|
|  | 1563 | --slash; | 
|---|
|  | 1564 |  | 
|---|
|  | 1565 | length = slash - path + 1; | 
|---|
|  | 1566 | } | 
|---|
|  | 1567 | newpath = (char *) SH_ALLOC (length + 1); | 
|---|
|  | 1568 | if (newpath == NULL) | 
|---|
|  | 1569 | return NULL; | 
|---|
|  | 1570 | strncpy (newpath, path, length); | 
|---|
|  | 1571 | newpath[length] = '\0'; | 
|---|
|  | 1572 | return newpath; | 
|---|
|  | 1573 | } | 
|---|
|  | 1574 | /* #ifdef FSTYPE_STATFS */ | 
|---|
|  | 1575 | #endif | 
|---|
|  | 1576 |  | 
|---|
|  | 1577 | /* fstype.c -- determine type of filesystems that files are on | 
|---|
|  | 1578 | Copyright (C) 1990, 91, 92, 93, 94 Free Software Foundation, Inc. | 
|---|
|  | 1579 |  | 
|---|
|  | 1580 | This program is free software; you can redistribute it and/or modify | 
|---|
|  | 1581 | it under the terms of the GNU General Public License as published by | 
|---|
|  | 1582 | the Free Software Foundation; either version 2, or (at your option) | 
|---|
|  | 1583 | any later version. | 
|---|
|  | 1584 |  | 
|---|
|  | 1585 | This program is distributed in the hope that it will be useful, | 
|---|
|  | 1586 | but WITHOUT ANY WARRANTY; without even the implied warranty of | 
|---|
|  | 1587 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 
|---|
|  | 1588 | GNU General Public License for more details. | 
|---|
|  | 1589 |  | 
|---|
|  | 1590 | You should have received a copy of the GNU General Public License | 
|---|
|  | 1591 | along with this program; if not, write to the Free Software | 
|---|
|  | 1592 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */ | 
|---|
|  | 1593 |  | 
|---|
|  | 1594 | /* Written by David MacKenzie <djm@gnu.ai.mit.edu>. */ | 
|---|
|  | 1595 |  | 
|---|
|  | 1596 | /* Modified by R. Wichmann: | 
|---|
|  | 1597 | - replaced error()   by sh_error_handle() | 
|---|
|  | 1598 | - replaced xstrdup() by sl_strdup() | 
|---|
|  | 1599 | - replaced strstr()  by sl_strstr() | 
|---|
|  | 1600 | - some additions to recognize nosuid fs | 
|---|
|  | 1601 | */ | 
|---|
|  | 1602 |  | 
|---|
|  | 1603 | /* modetype.h -- file type bits definitions for POSIX systems | 
|---|
|  | 1604 | Requires sys/types.h sys/stat.h. | 
|---|
|  | 1605 | Copyright (C) 1990 Free Software Foundation, Inc. | 
|---|
|  | 1606 |  | 
|---|
|  | 1607 | This program is free software; you can redistribute it and/or modify | 
|---|
|  | 1608 | it under the terms of the GNU General Public License as published by | 
|---|
|  | 1609 | the Free Software Foundation; either version 2, or (at your option) | 
|---|
|  | 1610 | any later version. | 
|---|
|  | 1611 |  | 
|---|
|  | 1612 | This program is distributed in the hope that it will be useful, | 
|---|
|  | 1613 | but WITHOUT ANY WARRANTY; without even the implied warranty of | 
|---|
|  | 1614 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 
|---|
|  | 1615 | GNU General Public License for more details. | 
|---|
|  | 1616 |  | 
|---|
|  | 1617 | You should have received a copy of the GNU General Public License | 
|---|
|  | 1618 | along with this program; if not, write to the Free Software | 
|---|
|  | 1619 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */ | 
|---|
|  | 1620 |  | 
|---|
|  | 1621 | /* POSIX.1 doesn't mention the S_IFMT bits; instead, it uses S_IStype | 
|---|
|  | 1622 | test macros.  To make storing file types more convenient, define | 
|---|
|  | 1623 | them; the values don't need to correspond to what the kernel uses, | 
|---|
|  | 1624 | because of the way we use them. */ | 
|---|
|  | 1625 | #ifndef S_IFMT                  /* Doesn't have traditional Unix macros. */ | 
|---|
|  | 1626 | #define S_IFBLK 1 | 
|---|
|  | 1627 | #define S_IFCHR 2 | 
|---|
|  | 1628 | #define S_IFDIR 4 | 
|---|
|  | 1629 | #define S_IFREG 8 | 
|---|
|  | 1630 | #ifdef S_ISLNK | 
|---|
|  | 1631 | #define S_IFLNK 16 | 
|---|
|  | 1632 | #endif | 
|---|
|  | 1633 | #ifdef S_ISFIFO | 
|---|
|  | 1634 | #define S_IFIFO 32 | 
|---|
|  | 1635 | #endif | 
|---|
|  | 1636 | #ifdef S_ISSOCK | 
|---|
|  | 1637 | #define S_IFSOCK 64 | 
|---|
|  | 1638 | #endif | 
|---|
|  | 1639 | #endif /* !S_IFMT */ | 
|---|
|  | 1640 |  | 
|---|
|  | 1641 | #ifdef STAT_MACROS_BROKEN | 
|---|
|  | 1642 | #undef S_ISBLK | 
|---|
|  | 1643 | #undef S_ISCHR | 
|---|
|  | 1644 | #undef S_ISDIR | 
|---|
|  | 1645 | #undef S_ISREG | 
|---|
|  | 1646 | #undef S_ISFIFO | 
|---|
|  | 1647 | #undef S_ISLNK | 
|---|
|  | 1648 | #undef S_ISSOCK | 
|---|
|  | 1649 | #undef S_ISMPB | 
|---|
|  | 1650 | #undef S_ISMPC | 
|---|
|  | 1651 | #undef S_ISNWK | 
|---|
|  | 1652 | #endif | 
|---|
|  | 1653 |  | 
|---|
|  | 1654 | /* Do the reverse: define the POSIX.1 macros for traditional Unix systems | 
|---|
|  | 1655 | that don't have them.  */ | 
|---|
|  | 1656 | #if !defined(S_ISBLK) && defined(S_IFBLK) | 
|---|
|  | 1657 | #define S_ISBLK(m) (((m) & S_IFMT) == S_IFBLK) | 
|---|
|  | 1658 | #endif | 
|---|
|  | 1659 | #if !defined(S_ISCHR) && defined(S_IFCHR) | 
|---|
|  | 1660 | #define S_ISCHR(m) (((m) & S_IFMT) == S_IFCHR) | 
|---|
|  | 1661 | #endif | 
|---|
|  | 1662 | #if !defined(S_ISDIR) && defined(S_IFDIR) | 
|---|
|  | 1663 | #define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR) | 
|---|
|  | 1664 | #endif | 
|---|
|  | 1665 | #if !defined(S_ISREG) && defined(S_IFREG) | 
|---|
|  | 1666 | #define S_ISREG(m) (((m) & S_IFMT) == S_IFREG) | 
|---|
|  | 1667 | #endif | 
|---|
|  | 1668 | #if !defined(S_ISFIFO) && defined(S_IFIFO) | 
|---|
|  | 1669 | #define S_ISFIFO(m) (((m) & S_IFMT) == S_IFIFO) | 
|---|
|  | 1670 | #endif | 
|---|
|  | 1671 | #if !defined(S_ISLNK) && defined(S_IFLNK) | 
|---|
|  | 1672 | #define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK) | 
|---|
|  | 1673 | #endif | 
|---|
|  | 1674 | #if !defined(S_ISSOCK) && defined(S_IFSOCK) | 
|---|
|  | 1675 | #define S_ISSOCK(m) (((m) & S_IFMT) == S_IFSOCK) | 
|---|
|  | 1676 | #endif | 
|---|
|  | 1677 | #if !defined(S_ISMPB) && defined(S_IFMPB) /* V7 */ | 
|---|
|  | 1678 | #define S_ISMPB(m) (((m) & S_IFMT) == S_IFMPB) | 
|---|
|  | 1679 | #define S_ISMPC(m) (((m) & S_IFMT) == S_IFMPC) | 
|---|
|  | 1680 | #endif | 
|---|
|  | 1681 | #if !defined(S_ISNWK) && defined(S_IFNWK) /* HP/UX */ | 
|---|
|  | 1682 | #define S_ISNWK(m) (((m) & S_IFMT) == S_IFNWK) | 
|---|
|  | 1683 | #endif | 
|---|
|  | 1684 |  | 
|---|
|  | 1685 |  | 
|---|
|  | 1686 | static char *filesystem_type_uncached (char *path, char *relpath, | 
|---|
|  | 1687 | struct stat *statp); | 
|---|
|  | 1688 |  | 
|---|
|  | 1689 | #ifdef FSTYPE_MNTENT            /* 4.3BSD etc.  */ | 
|---|
| [199] | 1690 | static int xatoi (const char *cp); | 
|---|
| [1] | 1691 | #endif | 
|---|
|  | 1692 |  | 
|---|
|  | 1693 | #ifdef FSTYPE_MNTENT            /* 4.3BSD, SunOS, HP-UX, Dynix, Irix.  */ | 
|---|
|  | 1694 | #include <mntent.h> | 
|---|
|  | 1695 | #if !defined(MOUNTED) | 
|---|
|  | 1696 | # if defined(MNT_MNTTAB)        /* HP-UX.  */ | 
|---|
|  | 1697 | #  define MOUNTED MNT_MNTTAB | 
|---|
|  | 1698 | # endif | 
|---|
|  | 1699 | # if defined(MNTTABNAME)        /* Dynix.  */ | 
|---|
|  | 1700 | #  define MOUNTED MNTTABNAME | 
|---|
|  | 1701 | # endif | 
|---|
|  | 1702 | #endif | 
|---|
|  | 1703 | #endif | 
|---|
|  | 1704 |  | 
|---|
|  | 1705 | #ifdef FSTYPE_GETMNT            /* Ultrix.  */ | 
|---|
|  | 1706 | #include <sys/param.h> | 
|---|
|  | 1707 | #include <sys/mount.h> | 
|---|
|  | 1708 | #include <sys/fs_types.h> | 
|---|
|  | 1709 | #endif | 
|---|
|  | 1710 |  | 
|---|
|  | 1711 | #ifdef FSTYPE_USG_STATFS        /* SVR3.  */ | 
|---|
|  | 1712 | #include <sys/statfs.h> | 
|---|
|  | 1713 | #include <sys/fstyp.h> | 
|---|
|  | 1714 | #endif | 
|---|
|  | 1715 |  | 
|---|
|  | 1716 | #ifdef FSTYPE_STATVFS           /* SVR4.  */ | 
|---|
|  | 1717 | #include <sys/statvfs.h> | 
|---|
|  | 1718 | #include <sys/fstyp.h> | 
|---|
|  | 1719 | #endif | 
|---|
|  | 1720 |  | 
|---|
|  | 1721 | #ifdef FSTYPE_STATFS            /* 4.4BSD.  */ | 
|---|
|  | 1722 | #include <sys/param.h>          /* NetBSD needs this.  */ | 
|---|
|  | 1723 | #include <sys/mount.h> | 
|---|
|  | 1724 |  | 
|---|
|  | 1725 | #ifndef MFSNAMELEN              /* NetBSD defines this.  */ | 
|---|
|  | 1726 | static char * | 
|---|
|  | 1727 | fstype_to_string (t) | 
|---|
|  | 1728 | short t; | 
|---|
|  | 1729 | { | 
|---|
|  | 1730 | #ifdef INITMOUNTNAMES           /* Defined in 4.4BSD, not in NET/2.  */ | 
|---|
|  | 1731 | static char *mn[] = INITMOUNTNAMES; | 
|---|
|  | 1732 | if (t >= 0 && t <= MOUNT_MAXTYPE) | 
|---|
|  | 1733 | return mn[t]; | 
|---|
|  | 1734 | else | 
|---|
|  | 1735 | return "?"; | 
|---|
|  | 1736 | #else /* !INITMOUNTNAMES */ | 
|---|
|  | 1737 | switch (t) | 
|---|
|  | 1738 | { | 
|---|
|  | 1739 | case MOUNT_UFS: | 
|---|
|  | 1740 | return _("ufs"); | 
|---|
|  | 1741 | case MOUNT_NFS: | 
|---|
|  | 1742 | return _("nfs"); | 
|---|
|  | 1743 | #ifdef MOUNT_PC | 
|---|
|  | 1744 | case MOUNT_PC: | 
|---|
|  | 1745 | return _("pc"); | 
|---|
|  | 1746 | #endif | 
|---|
|  | 1747 | #ifdef MOUNT_MFS | 
|---|
|  | 1748 | case MOUNT_MFS: | 
|---|
|  | 1749 | return _("mfs"); | 
|---|
|  | 1750 | #endif | 
|---|
|  | 1751 | #ifdef MOUNT_LO | 
|---|
|  | 1752 | case MOUNT_LO: | 
|---|
|  | 1753 | return _("lofs"); | 
|---|
|  | 1754 | #endif | 
|---|
|  | 1755 | #ifdef MOUNT_TFS | 
|---|
|  | 1756 | case MOUNT_TFS: | 
|---|
|  | 1757 | return _("tfs"); | 
|---|
|  | 1758 | #endif | 
|---|
|  | 1759 | #ifdef MOUNT_TMP | 
|---|
|  | 1760 | case MOUNT_TMP: | 
|---|
|  | 1761 | return _("tmp"); | 
|---|
|  | 1762 | #endif | 
|---|
|  | 1763 | #ifdef MOUNT_MSDOS | 
|---|
|  | 1764 | case MOUNT_MSDOS: | 
|---|
|  | 1765 | return _("msdos"); | 
|---|
|  | 1766 | #endif | 
|---|
|  | 1767 | #ifdef MOUNT_ISO9660 | 
|---|
|  | 1768 | case MOUNT_ISO9660: | 
|---|
|  | 1769 | return _("iso9660fs"); | 
|---|
|  | 1770 | #endif | 
|---|
|  | 1771 | default: | 
|---|
|  | 1772 | return "?"; | 
|---|
|  | 1773 | } | 
|---|
|  | 1774 | #endif /* !INITMOUNTNAMES */ | 
|---|
|  | 1775 | } | 
|---|
|  | 1776 | #endif /* !MFSNAMELEN */ | 
|---|
|  | 1777 | #endif /* FSTYPE_STATFS */ | 
|---|
|  | 1778 |  | 
|---|
|  | 1779 | #ifdef FSTYPE_AIX_STATFS        /* AIX.  */ | 
|---|
|  | 1780 | #include <sys/vmount.h> | 
|---|
|  | 1781 | #include <sys/statfs.h> | 
|---|
|  | 1782 |  | 
|---|
|  | 1783 | #define FSTYPE_STATFS           /* Otherwise like 4.4BSD.  */ | 
|---|
|  | 1784 | #define f_type f_vfstype | 
|---|
|  | 1785 |  | 
|---|
|  | 1786 | static char * | 
|---|
|  | 1787 | fstype_to_string (t) | 
|---|
|  | 1788 | short t; | 
|---|
|  | 1789 | { | 
|---|
|  | 1790 | switch (t) | 
|---|
|  | 1791 | { | 
|---|
|  | 1792 | case MNT_AIX: | 
|---|
|  | 1793 | return _("aix");  /* AIX 4.3: NFS filesystems are actually MNT_AIX. */ | 
|---|
|  | 1794 | #ifdef MNT_NAMEFS | 
|---|
|  | 1795 | case MNT_NAMEFS: | 
|---|
|  | 1796 | return _("namefs"); | 
|---|
|  | 1797 | #endif | 
|---|
|  | 1798 | case MNT_NFS: | 
|---|
|  | 1799 | return _("nfs"); | 
|---|
|  | 1800 | case MNT_JFS: | 
|---|
|  | 1801 | return _("jfs"); | 
|---|
|  | 1802 | case MNT_CDROM: | 
|---|
|  | 1803 | return _("cdrom"); | 
|---|
|  | 1804 | #ifdef MNT_PROCFS | 
|---|
|  | 1805 | case MNT_PROCFS: | 
|---|
|  | 1806 | return _("procfs"); | 
|---|
|  | 1807 | #endif | 
|---|
|  | 1808 | #ifdef MNT_SFS | 
|---|
|  | 1809 | case MNT_SFS: | 
|---|
|  | 1810 | return _("sfs"); | 
|---|
|  | 1811 | #endif | 
|---|
|  | 1812 | #ifdef MNT_CACHEFS | 
|---|
|  | 1813 | case MNT_CACHEFS: | 
|---|
|  | 1814 | return _("cachefs"); | 
|---|
|  | 1815 | #endif | 
|---|
|  | 1816 | #ifdef MNT_NFS3 | 
|---|
|  | 1817 | case MNT_NFS3: | 
|---|
|  | 1818 | return _("nfs3"); | 
|---|
|  | 1819 | #endif | 
|---|
|  | 1820 | #ifdef MNT_AUTOFS | 
|---|
|  | 1821 | case MNT_AUTOFS: | 
|---|
|  | 1822 | return _("autofs"); | 
|---|
|  | 1823 | #endif | 
|---|
|  | 1824 | #ifdef MNT_VXFS | 
|---|
|  | 1825 | case MNT_VXFS: | 
|---|
|  | 1826 | return _("vxfs"); | 
|---|
|  | 1827 | #endif | 
|---|
|  | 1828 | #ifdef MNT_VXODM | 
|---|
|  | 1829 | case MNT_VXODM: | 
|---|
|  | 1830 | return _("veritasfs"); | 
|---|
|  | 1831 | #endif | 
|---|
|  | 1832 | #ifdef MNT_UDF | 
|---|
|  | 1833 | case MNT_UDF: | 
|---|
|  | 1834 | return _("udfs"); | 
|---|
|  | 1835 | #endif | 
|---|
|  | 1836 | #ifdef MNT_NFS4 | 
|---|
|  | 1837 | case MNT_NFS4: | 
|---|
|  | 1838 | return _("nfs4"); | 
|---|
|  | 1839 | #endif | 
|---|
|  | 1840 | #ifdef MNT_RFS4 | 
|---|
|  | 1841 | case MNT_RFS4: | 
|---|
|  | 1842 | return _("nfs4"); | 
|---|
|  | 1843 | #endif | 
|---|
|  | 1844 | #ifdef MNT_CIFS | 
|---|
|  | 1845 | case MNT_CIFS: | 
|---|
|  | 1846 | return _("cifs"); | 
|---|
|  | 1847 | #endif | 
|---|
|  | 1848 | default: | 
|---|
|  | 1849 | return "?"; | 
|---|
|  | 1850 | } | 
|---|
|  | 1851 | } | 
|---|
|  | 1852 | #endif /* FSTYPE_AIX_STATFS */ | 
|---|
|  | 1853 |  | 
|---|
|  | 1854 | #ifdef AFS | 
|---|
|  | 1855 | #include <netinet/in.h> | 
|---|
|  | 1856 | #include <afs/venus.h> | 
|---|
|  | 1857 | #if __STDC__ | 
|---|
|  | 1858 | /* On SunOS 4, afs/vice.h defines this to rely on a pre-ANSI cpp.  */ | 
|---|
|  | 1859 | #undef _VICEIOCTL | 
|---|
|  | 1860 | #define _VICEIOCTL(id)  ((unsigned int ) _IOW('V', id, struct ViceIoctl)) | 
|---|
|  | 1861 | #endif | 
|---|
|  | 1862 | #ifndef _IOW | 
|---|
|  | 1863 | /* AFS on Solaris 2.3 doesn't get this definition.  */ | 
|---|
|  | 1864 | #include <sys/ioccom.h> | 
|---|
|  | 1865 | #endif | 
|---|
|  | 1866 |  | 
|---|
|  | 1867 | static int | 
|---|
|  | 1868 | in_afs (path) | 
|---|
|  | 1869 | char *path; | 
|---|
|  | 1870 | { | 
|---|
|  | 1871 | static char space[2048]; | 
|---|
|  | 1872 | struct ViceIoctl vi; | 
|---|
|  | 1873 |  | 
|---|
|  | 1874 | vi.in_size = 0; | 
|---|
|  | 1875 | vi.out_size = sizeof (space); | 
|---|
|  | 1876 | vi.out = space; | 
|---|
|  | 1877 |  | 
|---|
|  | 1878 | if (pioctl (path, VIOC_FILE_CELL_NAME, &vi, 1) | 
|---|
|  | 1879 | && (errno == EINVAL || errno == ENOENT)) | 
|---|
|  | 1880 | return 0; | 
|---|
|  | 1881 | return 1; | 
|---|
|  | 1882 | } | 
|---|
|  | 1883 | #endif /* AFS */ | 
|---|
|  | 1884 |  | 
|---|
|  | 1885 | /* Nonzero if the current filesystem's type is known.  */ | 
|---|
|  | 1886 | static int fstype_known = 0; | 
|---|
|  | 1887 |  | 
|---|
|  | 1888 | /* Return a static string naming the type of filesystem that the file PATH, | 
|---|
|  | 1889 | described by STATP, is on. | 
|---|
|  | 1890 | RELPATH is the file name relative to the current directory. | 
|---|
|  | 1891 | Return "unknown" if its filesystem type is unknown.  */ | 
|---|
|  | 1892 |  | 
|---|
|  | 1893 | static char * | 
|---|
|  | 1894 | filesystem_type (char * path, char * relpath, struct stat * statp) | 
|---|
|  | 1895 | { | 
|---|
|  | 1896 | static char *current_fstype = NULL; | 
|---|
|  | 1897 | static dev_t current_dev; | 
|---|
|  | 1898 |  | 
|---|
|  | 1899 | if (current_fstype != NULL) | 
|---|
|  | 1900 | { | 
|---|
|  | 1901 | if ((0 != fstype_known) && statp->st_dev == current_dev) | 
|---|
|  | 1902 | return current_fstype;  /* Cached value.  */ | 
|---|
|  | 1903 | SH_FREE (current_fstype); | 
|---|
|  | 1904 | } | 
|---|
|  | 1905 | current_dev = statp->st_dev; | 
|---|
|  | 1906 | current_fstype = filesystem_type_uncached (path, relpath, statp); | 
|---|
|  | 1907 | return current_fstype; | 
|---|
|  | 1908 | } | 
|---|
|  | 1909 |  | 
|---|
|  | 1910 | /* Return a newly allocated string naming the type of filesystem that the | 
|---|
|  | 1911 | file PATH, described by STATP, is on. | 
|---|
|  | 1912 | RELPATH is the file name relative to the current directory. | 
|---|
|  | 1913 | Return "unknown" if its filesystem type is unknown.  */ | 
|---|
|  | 1914 |  | 
|---|
|  | 1915 | static char * | 
|---|
|  | 1916 | filesystem_type_uncached (path, relpath, statp) | 
|---|
|  | 1917 | char *path; | 
|---|
|  | 1918 | char *relpath; | 
|---|
|  | 1919 | struct stat *statp; | 
|---|
|  | 1920 | { | 
|---|
|  | 1921 | char * type = NULL; | 
|---|
|  | 1922 | #ifdef MFSNAMELEN               /* NetBSD.  */ | 
|---|
|  | 1923 | static char my_tmp_type[64]; | 
|---|
|  | 1924 | #endif | 
|---|
|  | 1925 |  | 
|---|
|  | 1926 | #ifdef FSTYPE_MNTENT            /* 4.3BSD, SunOS, HP-UX, Dynix, Irix.  */ | 
|---|
|  | 1927 | char *table = MOUNTED; | 
|---|
|  | 1928 | FILE *mfp; | 
|---|
|  | 1929 | struct mntent *mnt; | 
|---|
|  | 1930 |  | 
|---|
|  | 1931 | if (path == NULL || relpath == NULL) | 
|---|
|  | 1932 | return NULL; | 
|---|
|  | 1933 |  | 
|---|
|  | 1934 | mfp = setmntent (table, "r"); | 
|---|
|  | 1935 | if (mfp == NULL) | 
|---|
|  | 1936 | { | 
|---|
|  | 1937 | sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_E_SUBGEN, | 
|---|
|  | 1938 | _("setmntent() failed"), | 
|---|
|  | 1939 | _("filesystem_type_uncached") ); | 
|---|
|  | 1940 | return NULL; | 
|---|
|  | 1941 | } | 
|---|
|  | 1942 |  | 
|---|
|  | 1943 | /* Find the entry with the same device number as STATP, and return | 
|---|
|  | 1944 | that entry's fstype. */ | 
|---|
|  | 1945 | while (type == NULL && (mnt = getmntent (mfp)) != NULL) | 
|---|
|  | 1946 | { | 
|---|
| [199] | 1947 | const char *devopt; | 
|---|
| [1] | 1948 | dev_t dev; | 
|---|
|  | 1949 | struct stat disk_stats; | 
|---|
|  | 1950 |  | 
|---|
|  | 1951 | #ifdef MNTTYPE_IGNORE | 
|---|
|  | 1952 | if (0 == strcmp (mnt->mnt_type, MNTTYPE_IGNORE)) | 
|---|
|  | 1953 | continue; | 
|---|
|  | 1954 | #endif | 
|---|
|  | 1955 |  | 
|---|
|  | 1956 | /* Newer systems like SunOS 4.1 keep the dev number in the mtab, | 
|---|
|  | 1957 | in the options string.  For older systems, we need to stat the | 
|---|
|  | 1958 | directory that the filesystem is mounted on to get it. | 
|---|
|  | 1959 |  | 
|---|
|  | 1960 | Unfortunately, the HPUX 9.x mnttab entries created by automountq | 
|---|
|  | 1961 | contain a dev= option but the option value does not match the | 
|---|
|  | 1962 | st_dev value of the file (maybe the lower 16 bits match?).  */ | 
|---|
|  | 1963 |  | 
|---|
|  | 1964 | #if !defined(hpux) && !defined(__hpux__) | 
|---|
|  | 1965 | devopt = sl_strstr (mnt->mnt_opts, "dev="); | 
|---|
|  | 1966 | if (devopt) | 
|---|
|  | 1967 | { | 
|---|
|  | 1968 | if (devopt[4] == '0' && (devopt[5] == 'x' || devopt[5] == 'X')) | 
|---|
|  | 1969 | dev = (dev_t) xatoi (devopt + 6); | 
|---|
|  | 1970 | else | 
|---|
|  | 1971 | dev = (dev_t) xatoi (devopt + 4); | 
|---|
|  | 1972 | } | 
|---|
|  | 1973 | else | 
|---|
|  | 1974 | #endif /* not hpux */ | 
|---|
|  | 1975 | { | 
|---|
|  | 1976 | if (stat (mnt->mnt_dir, &disk_stats) == -1) | 
|---|
|  | 1977 | { | 
|---|
|  | 1978 | sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_E_SUBGEN, | 
|---|
|  | 1979 | _("stat() failed"), | 
|---|
|  | 1980 | _("filesystem_type_uncached") ); | 
|---|
|  | 1981 | return NULL; | 
|---|
|  | 1982 | } | 
|---|
|  | 1983 | dev = disk_stats.st_dev; | 
|---|
|  | 1984 | } | 
|---|
|  | 1985 |  | 
|---|
|  | 1986 | if (dev == statp->st_dev) | 
|---|
|  | 1987 | { | 
|---|
|  | 1988 | /* check for the "nosuid" option | 
|---|
|  | 1989 | */ | 
|---|
| [61] | 1990 | #ifdef HAVE_HASMNTOPT | 
|---|
| [119] | 1991 | if (NULL == hasmntopt(mnt, "nosuid") || (ShSuidchkNosuid == S_TRUE)) | 
|---|
| [1] | 1992 | type = mnt->mnt_type; | 
|---|
|  | 1993 | else | 
|---|
| [61] | 1994 | type = _("nosuid"); /* hasmntopt (nosuid) */ | 
|---|
|  | 1995 | #else | 
|---|
|  | 1996 | type = mnt->mnt_type; | 
|---|
|  | 1997 | #endif | 
|---|
| [1] | 1998 | } | 
|---|
|  | 1999 | } | 
|---|
|  | 2000 |  | 
|---|
|  | 2001 | if (endmntent (mfp) == 0) | 
|---|
|  | 2002 | { | 
|---|
|  | 2003 | sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_E_SUBGEN, | 
|---|
|  | 2004 | _("endmntent() failed"), | 
|---|
|  | 2005 | _("filesystem_type_uncached") ); | 
|---|
|  | 2006 | } | 
|---|
|  | 2007 | #endif | 
|---|
|  | 2008 |  | 
|---|
|  | 2009 | #ifdef FSTYPE_GETMNT            /* Ultrix.  */ | 
|---|
|  | 2010 | int offset = 0; | 
|---|
|  | 2011 | struct fs_data fsd; | 
|---|
|  | 2012 |  | 
|---|
|  | 2013 | if (path == NULL || relpath == NULL) | 
|---|
|  | 2014 | return NULL; | 
|---|
|  | 2015 |  | 
|---|
|  | 2016 | while (type == NULL | 
|---|
|  | 2017 | && getmnt (&offset, &fsd, sizeof (fsd), NOSTAT_MANY, 0) > 0) | 
|---|
|  | 2018 | { | 
|---|
|  | 2019 | if (fsd.fd_req.dev == statp->st_dev) | 
|---|
|  | 2020 | type = gt_names[fsd.fd_req.fstype]; | 
|---|
|  | 2021 | } | 
|---|
|  | 2022 | #endif | 
|---|
|  | 2023 |  | 
|---|
|  | 2024 | #ifdef FSTYPE_USG_STATFS        /* SVR3.  */ | 
|---|
|  | 2025 | struct statfs fss; | 
|---|
|  | 2026 | char typebuf[FSTYPSZ]; | 
|---|
|  | 2027 |  | 
|---|
|  | 2028 | if (path == NULL || relpath == NULL) | 
|---|
|  | 2029 | return NULL; | 
|---|
|  | 2030 |  | 
|---|
|  | 2031 | if (statfs (relpath, &fss, sizeof (struct statfs), 0) == -1) | 
|---|
|  | 2032 | { | 
|---|
|  | 2033 | /* Don't die if a file was just removed. */ | 
|---|
|  | 2034 | if (errno != ENOENT) | 
|---|
|  | 2035 | { | 
|---|
|  | 2036 | sh_error_handle ((-1), FIL__, __LINE__, errno, MSG_E_SUBGEN, | 
|---|
|  | 2037 | _("statfs() failed"), | 
|---|
|  | 2038 | _("filesystem_type_uncached") ); | 
|---|
|  | 2039 | return NULL; | 
|---|
|  | 2040 | } | 
|---|
|  | 2041 | } | 
|---|
|  | 2042 | else if (!sysfs (GETFSTYP, fss.f_fstyp, typebuf)) | 
|---|
|  | 2043 | type = typebuf; | 
|---|
|  | 2044 | #endif | 
|---|
|  | 2045 |  | 
|---|
|  | 2046 | #ifdef FSTYPE_STATVFS           /* SVR4.  */ | 
|---|
|  | 2047 | struct statvfs fss; | 
|---|
|  | 2048 |  | 
|---|
|  | 2049 | if (path == NULL || relpath == NULL) | 
|---|
|  | 2050 | return NULL; | 
|---|
|  | 2051 |  | 
|---|
|  | 2052 | if (statvfs (relpath, &fss) == -1) | 
|---|
|  | 2053 | { | 
|---|
|  | 2054 | /* Don't die if a file was just removed. */ | 
|---|
|  | 2055 | if (errno != ENOENT) | 
|---|
|  | 2056 | { | 
|---|
|  | 2057 | sh_error_handle ((-1), FIL__, __LINE__, errno, MSG_E_SUBGEN, | 
|---|
|  | 2058 | _("statvfs() failed"), | 
|---|
|  | 2059 | _("filesystem_type_uncached") ); | 
|---|
|  | 2060 | return NULL; | 
|---|
|  | 2061 | } | 
|---|
|  | 2062 | } | 
|---|
|  | 2063 | else | 
|---|
|  | 2064 | { | 
|---|
|  | 2065 | type = fss.f_basetype; | 
|---|
|  | 2066 |  | 
|---|
|  | 2067 | /* patch by Konstantin Khrooschev <nathoo@co.ru> | 
|---|
|  | 2068 | */ | 
|---|
| [119] | 2069 | if( (fss.f_flag & ST_NOSUID)  && (ShSuidchkNosuid == S_FALSE)) | 
|---|
| [1] | 2070 | type = _("nosuid"); | 
|---|
|  | 2071 | } | 
|---|
|  | 2072 | (void) statp; /* fix compiler warning */ | 
|---|
|  | 2073 | #endif | 
|---|
|  | 2074 |  | 
|---|
|  | 2075 | #ifdef FSTYPE_STATFS            /* 4.4BSD.  */ | 
|---|
|  | 2076 | struct statfs fss; | 
|---|
|  | 2077 | char *p; | 
|---|
|  | 2078 | #if defined(MNT_VISFLAGMASK) && defined(HAVE_STRUCT_STATFS_F_FLAGS) | 
|---|
|  | 2079 | int flags; | 
|---|
|  | 2080 | #endif | 
|---|
|  | 2081 | /* char * sh_dirname(const char *path); */ | 
|---|
|  | 2082 |  | 
|---|
|  | 2083 | if (path == NULL || relpath == NULL) | 
|---|
|  | 2084 | return NULL; | 
|---|
|  | 2085 |  | 
|---|
|  | 2086 | if (S_ISLNK (statp->st_mode)) | 
|---|
|  | 2087 | p = sh_dirname (relpath); | 
|---|
|  | 2088 | else | 
|---|
|  | 2089 | p = relpath; | 
|---|
|  | 2090 |  | 
|---|
|  | 2091 | if (statfs (p, &fss) == -1) | 
|---|
|  | 2092 | { | 
|---|
|  | 2093 | /* Don't die if symlink to nonexisting file, or a file that was | 
|---|
|  | 2094 | just removed. */ | 
|---|
|  | 2095 | if (errno != ENOENT) | 
|---|
|  | 2096 | { | 
|---|
|  | 2097 | sh_error_handle ((-1), FIL__, __LINE__, errno, MSG_E_SUBGEN, | 
|---|
|  | 2098 | _("statfs() failed"), | 
|---|
|  | 2099 | _("filesystem_type_uncached") ); | 
|---|
|  | 2100 | return NULL; | 
|---|
|  | 2101 | } | 
|---|
|  | 2102 | } | 
|---|
|  | 2103 | else | 
|---|
|  | 2104 | { | 
|---|
|  | 2105 |  | 
|---|
|  | 2106 | #ifdef MFSNAMELEN               /* NetBSD.  */ | 
|---|
|  | 2107 | /* MEMORY LEAK !!! | 
|---|
|  | 2108 | *         type = sh_util_strdup (fss.f_fstypename); | 
|---|
|  | 2109 | */ | 
|---|
|  | 2110 | sl_strlcpy (my_tmp_type, fss.f_fstypename, 64); | 
|---|
|  | 2111 | type = my_tmp_type; | 
|---|
|  | 2112 | #else | 
|---|
|  | 2113 | type = fstype_to_string (fss.f_type); | 
|---|
|  | 2114 | #endif | 
|---|
|  | 2115 |  | 
|---|
|  | 2116 | #ifdef HAVE_STRUCT_STATFS_F_FLAGS | 
|---|
|  | 2117 | #ifdef MNT_VISFLAGMASK | 
|---|
|  | 2118 | flags = fss.f_flags & MNT_VISFLAGMASK; | 
|---|
| [119] | 2119 | if ((flags & MNT_NOSUID) && (ShSuidchkNosuid == S_FALSE)) | 
|---|
| [1] | 2120 | #else | 
|---|
| [119] | 2121 | if ((fss.f_flags & MNT_NOSUID) && (ShSuidchkNosuid == S_FALSE)) | 
|---|
| [1] | 2122 | #endif | 
|---|
|  | 2123 | type = _("nosuid"); | 
|---|
|  | 2124 | #endif | 
|---|
|  | 2125 | } | 
|---|
|  | 2126 | if (p != relpath) | 
|---|
|  | 2127 | SH_FREE (p); | 
|---|
|  | 2128 | #endif | 
|---|
|  | 2129 |  | 
|---|
|  | 2130 | #ifdef AFS | 
|---|
|  | 2131 | if ((!type || !strcmp (type, "xx")) && in_afs (relpath)) | 
|---|
|  | 2132 | type = "afs"; | 
|---|
|  | 2133 | #endif | 
|---|
|  | 2134 |  | 
|---|
|  | 2135 | /* An unknown value can be caused by an ENOENT error condition. | 
|---|
|  | 2136 | Don't cache those values.  */ | 
|---|
|  | 2137 | fstype_known = (int)(type != NULL); | 
|---|
|  | 2138 |  | 
|---|
|  | 2139 | return sh_util_strdup (type ? type : "unknown"); | 
|---|
|  | 2140 | } | 
|---|
|  | 2141 |  | 
|---|
|  | 2142 | #ifdef FSTYPE_MNTENT            /* 4.3BSD etc.  */ | 
|---|
|  | 2143 | /* Return the value of the hexadecimal number represented by CP. | 
|---|
|  | 2144 | No prefix (like '0x') or suffix (like 'h') is expected to be | 
|---|
|  | 2145 | part of CP. */ | 
|---|
|  | 2146 |  | 
|---|
|  | 2147 | static int | 
|---|
|  | 2148 | xatoi (cp) | 
|---|
| [199] | 2149 | const char *cp; | 
|---|
| [1] | 2150 | { | 
|---|
|  | 2151 | int val; | 
|---|
|  | 2152 |  | 
|---|
|  | 2153 | val = 0; | 
|---|
|  | 2154 | while (*cp != '\0') | 
|---|
|  | 2155 | { | 
|---|
|  | 2156 | /*@+charint@*/ | 
|---|
|  | 2157 | if (*cp >= 'a' && *cp <= 'f') | 
|---|
|  | 2158 | val = val * 16 + *cp - 'a' + 10; | 
|---|
|  | 2159 | else if (*cp >= 'A' && *cp <= 'F') | 
|---|
|  | 2160 | val = val * 16 + *cp - 'A' + 10; | 
|---|
|  | 2161 | else if (*cp >= '0' && *cp <= '9') | 
|---|
|  | 2162 | val = val * 16 + *cp - '0'; | 
|---|
|  | 2163 | else | 
|---|
|  | 2164 | break; | 
|---|
|  | 2165 | /*@-charint@*/ | 
|---|
|  | 2166 | cp++; | 
|---|
|  | 2167 | } | 
|---|
|  | 2168 | return val; | 
|---|
|  | 2169 | } | 
|---|
|  | 2170 | #endif | 
|---|
|  | 2171 |  | 
|---|
|  | 2172 |  | 
|---|
|  | 2173 |  | 
|---|
|  | 2174 | #endif | 
|---|
|  | 2175 |  | 
|---|
|  | 2176 |  | 
|---|
|  | 2177 | /* #ifdef SH_USE_UTMP */ | 
|---|
|  | 2178 | #endif | 
|---|
|  | 2179 |  | 
|---|
|  | 2180 |  | 
|---|
|  | 2181 |  | 
|---|