| [1] | 1 | /* SAMHAIN file system integrity testing                                   */ | 
|---|
|  | 2 | /* Copyright (C) 1999 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 <ctype.h> | 
|---|
| [98] | 27 | #ifdef HAVE_LINUX_FS_H | 
|---|
|  | 28 | #include <linux/fs.h> | 
|---|
|  | 29 | #endif | 
|---|
| [1] | 30 |  | 
|---|
|  | 31 | #ifdef HAVE_MEMORY_H | 
|---|
|  | 32 | #include <memory.h> | 
|---|
|  | 33 | #endif | 
|---|
|  | 34 |  | 
|---|
|  | 35 | #ifdef  HAVE_UNISTD_H | 
|---|
|  | 36 | #include <errno.h> | 
|---|
|  | 37 | #include <signal.h> | 
|---|
|  | 38 | #include <pwd.h> | 
|---|
|  | 39 | #include <grp.h> | 
|---|
|  | 40 | #include <sys/types.h> | 
|---|
|  | 41 | #include <sys/stat.h> | 
|---|
|  | 42 | #include <sys/resource.h> | 
|---|
|  | 43 | #include <fcntl.h> | 
|---|
|  | 44 | #include <unistd.h> | 
|---|
| [169] | 45 | /* need to undef these, since the #define's may be picked up from | 
|---|
|  | 46 | * linux/wait.h, and will clash with a typedef in sys/wait.h | 
|---|
|  | 47 | */ | 
|---|
|  | 48 | #undef P_ALL | 
|---|
|  | 49 | #undef P_PID | 
|---|
|  | 50 | #undef P_PGID | 
|---|
| [1] | 51 | #include <sys/wait.h> | 
|---|
|  | 52 |  | 
|---|
|  | 53 | /********************* | 
|---|
|  | 54 | #ifdef HAVE_SYS_VFS_H | 
|---|
|  | 55 | #include <sys/vfs.h> | 
|---|
|  | 56 | #endif | 
|---|
|  | 57 | **********************/ | 
|---|
|  | 58 | #endif | 
|---|
|  | 59 |  | 
|---|
|  | 60 | #if TIME_WITH_SYS_TIME | 
|---|
|  | 61 | #include <sys/time.h> | 
|---|
|  | 62 | #include <time.h> | 
|---|
|  | 63 | #else | 
|---|
|  | 64 | #if HAVE_SYS_TIME_H | 
|---|
|  | 65 | #include <sys/time.h> | 
|---|
|  | 66 | #else | 
|---|
|  | 67 | #include <time.h> | 
|---|
|  | 68 | #endif | 
|---|
|  | 69 | #endif | 
|---|
|  | 70 |  | 
|---|
|  | 71 | #ifdef HAVE_SYS_SELECT_H | 
|---|
|  | 72 | #include <sys/select.h> | 
|---|
|  | 73 | #endif | 
|---|
|  | 74 |  | 
|---|
|  | 75 | #ifndef FD_SET | 
|---|
|  | 76 | #define NFDBITS         32 | 
|---|
|  | 77 | #define FD_SET(n, p)    ((p)->fds_bits[(n)/NFDBITS] |= (1 << ((n) % NFDBITS))) | 
|---|
|  | 78 | #define FD_CLR(n, p)    ((p)->fds_bits[(n)/NFDBITS] &= ~(1 << ((n) % NFDBITS))) | 
|---|
|  | 79 | #define FD_ISSET(n, p)  ((p)->fds_bits[(n)/NFDBITS] & (1 << ((n) % NFDBITS))) | 
|---|
|  | 80 | #endif /* !FD_SET */ | 
|---|
|  | 81 | #ifndef FD_SETSIZE | 
|---|
|  | 82 | #define FD_SETSIZE      32 | 
|---|
|  | 83 | #endif | 
|---|
|  | 84 | #ifndef FD_ZERO | 
|---|
|  | 85 | #define FD_ZERO(p)      memset((char *)(p), '\0', sizeof(*(p))) | 
|---|
|  | 86 | #endif | 
|---|
|  | 87 |  | 
|---|
|  | 88 |  | 
|---|
|  | 89 | #if defined(HAVE_MLOCK) && !defined(HAVE_BROKEN_MLOCK) | 
|---|
|  | 90 | #include <sys/mman.h> | 
|---|
|  | 91 | #endif | 
|---|
|  | 92 |  | 
|---|
|  | 93 | #include "samhain.h" | 
|---|
|  | 94 | #include "sh_error.h" | 
|---|
|  | 95 | #include "sh_unix.h" | 
|---|
|  | 96 | #include "sh_utils.h" | 
|---|
|  | 97 | #include "sh_mem.h" | 
|---|
|  | 98 | #include "sh_hash.h" | 
|---|
|  | 99 | #include "sh_tools.h" | 
|---|
|  | 100 | #include "sh_tiger.h" | 
|---|
|  | 101 | #include "sh_prelink.h" | 
|---|
| [137] | 102 | #include "sh_pthread.h" | 
|---|
| [1] | 103 |  | 
|---|
|  | 104 | /* moved here from far below | 
|---|
|  | 105 | */ | 
|---|
|  | 106 | #include <netdb.h> | 
|---|
|  | 107 |  | 
|---|
|  | 108 | #define SH_NEED_PWD_GRP | 
|---|
|  | 109 | #define SH_NEED_GETHOSTBYXXX | 
|---|
|  | 110 | #include "sh_static.h" | 
|---|
|  | 111 |  | 
|---|
|  | 112 | #ifndef HAVE_LSTAT | 
|---|
|  | 113 | #define lstat   stat | 
|---|
|  | 114 | #endif | 
|---|
|  | 115 |  | 
|---|
|  | 116 | #if defined(S_IFLNK) && !defined(S_ISLNK) | 
|---|
|  | 117 | #define S_ISLNK(mode) (((mode) & S_IFMT) == S_IFLNK) | 
|---|
|  | 118 | #else | 
|---|
|  | 119 | #if !defined(S_ISLNK) | 
|---|
|  | 120 | #define S_ISLNK(mode) (0) | 
|---|
|  | 121 | #endif | 
|---|
|  | 122 | #endif | 
|---|
|  | 123 |  | 
|---|
|  | 124 | #if defined(S_IFSOCK) && !defined(S_ISSOCK) | 
|---|
|  | 125 | #define S_ISSOCK(mode) (((mode) & S_IFMT) == S_IFSOCK) | 
|---|
|  | 126 | #else | 
|---|
|  | 127 | #if !defined(S_ISSOCK) | 
|---|
|  | 128 | #define S_ISSOCK(mode) (0) | 
|---|
|  | 129 | #endif | 
|---|
|  | 130 | #endif | 
|---|
|  | 131 |  | 
|---|
| [40] | 132 | #if defined(S_IFDOOR) && !defined(S_ISDOOR) | 
|---|
|  | 133 | #define S_ISDOOR(mode) (((mode) & S_IFMT) == S_IFDOOR) | 
|---|
|  | 134 | #else | 
|---|
|  | 135 | #if !defined(S_ISDOOR) | 
|---|
|  | 136 | #define S_ISDOOR(mode) (0) | 
|---|
|  | 137 | #endif | 
|---|
|  | 138 | #endif | 
|---|
|  | 139 |  | 
|---|
|  | 140 | #if defined(S_IFPORT) && !defined(S_ISPORT) | 
|---|
|  | 141 | #define S_ISPORT(mode) (((mode) & S_IFMT) == S_IFPORT) | 
|---|
|  | 142 | #else | 
|---|
|  | 143 | #if !defined(S_ISPORT) | 
|---|
|  | 144 | #define S_ISPORT(mode) (0) | 
|---|
|  | 145 | #endif | 
|---|
|  | 146 | #endif | 
|---|
|  | 147 |  | 
|---|
| [105] | 148 | #define SH_KEY_NULL _("000000000000000000000000000000000000000000000000") | 
|---|
| [40] | 149 |  | 
|---|
| [1] | 150 | #undef  FIL__ | 
|---|
|  | 151 | #define FIL__  _("sh_unix.c") | 
|---|
|  | 152 |  | 
|---|
|  | 153 | unsigned long mask_PRELINK      = MASK_PRELINK_; | 
|---|
|  | 154 | unsigned long mask_USER0        = MASK_USER_; | 
|---|
|  | 155 | unsigned long mask_USER1        = MASK_USER_; | 
|---|
| [27] | 156 | unsigned long mask_USER2        = MASK_USER_; | 
|---|
|  | 157 | unsigned long mask_USER3        = MASK_USER_; | 
|---|
|  | 158 | unsigned long mask_USER4        = MASK_USER_; | 
|---|
| [1] | 159 | unsigned long mask_ALLIGNORE    = MASK_ALLIGNORE_; | 
|---|
|  | 160 | unsigned long mask_ATTRIBUTES   = MASK_ATTRIBUTES_; | 
|---|
|  | 161 | unsigned long mask_LOGFILES     = MASK_LOGFILES_; | 
|---|
|  | 162 | unsigned long mask_LOGGROW      = MASK_LOGGROW_; | 
|---|
|  | 163 | unsigned long mask_READONLY     = MASK_READONLY_; | 
|---|
|  | 164 | unsigned long mask_NOIGNORE     = MASK_NOIGNORE_; | 
|---|
|  | 165 |  | 
|---|
|  | 166 |  | 
|---|
|  | 167 | extern char **environ; | 
|---|
|  | 168 |  | 
|---|
|  | 169 | int sh_unix_maskreset() | 
|---|
|  | 170 | { | 
|---|
|  | 171 | mask_PRELINK      = MASK_PRELINK_; | 
|---|
|  | 172 | mask_USER0        = MASK_USER_; | 
|---|
|  | 173 | mask_USER1        = MASK_USER_; | 
|---|
| [27] | 174 | mask_USER2        = MASK_USER_; | 
|---|
|  | 175 | mask_USER3        = MASK_USER_; | 
|---|
|  | 176 | mask_USER4        = MASK_USER_; | 
|---|
| [1] | 177 | mask_ALLIGNORE    = MASK_ALLIGNORE_; | 
|---|
|  | 178 | mask_ATTRIBUTES   = MASK_ATTRIBUTES_; | 
|---|
|  | 179 | mask_LOGFILES     = MASK_LOGFILES_; | 
|---|
|  | 180 | mask_LOGGROW      = MASK_LOGGROW_; | 
|---|
|  | 181 | mask_READONLY     = MASK_READONLY_; | 
|---|
|  | 182 | mask_NOIGNORE     = MASK_NOIGNORE_; | 
|---|
|  | 183 | return 0; | 
|---|
|  | 184 | } | 
|---|
|  | 185 |  | 
|---|
|  | 186 |  | 
|---|
|  | 187 | #ifdef SYS_SIGLIST_DECLARED | 
|---|
|  | 188 | /* extern const char * const sys_siglist[]; */ | 
|---|
|  | 189 | #else | 
|---|
|  | 190 | char * sh_unix_siglist (int signum) | 
|---|
|  | 191 | { | 
|---|
|  | 192 | switch (signum) | 
|---|
|  | 193 | { | 
|---|
|  | 194 | #ifdef SIGHUP | 
|---|
|  | 195 | case SIGHUP: | 
|---|
|  | 196 | return _("Hangup"); | 
|---|
|  | 197 | #endif | 
|---|
|  | 198 | #ifdef SIGINT | 
|---|
|  | 199 | case SIGINT: | 
|---|
|  | 200 | return _("Interrupt"); | 
|---|
|  | 201 | #endif | 
|---|
|  | 202 | #ifdef SIGQUIT | 
|---|
|  | 203 | case SIGQUIT: | 
|---|
|  | 204 | return _("Quit"); | 
|---|
|  | 205 | #endif | 
|---|
|  | 206 | #ifdef SIGILL | 
|---|
|  | 207 | case SIGILL: | 
|---|
|  | 208 | return _("Illegal instruction"); | 
|---|
|  | 209 | #endif | 
|---|
|  | 210 | #ifdef SIGTRAP | 
|---|
|  | 211 | case SIGTRAP: | 
|---|
|  | 212 | return _("Trace/breakpoint trap"); | 
|---|
|  | 213 | #endif | 
|---|
|  | 214 | #ifdef SIGABRT | 
|---|
|  | 215 | case SIGABRT: | 
|---|
|  | 216 | return _("IOT trap/Abort"); | 
|---|
|  | 217 | #endif | 
|---|
|  | 218 | #ifdef SIGBUS | 
|---|
|  | 219 | case SIGBUS: | 
|---|
|  | 220 | return _("Bus error"); | 
|---|
|  | 221 | #endif | 
|---|
|  | 222 | #ifdef SIGFPE | 
|---|
|  | 223 | case SIGFPE: | 
|---|
|  | 224 | return _("Floating point exception"); | 
|---|
|  | 225 | #endif | 
|---|
|  | 226 | #ifdef SIGUSR1 | 
|---|
|  | 227 | case SIGUSR1: | 
|---|
|  | 228 | return _("User defined signal 1"); | 
|---|
|  | 229 | #endif | 
|---|
|  | 230 | #ifdef SIGSEGV | 
|---|
|  | 231 | case SIGSEGV: | 
|---|
|  | 232 | return _("Segmentation fault"); | 
|---|
|  | 233 | #endif | 
|---|
|  | 234 | #ifdef SIGUSR2 | 
|---|
|  | 235 | case SIGUSR2: | 
|---|
|  | 236 | return _("User defined signal 2"); | 
|---|
|  | 237 | #endif | 
|---|
|  | 238 | #ifdef SIGPIPE | 
|---|
|  | 239 | case SIGPIPE: | 
|---|
|  | 240 | return _("Broken pipe"); | 
|---|
|  | 241 | #endif | 
|---|
|  | 242 | #ifdef SIGALRM | 
|---|
|  | 243 | case SIGALRM: | 
|---|
|  | 244 | return _("Alarm clock"); | 
|---|
|  | 245 | #endif | 
|---|
|  | 246 | #ifdef SIGTERM | 
|---|
|  | 247 | case SIGTERM: | 
|---|
|  | 248 | return _("Terminated"); | 
|---|
|  | 249 | #endif | 
|---|
|  | 250 | #ifdef SIGSTKFLT | 
|---|
|  | 251 | case SIGSTKFLT: | 
|---|
|  | 252 | return _("Stack fault"); | 
|---|
|  | 253 | #endif | 
|---|
|  | 254 | #ifdef SIGCHLD | 
|---|
|  | 255 | case SIGCHLD: | 
|---|
|  | 256 | return _("Child exited"); | 
|---|
|  | 257 | #endif | 
|---|
|  | 258 | #ifdef SIGCONT | 
|---|
|  | 259 | case SIGCONT: | 
|---|
|  | 260 | return _("Continued"); | 
|---|
|  | 261 | #endif | 
|---|
|  | 262 | #ifdef SIGSTOP | 
|---|
|  | 263 | case SIGSTOP: | 
|---|
|  | 264 | return _("Stopped"); | 
|---|
|  | 265 | #endif | 
|---|
|  | 266 | #ifdef SIGTSTP | 
|---|
|  | 267 | case SIGTSTP: | 
|---|
|  | 268 | return _("Stop typed at tty"); | 
|---|
|  | 269 | #endif | 
|---|
|  | 270 | #ifdef SIGTTIN | 
|---|
|  | 271 | case SIGTTIN: | 
|---|
|  | 272 | return _("Stopped (tty input)"); | 
|---|
|  | 273 | #endif | 
|---|
|  | 274 | #ifdef SIGTTOU | 
|---|
|  | 275 | case SIGTTOU: | 
|---|
|  | 276 | return _("Stopped (tty output)"); | 
|---|
|  | 277 | #endif | 
|---|
|  | 278 | #ifdef SIGURG | 
|---|
|  | 279 | case SIGURG: | 
|---|
|  | 280 | return _("Urgent condition"); | 
|---|
|  | 281 | #endif | 
|---|
|  | 282 | #ifdef SIGXCPU | 
|---|
|  | 283 | case SIGXCPU: | 
|---|
|  | 284 | return _("CPU time limit exceeded"); | 
|---|
|  | 285 | #endif | 
|---|
|  | 286 | #ifdef SIGXFSZ | 
|---|
|  | 287 | case SIGXFSZ: | 
|---|
|  | 288 | return _("File size limit exceeded"); | 
|---|
|  | 289 | #endif | 
|---|
|  | 290 | #ifdef SIGVTALRM | 
|---|
|  | 291 | case SIGVTALRM: | 
|---|
|  | 292 | return _("Virtual time alarm"); | 
|---|
|  | 293 | #endif | 
|---|
|  | 294 | #ifdef SIGPROF | 
|---|
|  | 295 | case SIGPROF: | 
|---|
|  | 296 | return _("Profile signal"); | 
|---|
|  | 297 | #endif | 
|---|
|  | 298 | #ifdef SIGWINCH | 
|---|
|  | 299 | case SIGWINCH: | 
|---|
|  | 300 | return _("Window size changed"); | 
|---|
|  | 301 | #endif | 
|---|
|  | 302 | #ifdef SIGIO | 
|---|
|  | 303 | case SIGIO: | 
|---|
|  | 304 | return _("Possible I/O"); | 
|---|
|  | 305 | #endif | 
|---|
|  | 306 | #ifdef SIGPWR | 
|---|
|  | 307 | case SIGPWR: | 
|---|
|  | 308 | return _("Power failure"); | 
|---|
|  | 309 | #endif | 
|---|
|  | 310 | #ifdef SIGUNUSED | 
|---|
|  | 311 | case SIGUNUSED: | 
|---|
|  | 312 | return _("Unused signal"); | 
|---|
|  | 313 | #endif | 
|---|
|  | 314 | } | 
|---|
|  | 315 | return _("Unknown"); | 
|---|
|  | 316 | } | 
|---|
|  | 317 | #endif | 
|---|
|  | 318 |  | 
|---|
|  | 319 |  | 
|---|
|  | 320 | /* Log from within a signal handler without using any | 
|---|
|  | 321 | * functions that are not async signal safe. | 
|---|
|  | 322 | * | 
|---|
|  | 323 | * This is the safe_itoa helper function. | 
|---|
|  | 324 | */ | 
|---|
|  | 325 | char * safe_itoa(int i, char * str, int size) | 
|---|
|  | 326 | { | 
|---|
|  | 327 | unsigned int u; | 
|---|
|  | 328 | int iisneg = 0; | 
|---|
|  | 329 | char *p = &str[size-1]; | 
|---|
|  | 330 |  | 
|---|
|  | 331 | *p = '\0'; | 
|---|
|  | 332 | if (i < 0) { | 
|---|
|  | 333 | iisneg = 1; | 
|---|
|  | 334 | u = ((unsigned int)(-(1+i))) + 1; | 
|---|
|  | 335 | } else { | 
|---|
|  | 336 | u = i; | 
|---|
|  | 337 | } | 
|---|
|  | 338 | do { | 
|---|
|  | 339 | --p; | 
|---|
|  | 340 | *p = '0' + (u % 10); | 
|---|
|  | 341 | u /= 10; | 
|---|
| [22] | 342 | } while (u && (p != str)); | 
|---|
|  | 343 | if ((iisneg == 1) && (p != str)) { | 
|---|
| [1] | 344 | --p; | 
|---|
|  | 345 | *p = '-'; | 
|---|
|  | 346 | } | 
|---|
|  | 347 | return p; | 
|---|
|  | 348 | } | 
|---|
|  | 349 |  | 
|---|
|  | 350 | /* Log from within a signal handler without using any | 
|---|
|  | 351 | * functions that are not async signal safe. | 
|---|
|  | 352 | * | 
|---|
|  | 353 | * This is the safe_logger function. | 
|---|
|  | 354 | * Arguments: signal (signal number), method (0=logger, 1=stderr), thepid (pid) | 
|---|
|  | 355 | */ | 
|---|
|  | 356 | extern int OnlyStderr; | 
|---|
|  | 357 |  | 
|---|
| [170] | 358 | int safe_logger (int thesignal, int method, char * details) | 
|---|
| [1] | 359 | { | 
|---|
| [34] | 360 | unsigned int i = 0; | 
|---|
| [1] | 361 | int status = -1; | 
|---|
|  | 362 | struct stat buf; | 
|---|
|  | 363 | pid_t  newpid; | 
|---|
|  | 364 | char  str[128]; | 
|---|
|  | 365 | char  * p; | 
|---|
| [22] | 366 |  | 
|---|
| [1] | 367 | char l0[64], l1[64], l2[64], l3[64]; | 
|---|
|  | 368 | char a0[32], a1[32], a2[32]; | 
|---|
|  | 369 | char e0[128]; | 
|---|
|  | 370 | char msg[128]; | 
|---|
| [22] | 371 |  | 
|---|
| [1] | 372 | char * locations[] = { NULL, NULL, NULL, NULL, NULL }; | 
|---|
|  | 373 | char * envp[]      = { NULL, NULL }; | 
|---|
|  | 374 | char * argp[]      = { NULL, NULL, NULL, NULL, NULL }; | 
|---|
| [22] | 375 |  | 
|---|
|  | 376 | pid_t  thepid = getpid(); | 
|---|
|  | 377 |  | 
|---|
| [1] | 378 | if ((sh.flag.isdaemon == S_FALSE) || (OnlyStderr == S_TRUE)) | 
|---|
|  | 379 | method = 1; | 
|---|
| [22] | 380 |  | 
|---|
| [1] | 381 | /* seems that solaris cc needs this way of initializing ... | 
|---|
|  | 382 | */ | 
|---|
|  | 383 | locations[0] = l0; | 
|---|
|  | 384 | locations[1] = l1; | 
|---|
|  | 385 | locations[2] = l2; | 
|---|
|  | 386 | locations[3] = l3; | 
|---|
| [22] | 387 |  | 
|---|
| [1] | 388 | envp[0] = e0; | 
|---|
| [22] | 389 |  | 
|---|
| [1] | 390 | argp[0] = a0; | 
|---|
|  | 391 | argp[1] = a1; | 
|---|
|  | 392 | argp[2] = a2; | 
|---|
| [22] | 393 |  | 
|---|
| [1] | 394 | sl_strlcpy(msg, _("samhain["), 128); | 
|---|
|  | 395 | p = safe_itoa((int) thepid, str, 128); | 
|---|
|  | 396 | if (p && *p) | 
|---|
|  | 397 | sl_strlcat(msg, p, 128); | 
|---|
| [170] | 398 | if (thesignal == 0) | 
|---|
| [1] | 399 | { | 
|---|
| [22] | 400 | if (details == NULL) { | 
|---|
|  | 401 | sl_strlcat(msg, _("]: out of memory"), 128); | 
|---|
|  | 402 | } else { | 
|---|
|  | 403 | sl_strlcat(msg, _("]: "), 128); | 
|---|
|  | 404 | sl_strlcat(msg, details, 128); | 
|---|
|  | 405 | } | 
|---|
| [1] | 406 | } | 
|---|
|  | 407 | else | 
|---|
|  | 408 | { | 
|---|
|  | 409 | sl_strlcat(msg, _("]: exit on signal "), 128); | 
|---|
| [170] | 410 | p = safe_itoa(thesignal, str, 128); | 
|---|
| [1] | 411 | if (p && *p) | 
|---|
|  | 412 | sl_strlcat(msg, p, 128); | 
|---|
|  | 413 | } | 
|---|
|  | 414 |  | 
|---|
|  | 415 | if (method == 1) { | 
|---|
|  | 416 | #ifndef STDERR_FILENO | 
|---|
|  | 417 | #define STDERR_FILENO 2 | 
|---|
|  | 418 | #endif | 
|---|
| [153] | 419 | int retval = 0; | 
|---|
|  | 420 | do { | 
|---|
|  | 421 | retval = write(STDERR_FILENO,  msg, strlen(msg)); | 
|---|
|  | 422 | } while (retval < 0 && errno == EINTR); | 
|---|
|  | 423 | do { | 
|---|
|  | 424 | retval = write(STDERR_FILENO, "\n", 1); | 
|---|
|  | 425 | } while (retval < 0 && errno == EINTR); | 
|---|
| [1] | 426 | return 0; | 
|---|
|  | 427 | } | 
|---|
| [22] | 428 |  | 
|---|
|  | 429 | sl_strlcpy (l0, _("/usr/bin/logger"), 64); | 
|---|
|  | 430 | sl_strlcpy (l1, _("/usr/sbin/logger"), 64); | 
|---|
|  | 431 | sl_strlcpy (l2, _("/usr/ucb/logger"), 64); | 
|---|
|  | 432 | sl_strlcpy (l3, _("/bin/logger"), 64); | 
|---|
|  | 433 |  | 
|---|
|  | 434 | sl_strlcpy (a0, _("logger"), 32); | 
|---|
|  | 435 | sl_strlcpy (a1, _("-p"), 32); | 
|---|
|  | 436 | sl_strlcpy (a2, _("daemon.alert"), 32); | 
|---|
|  | 437 |  | 
|---|
|  | 438 | sl_strlcpy (e0, | 
|---|
|  | 439 | _("PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/ucb:/usr/local/bin"), | 
|---|
|  | 440 | 128); | 
|---|
|  | 441 |  | 
|---|
| [1] | 442 | while (locations[i] != NULL) { | 
|---|
|  | 443 | status = stat(locations[i], &buf); | 
|---|
|  | 444 | if (status == 0) | 
|---|
|  | 445 | break; | 
|---|
|  | 446 | ++i; | 
|---|
|  | 447 | } | 
|---|
|  | 448 |  | 
|---|
|  | 449 | if (locations[i] != NULL) { | 
|---|
|  | 450 | argp[3] = msg; | 
|---|
|  | 451 | newpid = fork(); | 
|---|
|  | 452 | if (newpid == 0) { | 
|---|
|  | 453 | execve(locations[i], argp, envp); | 
|---|
|  | 454 | _exit(1); | 
|---|
|  | 455 | } | 
|---|
|  | 456 | else if (newpid > 0) { | 
|---|
|  | 457 | waitpid(newpid, &status, WUNTRACED); | 
|---|
|  | 458 | } | 
|---|
|  | 459 | } | 
|---|
|  | 460 | return 0; | 
|---|
|  | 461 | } | 
|---|
|  | 462 |  | 
|---|
| [170] | 463 | void safe_fatal (const char * details, | 
|---|
|  | 464 | const char * file, int line) | 
|---|
| [22] | 465 | { | 
|---|
|  | 466 | char msg[128]; | 
|---|
|  | 467 | char str[128]; | 
|---|
|  | 468 | char * p; | 
|---|
| [170] | 469 | int  thesignal = 0; | 
|---|
| [34] | 470 | int  method = 0; | 
|---|
|  | 471 |  | 
|---|
| [22] | 472 | p = safe_itoa((int) line, str, 128); | 
|---|
|  | 473 | sl_strlcpy(msg, _("FATAL: "), 128); | 
|---|
|  | 474 | sl_strlcat(msg, file, 128); | 
|---|
|  | 475 | sl_strlcat(msg, ": ", 128); | 
|---|
|  | 476 | if (p && (*p)) { | 
|---|
|  | 477 | sl_strlcat(msg, p   , 128); | 
|---|
|  | 478 | sl_strlcat(msg, ": ", 128); | 
|---|
|  | 479 | } | 
|---|
|  | 480 | sl_strlcat(msg, details, 128); | 
|---|
| [170] | 481 | (void) safe_logger (thesignal, method, msg); | 
|---|
| [205] | 482 | raise(SIGKILL); | 
|---|
| [22] | 483 | } | 
|---|
| [1] | 484 |  | 
|---|
|  | 485 | extern char sh_sig_msg[64]; | 
|---|
|  | 486 |  | 
|---|
|  | 487 | volatile int immediate_exit_normal = 0; | 
|---|
|  | 488 |  | 
|---|
|  | 489 | #if defined(SA_SIGACTION_WORKS) | 
|---|
|  | 490 | static | 
|---|
|  | 491 | void sh_unix_sigexit (int mysignal, siginfo_t * signal_info, void * signal_add) | 
|---|
|  | 492 | #else | 
|---|
|  | 493 | static | 
|---|
|  | 494 | void sh_unix_sigexit (int mysignal) | 
|---|
|  | 495 | #endif | 
|---|
|  | 496 | { | 
|---|
|  | 497 |  | 
|---|
|  | 498 | #if defined(SA_SIGACTION_WORKS) | 
|---|
|  | 499 | if (signal_info != NULL && signal_info->si_code == SI_USER && | 
|---|
|  | 500 | mysignal != SIGTERM && mysignal != SIGINT) | 
|---|
|  | 501 | { | 
|---|
|  | 502 | return; | 
|---|
|  | 503 | } | 
|---|
|  | 504 |  | 
|---|
|  | 505 | /* avoid compiler warning (unused var) | 
|---|
|  | 506 | */ | 
|---|
|  | 507 | (void) signal_add; | 
|---|
|  | 508 | #endif | 
|---|
|  | 509 |  | 
|---|
|  | 510 | /* | 
|---|
|  | 511 | * Block re-entry | 
|---|
|  | 512 | */ | 
|---|
|  | 513 | if (immediate_exit_normal > 0) | 
|---|
|  | 514 | { | 
|---|
|  | 515 | ++immediate_exit_normal; | 
|---|
|  | 516 | if ((skey != NULL) && (immediate_exit_normal == 2)) | 
|---|
|  | 517 | memset (skey, '\0', sizeof(sh_key_t)); | 
|---|
|  | 518 | if (immediate_exit_normal == 2) | 
|---|
|  | 519 | { | 
|---|
| [153] | 520 | int val_return; | 
|---|
|  | 521 |  | 
|---|
|  | 522 | do { | 
|---|
|  | 523 | val_return = chdir ("/"); | 
|---|
|  | 524 | } while (val_return < 0 && errno == EINTR); | 
|---|
|  | 525 |  | 
|---|
| [22] | 526 | safe_logger (mysignal, 0, NULL); | 
|---|
| [1] | 527 | } | 
|---|
| [205] | 528 | raise(SIGKILL); | 
|---|
| [1] | 529 | } | 
|---|
|  | 530 | else | 
|---|
|  | 531 | { | 
|---|
|  | 532 | immediate_exit_normal = 1; | 
|---|
|  | 533 | } | 
|---|
|  | 534 |  | 
|---|
|  | 535 | #ifdef SYS_SIGLIST_DECLARED | 
|---|
|  | 536 | strncpy (sh_sig_msg, sys_siglist[mysignal],     40); | 
|---|
|  | 537 | #else | 
|---|
|  | 538 | strncpy (sh_sig_msg, sh_unix_siglist(mysignal), 40); | 
|---|
|  | 539 | #endif | 
|---|
|  | 540 | sh_sig_msg[63] = '\0'; | 
|---|
|  | 541 |  | 
|---|
|  | 542 | ++sig_raised; | 
|---|
|  | 543 | ++sig_urgent; | 
|---|
|  | 544 | sig_termfast   = 1; | 
|---|
|  | 545 | return; | 
|---|
|  | 546 | } | 
|---|
|  | 547 |  | 
|---|
|  | 548 | volatile int immediate_exit_fast = 0; | 
|---|
|  | 549 |  | 
|---|
|  | 550 | #if defined(SA_SIGACTION_WORKS) | 
|---|
|  | 551 | static | 
|---|
|  | 552 | void sh_unix_sigexit_fast (int mysignal, siginfo_t * signal_info, | 
|---|
|  | 553 | void * signal_add) | 
|---|
|  | 554 | #else | 
|---|
|  | 555 | static | 
|---|
|  | 556 | void sh_unix_sigexit_fast (int mysignal) | 
|---|
|  | 557 | #endif | 
|---|
|  | 558 | { | 
|---|
| [172] | 559 | #if defined(SL_DEBUG) && (defined(USE_SYSTEM_MALLOC) || !defined(USE_MALLOC_LOCK)) | 
|---|
| [154] | 560 | int retval; | 
|---|
|  | 561 | #endif | 
|---|
|  | 562 |  | 
|---|
| [1] | 563 | #if defined(SA_SIGACTION_WORKS) | 
|---|
|  | 564 | if (signal_info != NULL && signal_info->si_code == SI_USER) | 
|---|
|  | 565 | { | 
|---|
|  | 566 | return; | 
|---|
|  | 567 | } | 
|---|
|  | 568 | #endif | 
|---|
|  | 569 |  | 
|---|
|  | 570 | /* avoid compiler warning (unused var) | 
|---|
|  | 571 | */ | 
|---|
|  | 572 | #if defined(SA_SIGACTION_WORKS) | 
|---|
|  | 573 | (void) signal_add; | 
|---|
|  | 574 | #endif | 
|---|
|  | 575 |  | 
|---|
|  | 576 | /* Check whether the heap is ok; otherwise _exit | 
|---|
|  | 577 | */ | 
|---|
| [172] | 578 | #if !defined(SL_DEBUG) || (!defined(USE_SYSTEM_MALLOC) && defined(USE_MALLOC_LOCK)) | 
|---|
| [1] | 579 | ++immediate_exit_fast; | 
|---|
|  | 580 | if (skey != NULL && immediate_exit_fast < 2) | 
|---|
|  | 581 | memset (skey, '\0', sizeof(sh_key_t)); | 
|---|
|  | 582 | if (immediate_exit_fast < 2) | 
|---|
| [22] | 583 | safe_logger (mysignal, 0, NULL); | 
|---|
| [205] | 584 | raise(SIGKILL); | 
|---|
| [1] | 585 | #else | 
|---|
|  | 586 |  | 
|---|
|  | 587 | /* debug code | 
|---|
|  | 588 | */ | 
|---|
|  | 589 | if (immediate_exit_fast == 1) | 
|---|
|  | 590 | { | 
|---|
|  | 591 | ++immediate_exit_fast; | 
|---|
|  | 592 | if (skey != NULL) | 
|---|
|  | 593 | memset (skey, '\0', sizeof(sh_key_t)); | 
|---|
|  | 594 | #ifdef WITH_MESSAGE_QUEUE | 
|---|
|  | 595 | close_ipc (); | 
|---|
|  | 596 | #endif | 
|---|
| [22] | 597 | safe_logger (mysignal, 0, NULL); | 
|---|
| [154] | 598 | do { | 
|---|
|  | 599 | retval = chdir ("/"); | 
|---|
|  | 600 | } while (retval < 0 && errno == EINTR); | 
|---|
| [1] | 601 | raise(SIGFPE); | 
|---|
|  | 602 | } | 
|---|
|  | 603 | else if (immediate_exit_fast == 2) | 
|---|
|  | 604 | { | 
|---|
| [154] | 605 | do { | 
|---|
|  | 606 | retval = chdir ("/"); | 
|---|
|  | 607 | } while (retval < 0 && errno == EINTR); | 
|---|
| [1] | 608 | raise(SIGFPE); | 
|---|
|  | 609 | } | 
|---|
|  | 610 | else if (immediate_exit_fast != 0) | 
|---|
|  | 611 | { | 
|---|
| [205] | 612 | raise(SIGKILL); | 
|---|
| [1] | 613 | } | 
|---|
|  | 614 |  | 
|---|
|  | 615 | ++immediate_exit_fast; | 
|---|
|  | 616 |  | 
|---|
|  | 617 | /* The FPE|BUS|SEGV|ILL signals leave the system in an undefined | 
|---|
|  | 618 | * state, thus it is best to exit immediately. | 
|---|
|  | 619 | */ | 
|---|
|  | 620 | #ifdef SYS_SIGLIST_DECLARED | 
|---|
|  | 621 | strncpy (sh_sig_msg, sys_siglist[mysignal],     40); | 
|---|
|  | 622 | #else | 
|---|
|  | 623 | strncpy (sh_sig_msg, sh_unix_siglist(mysignal), 40); | 
|---|
|  | 624 | #endif | 
|---|
| [131] | 625 | sh_sig_msg[63] = '\0'; | 
|---|
| [1] | 626 |  | 
|---|
|  | 627 | sl_stack_print(); | 
|---|
|  | 628 |  | 
|---|
|  | 629 | /* Try to push out an error message. | 
|---|
|  | 630 | */ | 
|---|
|  | 631 | sh_error_handle ((-1), FIL__, __LINE__, mysignal, MSG_EXIT_NORMAL, | 
|---|
|  | 632 | sh.prg_name, sh_sig_msg); | 
|---|
|  | 633 |  | 
|---|
|  | 634 | if (skey != NULL) | 
|---|
|  | 635 | memset (skey, '\0', sizeof(sh_key_t)); | 
|---|
|  | 636 | #ifdef WITH_MESSAGE_QUEUE | 
|---|
|  | 637 | close_ipc (); | 
|---|
|  | 638 | #endif | 
|---|
|  | 639 |  | 
|---|
| [154] | 640 | do { | 
|---|
|  | 641 | retval = chdir ("/"); | 
|---|
|  | 642 | } while (retval < 0 && errno == EINTR); | 
|---|
|  | 643 |  | 
|---|
| [1] | 644 | raise(SIGFPE); | 
|---|
|  | 645 | #endif | 
|---|
|  | 646 | } | 
|---|
|  | 647 |  | 
|---|
|  | 648 |  | 
|---|
|  | 649 | static | 
|---|
|  | 650 | void sh_unix_sigaction (int mysignal) | 
|---|
|  | 651 | { | 
|---|
|  | 652 | ++sig_raised; | 
|---|
|  | 653 | #ifdef SIGUSR1 | 
|---|
|  | 654 | if (mysignal == SIGUSR1) | 
|---|
|  | 655 | sig_debug_switch       = 1; | 
|---|
|  | 656 | #endif | 
|---|
|  | 657 | #ifdef SIGUSR2 | 
|---|
|  | 658 | if (mysignal == SIGUSR2) | 
|---|
|  | 659 | { | 
|---|
| [19] | 660 | ++sig_suspend_switch; | 
|---|
| [1] | 661 | ++sig_urgent; | 
|---|
|  | 662 | } | 
|---|
|  | 663 | #endif | 
|---|
|  | 664 | #ifdef SIGHUP | 
|---|
|  | 665 | if (mysignal == SIGHUP) | 
|---|
|  | 666 | sig_config_read_again = 1; | 
|---|
|  | 667 | #endif | 
|---|
|  | 668 | #ifdef SIGTTOU | 
|---|
|  | 669 | if (mysignal == SIGTTOU) | 
|---|
|  | 670 | sig_force_check = 1; | 
|---|
|  | 671 | #endif | 
|---|
|  | 672 | #ifdef SIGABRT | 
|---|
|  | 673 | if (mysignal == SIGABRT) | 
|---|
|  | 674 | sig_fresh_trail       = 1; | 
|---|
|  | 675 | #endif | 
|---|
|  | 676 | #ifdef SIGQUIT | 
|---|
|  | 677 | if (mysignal == SIGQUIT) | 
|---|
|  | 678 | { | 
|---|
| [131] | 679 | sig_terminate       = 1; | 
|---|
| [1] | 680 | ++sig_urgent; | 
|---|
|  | 681 | } | 
|---|
|  | 682 | #endif | 
|---|
|  | 683 | #ifdef SIGTERM | 
|---|
|  | 684 | if (mysignal == SIGTERM) | 
|---|
|  | 685 | { | 
|---|
|  | 686 | strncpy (sh_sig_msg, _("Terminated"), 40); | 
|---|
|  | 687 | sig_termfast          = 1; | 
|---|
|  | 688 | ++sig_urgent; | 
|---|
|  | 689 | } | 
|---|
|  | 690 | #endif | 
|---|
|  | 691 |  | 
|---|
|  | 692 | return; | 
|---|
|  | 693 | } | 
|---|
|  | 694 |  | 
|---|
|  | 695 | static | 
|---|
|  | 696 | void sh_unix_siginstall (int goDaemon) | 
|---|
|  | 697 | { | 
|---|
|  | 698 | struct sigaction act, act_fast, act2, oldact, ignact; | 
|---|
|  | 699 | #if defined (SH_WITH_SERVER) | 
|---|
|  | 700 | (void) goDaemon; | 
|---|
|  | 701 | #endif | 
|---|
|  | 702 |  | 
|---|
|  | 703 | SL_ENTER(_("sh_unix_siginstall")); | 
|---|
|  | 704 |  | 
|---|
|  | 705 | ignact.sa_handler = SIG_IGN;            /* signal action           */ | 
|---|
|  | 706 | sigemptyset( &ignact.sa_mask );         /* set an empty mask       */ | 
|---|
|  | 707 | ignact.sa_flags = 0;                    /* init sa_flags           */ | 
|---|
|  | 708 |  | 
|---|
|  | 709 | #if defined(SA_SIGACTION_WORKS) | 
|---|
|  | 710 | act.sa_sigaction = &sh_unix_sigexit;    /* signal action           */ | 
|---|
|  | 711 | #else | 
|---|
|  | 712 | act.sa_handler   = &sh_unix_sigexit;    /* signal action           */ | 
|---|
|  | 713 | #endif | 
|---|
|  | 714 |  | 
|---|
|  | 715 | sigfillset ( &act.sa_mask );            /* set a  full mask        */ | 
|---|
|  | 716 |  | 
|---|
|  | 717 |  | 
|---|
|  | 718 | /* Block all but deadly signals. | 
|---|
|  | 719 | */ | 
|---|
|  | 720 | #ifdef SIGILL | 
|---|
|  | 721 | sigdelset  ( &act.sa_mask, SIGILL  ); | 
|---|
|  | 722 | #endif | 
|---|
|  | 723 | #ifndef SL_DEBUG | 
|---|
|  | 724 | #ifdef SIGFPE | 
|---|
|  | 725 | sigdelset  ( &act.sa_mask, SIGFPE  ); | 
|---|
|  | 726 | #endif | 
|---|
|  | 727 | #endif | 
|---|
|  | 728 | #ifdef SIGSEGV | 
|---|
|  | 729 | sigdelset  ( &act.sa_mask, SIGSEGV ); | 
|---|
|  | 730 | #endif | 
|---|
|  | 731 | #ifdef SIGBUS | 
|---|
|  | 732 | sigdelset  ( &act.sa_mask, SIGBUS  ); | 
|---|
|  | 733 | #endif | 
|---|
|  | 734 |  | 
|---|
|  | 735 | #if defined(SA_SIGACTION_WORKS) | 
|---|
|  | 736 | act_fast.sa_sigaction = &sh_unix_sigexit_fast;  /* signal action           */ | 
|---|
|  | 737 | #else | 
|---|
|  | 738 | act_fast.sa_handler   = &sh_unix_sigexit_fast;  /* signal action           */ | 
|---|
|  | 739 | #endif | 
|---|
|  | 740 |  | 
|---|
|  | 741 | sigfillset ( &act_fast.sa_mask );               /* set a full mask         */ | 
|---|
|  | 742 |  | 
|---|
|  | 743 | #ifdef SIGILL | 
|---|
|  | 744 | sigdelset  ( &act_fast.sa_mask, SIGILL  ); | 
|---|
|  | 745 | #endif | 
|---|
|  | 746 | #ifndef SL_DEBUG | 
|---|
|  | 747 | #ifdef SIGFPE | 
|---|
|  | 748 | sigdelset  ( &act_fast.sa_mask, SIGFPE  ); | 
|---|
|  | 749 | #endif | 
|---|
|  | 750 | #endif | 
|---|
|  | 751 | #ifdef SIGSEGV | 
|---|
|  | 752 | sigdelset  ( &act_fast.sa_mask, SIGSEGV ); | 
|---|
|  | 753 | #endif | 
|---|
|  | 754 | #ifdef SIGBUS | 
|---|
|  | 755 | sigdelset  ( &act_fast.sa_mask, SIGBUS  ); | 
|---|
|  | 756 | #endif | 
|---|
|  | 757 |  | 
|---|
|  | 758 |  | 
|---|
|  | 759 | /* Use siginfo to verify origin of signal, if possible. | 
|---|
|  | 760 | */ | 
|---|
|  | 761 | #if defined(SA_SIGACTION_WORKS) | 
|---|
|  | 762 | act.sa_flags      = SA_SIGINFO; | 
|---|
|  | 763 | act_fast.sa_flags = SA_SIGINFO; | 
|---|
|  | 764 | #else | 
|---|
|  | 765 | act.sa_flags      = 0; | 
|---|
|  | 766 | act_fast.sa_flags = 0; | 
|---|
|  | 767 | #endif | 
|---|
|  | 768 |  | 
|---|
|  | 769 | /* Do not block the signal from being received in its handler ... | 
|---|
|  | 770 | * (is this a good or a bad idea ??). | 
|---|
|  | 771 | */ | 
|---|
|  | 772 | #if   defined(SA_NOMASK) | 
|---|
|  | 773 | act_fast.sa_flags |= SA_NOMASK; | 
|---|
|  | 774 | #elif defined(SA_NODEFER) | 
|---|
|  | 775 | act_fast.sa_flags |= SA_NODEFER; | 
|---|
|  | 776 | #endif | 
|---|
|  | 777 |  | 
|---|
|  | 778 |  | 
|---|
|  | 779 | act2.sa_handler = &sh_unix_sigaction;  /* signal action           */ | 
|---|
|  | 780 | sigemptyset( &act2.sa_mask );          /* set an empty mask       */ | 
|---|
|  | 781 | act2.sa_flags = 0;                     /* init sa_flags           */ | 
|---|
|  | 782 |  | 
|---|
|  | 783 | /* signals to control the daemon */ | 
|---|
|  | 784 |  | 
|---|
|  | 785 | #ifdef SIGHUP | 
|---|
|  | 786 | retry_sigaction(FIL__, __LINE__, SIGHUP,     &act2, &oldact); | 
|---|
|  | 787 | #endif | 
|---|
|  | 788 | #ifdef SIGABRT | 
|---|
|  | 789 | retry_sigaction(FIL__, __LINE__, SIGABRT,    &act2, &oldact); | 
|---|
|  | 790 | #endif | 
|---|
|  | 791 | #ifdef SIGUSR1 | 
|---|
|  | 792 | retry_sigaction(FIL__, __LINE__, SIGUSR1,    &act2, &oldact); | 
|---|
|  | 793 | #endif | 
|---|
|  | 794 | #ifdef SIGUSR2 | 
|---|
|  | 795 | retry_sigaction(FIL__, __LINE__, SIGUSR2,    &act2, &oldact); | 
|---|
|  | 796 | #endif | 
|---|
|  | 797 | #ifdef SIGQUIT | 
|---|
|  | 798 | retry_sigaction(FIL__, __LINE__, SIGQUIT,    &act2, &oldact); | 
|---|
|  | 799 | #endif | 
|---|
|  | 800 | #ifdef SIGTERM | 
|---|
| [131] | 801 | retry_sigaction(FIL__, __LINE__, SIGTERM,    &act,  &oldact); | 
|---|
| [1] | 802 | #endif | 
|---|
|  | 803 |  | 
|---|
|  | 804 | /* fatal signals that may cause termination */ | 
|---|
|  | 805 |  | 
|---|
|  | 806 | #ifdef SIGILL | 
|---|
|  | 807 | retry_sigaction(FIL__, __LINE__, SIGILL,  &act_fast, &oldact); | 
|---|
|  | 808 | #endif | 
|---|
|  | 809 | #ifndef SL_DEBUG | 
|---|
|  | 810 | #ifdef SIGFPE | 
|---|
|  | 811 | retry_sigaction(FIL__, __LINE__, SIGFPE,  &act_fast, &oldact); | 
|---|
|  | 812 | #endif | 
|---|
|  | 813 | #endif | 
|---|
|  | 814 | #ifdef SIGSEGV | 
|---|
|  | 815 | retry_sigaction(FIL__, __LINE__, SIGSEGV, &act_fast, &oldact); | 
|---|
|  | 816 | #endif | 
|---|
|  | 817 | #ifdef SIGBUS | 
|---|
|  | 818 | retry_sigaction(FIL__, __LINE__, SIGBUS,  &act_fast, &oldact); | 
|---|
|  | 819 | #endif | 
|---|
|  | 820 |  | 
|---|
|  | 821 | /* other signals  */ | 
|---|
|  | 822 |  | 
|---|
|  | 823 | #ifdef SIGINT | 
|---|
|  | 824 | retry_sigaction(FIL__, __LINE__, SIGINT,       &act, &oldact); | 
|---|
|  | 825 | #endif | 
|---|
|  | 826 | #ifdef SIGPIPE | 
|---|
| [132] | 827 | #ifdef HAVE_PTHREAD | 
|---|
|  | 828 | retry_sigaction(FIL__, __LINE__, SIGPIPE,   &ignact, &oldact); | 
|---|
|  | 829 | #else | 
|---|
| [1] | 830 | retry_sigaction(FIL__, __LINE__, SIGPIPE,      &act, &oldact); | 
|---|
|  | 831 | #endif | 
|---|
| [132] | 832 | #endif | 
|---|
| [1] | 833 | #ifdef SIGALRM | 
|---|
|  | 834 | retry_sigaction(FIL__, __LINE__, SIGALRM,   &ignact, &oldact); | 
|---|
|  | 835 | #endif | 
|---|
|  | 836 | #ifdef SIGTSTP | 
|---|
|  | 837 | retry_sigaction(FIL__, __LINE__, SIGTSTP,   &ignact, &oldact); | 
|---|
|  | 838 | #endif | 
|---|
|  | 839 | #ifdef SIGTTIN | 
|---|
|  | 840 | retry_sigaction(FIL__, __LINE__, SIGTTIN,   &ignact, &oldact); | 
|---|
|  | 841 | #endif | 
|---|
|  | 842 | #if defined (SH_WITH_CLIENT) || defined (SH_STANDALONE) | 
|---|
|  | 843 | #ifdef SIGTTOU | 
|---|
|  | 844 | if (goDaemon == 1) | 
|---|
|  | 845 | retry_sigaction(FIL__, __LINE__, SIGTTOU,     &act2, &oldact); | 
|---|
|  | 846 | else | 
|---|
|  | 847 | retry_sigaction(FIL__, __LINE__, SIGTTOU,   &ignact, &oldact); | 
|---|
|  | 848 | #endif | 
|---|
|  | 849 | #else | 
|---|
|  | 850 | #ifdef SIGTTOU | 
|---|
|  | 851 | retry_sigaction(FIL__, __LINE__, SIGTTOU,   &ignact, &oldact); | 
|---|
|  | 852 | #endif | 
|---|
|  | 853 | #endif | 
|---|
|  | 854 |  | 
|---|
|  | 855 | #ifdef SIGTRAP | 
|---|
|  | 856 | #if !defined(SCREW_IT_UP) | 
|---|
|  | 857 | retry_sigaction(FIL__, __LINE__, SIGTRAP,      &act, &oldact); | 
|---|
|  | 858 | #endif | 
|---|
|  | 859 | #endif | 
|---|
|  | 860 |  | 
|---|
|  | 861 | #ifdef SIGPOLL | 
|---|
|  | 862 | retry_sigaction(FIL__, __LINE__, SIGPOLL,   &ignact, &oldact); | 
|---|
|  | 863 | #endif | 
|---|
|  | 864 | #if defined(SIGPROF) && !defined(SH_PROFILE) | 
|---|
|  | 865 | retry_sigaction(FIL__, __LINE__, SIGPROF,   &ignact, &oldact); | 
|---|
|  | 866 | #endif | 
|---|
|  | 867 | #ifdef SIGSYS | 
|---|
|  | 868 | retry_sigaction(FIL__, __LINE__, SIGSYS,       &act, &oldact); | 
|---|
|  | 869 | #endif | 
|---|
|  | 870 | #ifdef SIGURG | 
|---|
|  | 871 | retry_sigaction(FIL__, __LINE__, SIGURG,    &ignact, &oldact); | 
|---|
|  | 872 | #endif | 
|---|
|  | 873 | #if defined(SIGVTALRM) && !defined(SH_PROFILE) | 
|---|
|  | 874 | retry_sigaction(FIL__, __LINE__, SIGVTALRM, &ignact, &oldact); | 
|---|
|  | 875 | #endif | 
|---|
|  | 876 | #ifdef SIGXCPU | 
|---|
|  | 877 | retry_sigaction(FIL__, __LINE__, SIGXCPU,      &act, &oldact); | 
|---|
|  | 878 | #endif | 
|---|
|  | 879 | #ifdef SIGXFSZ | 
|---|
|  | 880 | retry_sigaction(FIL__, __LINE__, SIGXFSZ,      &act, &oldact); | 
|---|
|  | 881 | #endif | 
|---|
|  | 882 |  | 
|---|
|  | 883 | #ifdef SIGEMT | 
|---|
|  | 884 | retry_sigaction(FIL__, __LINE__, SIGEMT,    &ignact, &oldact); | 
|---|
|  | 885 | #endif | 
|---|
|  | 886 | #ifdef SIGSTKFLT | 
|---|
|  | 887 | retry_sigaction(FIL__, __LINE__, SIGSTKFLT,    &act, &oldact); | 
|---|
|  | 888 | #endif | 
|---|
|  | 889 | #ifdef SIGIO | 
|---|
|  | 890 | retry_sigaction(FIL__, __LINE__, SIGIO,     &ignact, &oldact); | 
|---|
|  | 891 | #endif | 
|---|
|  | 892 | #ifdef SIGPWR | 
|---|
|  | 893 | retry_sigaction(FIL__, __LINE__, SIGPWR,       &act, &oldact); | 
|---|
|  | 894 | #endif | 
|---|
|  | 895 |  | 
|---|
|  | 896 | #ifdef SIGLOST | 
|---|
|  | 897 | retry_sigaction(FIL__, __LINE__, SIGLOST,   &ignact, &oldact); | 
|---|
|  | 898 | #endif | 
|---|
|  | 899 | #ifdef SIGUNUSED | 
|---|
|  | 900 | retry_sigaction(FIL__, __LINE__, SIGUNUSED, &ignact, &oldact); | 
|---|
|  | 901 | #endif | 
|---|
|  | 902 |  | 
|---|
|  | 903 | SL_RET0(_("sh_unix_siginstall")); | 
|---|
|  | 904 | } | 
|---|
|  | 905 |  | 
|---|
|  | 906 | /* ---------------------------------------------------------------- */ | 
|---|
|  | 907 |  | 
|---|
|  | 908 | /* checksum the own binary | 
|---|
|  | 909 | */ | 
|---|
| [22] | 910 | int sh_unix_self_hash (const char * c) | 
|---|
| [1] | 911 | { | 
|---|
|  | 912 | char message[512]; | 
|---|
| [133] | 913 | char hashbuf[KEYBUF_SIZE]; | 
|---|
| [1] | 914 |  | 
|---|
|  | 915 | SL_ENTER(_("sh_unix_self_hash")); | 
|---|
|  | 916 |  | 
|---|
|  | 917 | if (c == NULL) | 
|---|
|  | 918 | { | 
|---|
|  | 919 | sh.exec.path[0] = '\0'; | 
|---|
|  | 920 | SL_RETURN((0), _("sh_unix_self_hash")); | 
|---|
|  | 921 | } | 
|---|
|  | 922 | sl_strlcpy(sh.exec.path, c, SH_PATHBUF); | 
|---|
|  | 923 |  | 
|---|
|  | 924 | sl_strlcpy(sh.exec.hash, | 
|---|
| [160] | 925 | sh_tiger_hash (c, TIGER_FILE, TIGER_NOLIM, hashbuf, sizeof(hashbuf)), | 
|---|
| [1] | 926 | KEY_LEN+1); | 
|---|
|  | 927 | sl_snprintf(message, 512, _("%s has checksum: %s"), | 
|---|
|  | 928 | sh.exec.path, sh.exec.hash); | 
|---|
|  | 929 | message[511] = '\0'; | 
|---|
|  | 930 | sh_error_handle(SH_ERR_INFO, FIL__, __LINE__, 0, MSG_E_SUBGEN, | 
|---|
|  | 931 | message, _("sh_unix_self_hash")); | 
|---|
| [93] | 932 | if (0 == sl_strcmp(sh.exec.hash, SH_KEY_NULL )) | 
|---|
| [1] | 933 | { | 
|---|
|  | 934 | dlog(1, FIL__, __LINE__, | 
|---|
|  | 935 | _("Could not checksum my own executable because of the\nfollowing error: %s: %s\n\nPossible reasons include:\n  Wrong path in configure file option SamhainPath=/path/to/executable\n  No read permission for the effective UID: %d\n"), | 
|---|
|  | 936 | sh.exec.path, sl_get_errmsg(), (int) sl_ret_euid()); | 
|---|
|  | 937 | sh_error_handle ((-1), FIL__, __LINE__, EACCES, MSG_NOACCESS, | 
|---|
|  | 938 | (long) sh.real.uid, c); | 
|---|
|  | 939 | aud_exit (FIL__, __LINE__, EXIT_FAILURE); | 
|---|
|  | 940 | } | 
|---|
|  | 941 | SL_RETURN((0), _("sh_unix_self_hash")); | 
|---|
|  | 942 | } | 
|---|
|  | 943 |  | 
|---|
|  | 944 | int sh_unix_self_check () | 
|---|
|  | 945 | { | 
|---|
|  | 946 | char newhash[KEY_LEN+1]; | 
|---|
|  | 947 | char message[512]; | 
|---|
| [133] | 948 | char hashbuf[KEYBUF_SIZE]; | 
|---|
| [1] | 949 |  | 
|---|
|  | 950 | SL_ENTER(_("sh_unix_self_check")); | 
|---|
|  | 951 | if (sh.exec.path == NULL || sh.exec.path[0] == '\0') | 
|---|
|  | 952 | SL_RETURN((0), _("sh_unix_self_check")); | 
|---|
|  | 953 |  | 
|---|
| [133] | 954 | sl_strlcpy(newhash, | 
|---|
| [160] | 955 | sh_tiger_hash (sh.exec.path, TIGER_FILE, TIGER_NOLIM, hashbuf, sizeof(hashbuf)), | 
|---|
| [133] | 956 | KEY_LEN+1); | 
|---|
| [1] | 957 | if (0 == sl_strncmp(sh.exec.hash, | 
|---|
|  | 958 | newhash, | 
|---|
|  | 959 | KEY_LEN)) | 
|---|
|  | 960 | SL_RETURN((0), _("sh_unix_self_check")); | 
|---|
|  | 961 |  | 
|---|
|  | 962 |  | 
|---|
|  | 963 | dlog(1, FIL__, __LINE__, | 
|---|
|  | 964 | _("The checksum of the executable: %s has changed since startup (%s -> %s).\n"), | 
|---|
|  | 965 | sh.exec.path, sh.exec.hash, newhash); | 
|---|
|  | 966 |  | 
|---|
|  | 967 | sl_snprintf(message, 512, | 
|---|
|  | 968 | _("The checksum of %s has changed since startup (%s -> %s)"), | 
|---|
|  | 969 | sh.exec.path, sh.exec.hash, newhash); | 
|---|
|  | 970 | message[511] = '\0'; | 
|---|
|  | 971 |  | 
|---|
|  | 972 | sh_error_handle(SH_ERR_INFO, FIL__, __LINE__, 0, MSG_E_SUBGEN, | 
|---|
|  | 973 | message, _("sh_unix_self_check")); | 
|---|
|  | 974 | sh_error_handle ((-1), FIL__, __LINE__, EACCES, MSG_E_AUTH, | 
|---|
|  | 975 | sh.exec.path); | 
|---|
|  | 976 | SL_RETURN((-1), _("sh_unix_self_check")); | 
|---|
|  | 977 | } | 
|---|
|  | 978 |  | 
|---|
|  | 979 |  | 
|---|
|  | 980 | /* ---------------------------------------------------------------- */ | 
|---|
|  | 981 |  | 
|---|
|  | 982 |  | 
|---|
|  | 983 | /* added    Tue Feb 22 10:36:44 NFT 2000 Rainer Wichmann            */ | 
|---|
| [22] | 984 | static int tf_add_trusted_user_int(const char * c) | 
|---|
| [1] | 985 | { | 
|---|
| [137] | 986 | struct passwd *          w; | 
|---|
| [1] | 987 | int                           count; | 
|---|
|  | 988 | uid_t                     pwid  = (uid_t)-1; | 
|---|
|  | 989 |  | 
|---|
| [131] | 990 | #if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GETPWNAM_R) | 
|---|
|  | 991 | struct passwd    pwd; | 
|---|
|  | 992 | char             buffer[SH_PWBUF_SIZE]; | 
|---|
|  | 993 | #endif | 
|---|
|  | 994 |  | 
|---|
| [1] | 995 | SL_ENTER(_("tf_add_trusted_user_int")); | 
|---|
|  | 996 |  | 
|---|
|  | 997 | /* First check for a user name. | 
|---|
|  | 998 | */ | 
|---|
| [131] | 999 | #if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GETPWNAM_R) | 
|---|
| [137] | 1000 | sh_getpwnam_r(c, &pwd, buffer, sizeof(buffer), &w); | 
|---|
| [131] | 1001 | #else | 
|---|
|  | 1002 | w = sh_getpwnam(c); | 
|---|
|  | 1003 | #endif | 
|---|
|  | 1004 |  | 
|---|
|  | 1005 | if ((w != NULL) && ((pwid = w->pw_uid) > 0)) | 
|---|
| [1] | 1006 | goto succe; | 
|---|
|  | 1007 |  | 
|---|
|  | 1008 | /* Failed, so check for a numerical value. | 
|---|
|  | 1009 | */ | 
|---|
|  | 1010 | pwid = strtol(c, (char **)NULL, 10); | 
|---|
|  | 1011 | if (pwid > 0 && pwid < 65535) | 
|---|
|  | 1012 | goto succe; | 
|---|
|  | 1013 |  | 
|---|
|  | 1014 | sh_error_handle ((-1), FIL__, __LINE__, EINVAL, MSG_EINVALS, | 
|---|
|  | 1015 | _("add trusted user"), c); | 
|---|
|  | 1016 | SL_RETURN((-1), _("tf_add_trusted_user_int")); | 
|---|
|  | 1017 |  | 
|---|
|  | 1018 | succe: | 
|---|
|  | 1019 | count = sl_trust_add_user(pwid); | 
|---|
|  | 1020 | SL_RETURN((count), _("tf_add_trusted_user_int")); | 
|---|
|  | 1021 | } | 
|---|
|  | 1022 |  | 
|---|
| [22] | 1023 | int tf_add_trusted_user(const char * c) | 
|---|
| [1] | 1024 | { | 
|---|
|  | 1025 | int    i; | 
|---|
|  | 1026 | char * q; | 
|---|
|  | 1027 | char * p = sh_util_strdup (c); | 
|---|
| [131] | 1028 | #if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_STRTOK_R) | 
|---|
|  | 1029 | char * saveptr; | 
|---|
|  | 1030 | #endif | 
|---|
|  | 1031 |  | 
|---|
| [1] | 1032 | SL_ENTER(_("tf_add_trusted_user")); | 
|---|
|  | 1033 |  | 
|---|
| [131] | 1034 | #if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_STRTOK_R) | 
|---|
|  | 1035 | q = strtok_r(p, ", \t", &saveptr); | 
|---|
|  | 1036 | #else | 
|---|
| [1] | 1037 | q = strtok(p, ", \t"); | 
|---|
| [131] | 1038 | #endif | 
|---|
| [1] | 1039 | if (!q) | 
|---|
|  | 1040 | { | 
|---|
|  | 1041 | SH_FREE(p); | 
|---|
|  | 1042 | SL_RETURN((-1), _("tf_add_trusted_user")); | 
|---|
|  | 1043 | } | 
|---|
|  | 1044 | while (q) | 
|---|
|  | 1045 | { | 
|---|
|  | 1046 | i = tf_add_trusted_user_int(q); | 
|---|
|  | 1047 | if (SL_ISERROR(i)) | 
|---|
|  | 1048 | { | 
|---|
|  | 1049 | SH_FREE(p); | 
|---|
|  | 1050 | SL_RETURN((i), _("tf_add_trusted_user")); | 
|---|
|  | 1051 | } | 
|---|
| [131] | 1052 | #if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_STRTOK_R) | 
|---|
|  | 1053 | q = strtok_r(NULL, ", \t", &saveptr); | 
|---|
|  | 1054 | #else | 
|---|
| [1] | 1055 | q = strtok(NULL, ", \t"); | 
|---|
| [131] | 1056 | #endif | 
|---|
| [1] | 1057 | } | 
|---|
|  | 1058 | SH_FREE(p); | 
|---|
|  | 1059 | SL_RETURN((0), _("tf_add_trusted_user")); | 
|---|
|  | 1060 | } | 
|---|
|  | 1061 |  | 
|---|
| [170] | 1062 | extern uid_t   sl_trust_baduid(void); | 
|---|
|  | 1063 | extern gid_t   sl_trust_badgid(void); | 
|---|
| [1] | 1064 |  | 
|---|
|  | 1065 | #if defined(HOST_IS_CYGWIN) || defined(__cygwin__) || defined(__CYGWIN32__) || defined(__CYGWIN__) | 
|---|
| [183] | 1066 | int tf_trust_check (const char * file, int mode) | 
|---|
| [1] | 1067 | { | 
|---|
|  | 1068 | (void) file; | 
|---|
|  | 1069 | (void) mode; | 
|---|
|  | 1070 | return 0; | 
|---|
|  | 1071 | } | 
|---|
|  | 1072 | #else | 
|---|
| [183] | 1073 | int tf_trust_check (const char * file, int mode) | 
|---|
| [1] | 1074 | { | 
|---|
|  | 1075 | char * tmp; | 
|---|
|  | 1076 | char * tmp2; | 
|---|
|  | 1077 | char * p; | 
|---|
|  | 1078 | int    status; | 
|---|
|  | 1079 | int    level; | 
|---|
|  | 1080 | uid_t  ff_euid; | 
|---|
|  | 1081 |  | 
|---|
|  | 1082 | SL_ENTER(_("tf_trust_check")); | 
|---|
|  | 1083 |  | 
|---|
|  | 1084 | if (mode == SL_YESPRIV) | 
|---|
|  | 1085 | sl_get_euid(&ff_euid); | 
|---|
|  | 1086 | else | 
|---|
|  | 1087 | sl_get_ruid(&ff_euid); | 
|---|
|  | 1088 |  | 
|---|
|  | 1089 | #if defined(SH_WITH_SERVER) | 
|---|
|  | 1090 | if (0 == sl_ret_euid())   /* privileges not dropped yet */ | 
|---|
|  | 1091 | { | 
|---|
| [131] | 1092 | #if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GETPWNAM_R) | 
|---|
|  | 1093 | struct passwd    pwd; | 
|---|
|  | 1094 | char             buffer[SH_PWBUF_SIZE]; | 
|---|
|  | 1095 | struct passwd *  tempres; | 
|---|
|  | 1096 | sh_getpwnam_r(DEFAULT_IDENT, &pwd, buffer, sizeof(buffer), &tempres); | 
|---|
|  | 1097 | #else | 
|---|
| [1] | 1098 | struct passwd * tempres = sh_getpwnam(DEFAULT_IDENT); | 
|---|
| [131] | 1099 | #endif | 
|---|
| [1] | 1100 |  | 
|---|
|  | 1101 | if (!tempres) | 
|---|
|  | 1102 | { | 
|---|
|  | 1103 | dlog(1, FIL__, __LINE__, | 
|---|
|  | 1104 | _("User %s does not exist. Please add the user to your system.\n"), | 
|---|
|  | 1105 | DEFAULT_IDENT); | 
|---|
|  | 1106 | aud_exit (FIL__, __LINE__, EXIT_FAILURE); | 
|---|
|  | 1107 | } | 
|---|
|  | 1108 | ff_euid = tempres->pw_uid; | 
|---|
|  | 1109 | } | 
|---|
|  | 1110 | #endif | 
|---|
|  | 1111 |  | 
|---|
|  | 1112 | status = sl_trustfile_euid(file, ff_euid); | 
|---|
|  | 1113 |  | 
|---|
|  | 1114 | if ( SL_ENONE != status) | 
|---|
|  | 1115 | { | 
|---|
|  | 1116 | if (status == SL_ESTAT) | 
|---|
|  | 1117 | level = SH_ERR_ALL; | 
|---|
|  | 1118 | else | 
|---|
|  | 1119 | level = SH_ERR_ERR; | 
|---|
|  | 1120 |  | 
|---|
|  | 1121 | tmp  = sh_util_safe_name (file); | 
|---|
|  | 1122 | p    = sl_trust_errfile(); | 
|---|
|  | 1123 | if (p && *p != '\0') | 
|---|
|  | 1124 | { | 
|---|
|  | 1125 | tmp2  = sh_util_safe_name (sl_trust_errfile()); | 
|---|
|  | 1126 | sh_error_handle(level, FIL__, __LINE__, status, MSG_E_TRUST2, | 
|---|
|  | 1127 | sl_error_string(status), tmp, tmp2); | 
|---|
|  | 1128 | SH_FREE(tmp2); | 
|---|
|  | 1129 | } | 
|---|
|  | 1130 | else | 
|---|
|  | 1131 | { | 
|---|
|  | 1132 | sh_error_handle(level, FIL__, __LINE__, status, MSG_E_TRUST1, | 
|---|
|  | 1133 | sl_error_string(status), tmp); | 
|---|
|  | 1134 | } | 
|---|
|  | 1135 | SH_FREE(tmp); | 
|---|
|  | 1136 |  | 
|---|
|  | 1137 | if (status == SL_EBADUID   || status == SL_EBADGID || | 
|---|
|  | 1138 | status == SL_EBADOTH   || status == SL_ETRUNC  || | 
|---|
|  | 1139 | status == SL_EINTERNAL ) | 
|---|
|  | 1140 | { | 
|---|
|  | 1141 | switch (status) { | 
|---|
|  | 1142 | case SL_EINTERNAL: | 
|---|
|  | 1143 | dlog(1, FIL__, __LINE__, | 
|---|
|  | 1144 | _("An internal error occured in the trustfile function.\n")); | 
|---|
|  | 1145 | break; | 
|---|
|  | 1146 | case SL_ETRUNC: | 
|---|
|  | 1147 | tmp  = sh_util_safe_name (file); | 
|---|
|  | 1148 | dlog(1, FIL__, __LINE__, | 
|---|
|  | 1149 | _("A filename truncation occured in the trustfile function.\nProbably the normalized filename for %s\nis too long. This may be due e.g. to deep or circular softlinks.\n"), | 
|---|
|  | 1150 | tmp); | 
|---|
|  | 1151 | SH_FREE(tmp); | 
|---|
|  | 1152 | break; | 
|---|
|  | 1153 | case SL_EBADOTH: | 
|---|
|  | 1154 | tmp  = sh_util_safe_name (file); | 
|---|
|  | 1155 | p    = sl_trust_errfile(); | 
|---|
|  | 1156 | dlog(1, FIL__, __LINE__, | 
|---|
|  | 1157 | _("The path element: %s\nin the filename: %s is world writeable.\n"), | 
|---|
|  | 1158 | p, tmp); | 
|---|
|  | 1159 | SH_FREE(tmp); | 
|---|
|  | 1160 | break; | 
|---|
|  | 1161 | case SL_EBADUID: | 
|---|
|  | 1162 | tmp  = sh_util_safe_name (file); | 
|---|
|  | 1163 | p    = sl_trust_errfile(); | 
|---|
|  | 1164 | dlog(1, FIL__, __LINE__, | 
|---|
|  | 1165 | _("The owner (UID = %ld) of the path element: %s\nin the filename: %s\nis not in the list of trusted users.\nTo fix the problem, you can:\n - run ./configure again with the option --with-trusted=0,...,UID\n   where UID is the UID of the untrusted user, or\n - use the option TrustedUser=UID in the configuration file.\n"), | 
|---|
|  | 1166 | (UID_CAST)sl_trust_baduid(), p, tmp); | 
|---|
|  | 1167 | SH_FREE(tmp); | 
|---|
|  | 1168 | break; | 
|---|
|  | 1169 | case SL_EBADGID: | 
|---|
|  | 1170 | tmp  = sh_util_safe_name (file); | 
|---|
|  | 1171 | p    = sl_trust_errfile(); | 
|---|
|  | 1172 | dlog(1, FIL__, __LINE__, | 
|---|
|  | 1173 | _("The path element: %s\nin the filename: %s\nis group writeable (GID = %ld), and at least one of the group\nmembers (UID = %ld) is not in the list of trusted users.\nTo fix the problem, you can:\n - run ./configure again with the option --with-trusted=0,...,UID\n   where UID is the UID of the untrusted user, or\n - use the option TrustedUser=UID in the configuration file.\n"), | 
|---|
|  | 1174 | p, tmp, (UID_CAST)sl_trust_badgid(), | 
|---|
|  | 1175 | (UID_CAST)sl_trust_baduid()); | 
|---|
|  | 1176 | SH_FREE(tmp); | 
|---|
|  | 1177 | break; | 
|---|
|  | 1178 | default: | 
|---|
|  | 1179 | break; | 
|---|
|  | 1180 | } | 
|---|
|  | 1181 |  | 
|---|
|  | 1182 | SL_RETURN((-1), _("tf_trust_check")); | 
|---|
|  | 1183 | } | 
|---|
|  | 1184 | } | 
|---|
|  | 1185 |  | 
|---|
|  | 1186 | SL_RETURN((0), _("tf_trust_check")); | 
|---|
|  | 1187 | } | 
|---|
|  | 1188 | #endif | 
|---|
|  | 1189 |  | 
|---|
|  | 1190 | #ifdef HAVE_INITGROUPS | 
|---|
|  | 1191 | #ifdef HOST_IS_OSF | 
|---|
|  | 1192 | int  sh_unix_initgroups (      char * in_user, gid_t in_gid) | 
|---|
|  | 1193 | #else | 
|---|
|  | 1194 | int  sh_unix_initgroups (const char * in_user, gid_t in_gid) | 
|---|
|  | 1195 | #endif | 
|---|
|  | 1196 | { | 
|---|
|  | 1197 | int status  = -1; | 
|---|
|  | 1198 | status = sh_initgroups (in_user, in_gid); | 
|---|
|  | 1199 | if (status < 0) | 
|---|
|  | 1200 | { | 
|---|
|  | 1201 | if (errno == EPERM) | 
|---|
|  | 1202 | return 0; | 
|---|
|  | 1203 | if (errno == EINVAL) | 
|---|
|  | 1204 | return 0; | 
|---|
|  | 1205 | return -1; | 
|---|
|  | 1206 | } | 
|---|
|  | 1207 | return 0; | 
|---|
|  | 1208 | } | 
|---|
|  | 1209 | #else | 
|---|
|  | 1210 | int  sh_unix_initgroups (const char * in_user, gid_t in_gid) | 
|---|
|  | 1211 | { | 
|---|
|  | 1212 | (void) in_user; | 
|---|
|  | 1213 | (void) in_gid; | 
|---|
|  | 1214 | return 0; | 
|---|
|  | 1215 | } | 
|---|
|  | 1216 | #endif | 
|---|
|  | 1217 |  | 
|---|
|  | 1218 | #ifdef HAVE_INITGROUPS | 
|---|
| [132] | 1219 | char *  sh_unix_getUIDname (int level, uid_t uid, char * out, size_t len); | 
|---|
| [1] | 1220 | int  sh_unix_initgroups2 (uid_t in_pid, gid_t in_gid) | 
|---|
|  | 1221 | { | 
|---|
|  | 1222 | int status  = -1; | 
|---|
| [132] | 1223 | char user[SH_MINIBUF]; | 
|---|
| [1] | 1224 |  | 
|---|
|  | 1225 | SL_ENTER(_("sh_unix_initgroups2")); | 
|---|
|  | 1226 |  | 
|---|
| [132] | 1227 | if (NULL == sh_unix_getUIDname (SH_ERR_ERR, in_pid, user, sizeof(user))) | 
|---|
| [1] | 1228 | SL_RETURN((-1), _("sh_unix_initgroups2")); | 
|---|
|  | 1229 | status = sh_initgroups (user, in_gid); | 
|---|
|  | 1230 | if (status < 0) | 
|---|
|  | 1231 | { | 
|---|
|  | 1232 | if (errno == EPERM) | 
|---|
|  | 1233 | status = 0; | 
|---|
|  | 1234 | if (errno == EINVAL) | 
|---|
|  | 1235 | status = 0; | 
|---|
|  | 1236 | } | 
|---|
|  | 1237 | SL_RETURN((status), _("sh_unix_initgroups2")); | 
|---|
|  | 1238 | } | 
|---|
|  | 1239 | #else | 
|---|
|  | 1240 | int  sh_unix_initgroups2 (uid_t in_pid, gid_t in_gid) | 
|---|
|  | 1241 | { | 
|---|
|  | 1242 | (void) in_pid; | 
|---|
|  | 1243 | (void) in_gid; | 
|---|
|  | 1244 | return 0; | 
|---|
|  | 1245 | } | 
|---|
|  | 1246 | #endif | 
|---|
|  | 1247 |  | 
|---|
| [174] | 1248 | void sh_unix_closeall (int fd, int except, int inchild) | 
|---|
| [1] | 1249 | { | 
|---|
|  | 1250 | int fdx = fd; | 
|---|
|  | 1251 | #ifdef _SC_OPEN_MAX | 
|---|
|  | 1252 | int fdlimit = sysconf (_SC_OPEN_MAX); | 
|---|
|  | 1253 | #else | 
|---|
|  | 1254 | #ifdef OPEN_MAX | 
|---|
|  | 1255 | int fdlimit = OPEN_MAX; | 
|---|
|  | 1256 | #else | 
|---|
|  | 1257 | int fdlimit = _POSIX_OPEN_MAX; | 
|---|
|  | 1258 | #endif | 
|---|
|  | 1259 | #endif | 
|---|
|  | 1260 |  | 
|---|
|  | 1261 | SL_ENTER(_("sh_unix_closeall")); | 
|---|
|  | 1262 |  | 
|---|
|  | 1263 | /* can't happen - so fix it :-( | 
|---|
|  | 1264 | */ | 
|---|
|  | 1265 | if (fdlimit < 0) | 
|---|
| [84] | 1266 | fdlimit = 20;  /* POSIX lower limit */ | 
|---|
| [1] | 1267 |  | 
|---|
|  | 1268 | if (fdlimit > 65536) | 
|---|
|  | 1269 | fdlimit = 65536; | 
|---|
|  | 1270 |  | 
|---|
|  | 1271 | /* Close everything from fd (inclusive) up to fdlimit (exclusive). | 
|---|
|  | 1272 | */ | 
|---|
|  | 1273 | while (fd < fdlimit) | 
|---|
|  | 1274 | { | 
|---|
|  | 1275 | if (fd == except) | 
|---|
|  | 1276 | fd++; | 
|---|
|  | 1277 | else if (slib_do_trace != 0 && fd == slib_trace_fd) | 
|---|
|  | 1278 | fd++; | 
|---|
|  | 1279 | else | 
|---|
|  | 1280 | close(fd++); | 
|---|
|  | 1281 | } | 
|---|
|  | 1282 |  | 
|---|
| [174] | 1283 | if (!inchild) | 
|---|
|  | 1284 | sl_dropall (fdx, except); | 
|---|
|  | 1285 | else | 
|---|
|  | 1286 | sl_dropall_dirty (fdx, except); | 
|---|
| [1] | 1287 |  | 
|---|
|  | 1288 | SL_RET0(_("sh_unix_closeall")); | 
|---|
|  | 1289 | } | 
|---|
|  | 1290 |  | 
|---|
|  | 1291 | static void sh_unix_setlimits(void) | 
|---|
|  | 1292 | { | 
|---|
|  | 1293 | struct rlimit limits; | 
|---|
|  | 1294 |  | 
|---|
|  | 1295 | SL_ENTER(_("sh_unix_setlimits")); | 
|---|
|  | 1296 |  | 
|---|
|  | 1297 | limits.rlim_cur = RLIM_INFINITY; | 
|---|
|  | 1298 | limits.rlim_max = RLIM_INFINITY; | 
|---|
|  | 1299 |  | 
|---|
|  | 1300 | #ifdef RLIMIT_CPU | 
|---|
|  | 1301 | setrlimit (RLIMIT_CPU,     &limits); | 
|---|
|  | 1302 | #endif | 
|---|
|  | 1303 | #ifdef RLIMIT_FSIZE | 
|---|
|  | 1304 | setrlimit (RLIMIT_FSIZE,   &limits); | 
|---|
|  | 1305 | #endif | 
|---|
|  | 1306 | #ifdef RLIMIT_DATA | 
|---|
|  | 1307 | setrlimit (RLIMIT_DATA,    &limits); | 
|---|
|  | 1308 | #endif | 
|---|
|  | 1309 | #ifdef RLIMIT_STACK | 
|---|
|  | 1310 | setrlimit (RLIMIT_STACK,   &limits); | 
|---|
|  | 1311 | #endif | 
|---|
|  | 1312 | #ifdef RLIMIT_RSS | 
|---|
|  | 1313 | setrlimit (RLIMIT_RSS,     &limits); | 
|---|
|  | 1314 | #endif | 
|---|
|  | 1315 | #ifdef RLIMIT_NPROC | 
|---|
|  | 1316 | setrlimit (RLIMIT_NPROC,   &limits); | 
|---|
|  | 1317 | #endif | 
|---|
|  | 1318 | #ifdef RLIMIT_MEMLOCK | 
|---|
|  | 1319 | setrlimit (RLIMIT_MEMLOCK, &limits); | 
|---|
|  | 1320 | #endif | 
|---|
|  | 1321 |  | 
|---|
|  | 1322 | #if !defined(SL_DEBUG) | 
|---|
|  | 1323 | /* no core dumps | 
|---|
|  | 1324 | */ | 
|---|
|  | 1325 | limits.rlim_cur = 0; | 
|---|
|  | 1326 | limits.rlim_max = 0; | 
|---|
|  | 1327 | #ifdef RLIMIT_CORE | 
|---|
|  | 1328 | setrlimit (RLIMIT_CORE,    &limits); | 
|---|
|  | 1329 | #endif | 
|---|
|  | 1330 | #else | 
|---|
|  | 1331 | #ifdef RLIMIT_CORE | 
|---|
|  | 1332 | setrlimit (RLIMIT_CORE,    &limits); | 
|---|
|  | 1333 | #endif | 
|---|
|  | 1334 | #endif | 
|---|
|  | 1335 |  | 
|---|
| [8] | 1336 | limits.rlim_cur = 1024; | 
|---|
|  | 1337 | limits.rlim_max = 1024; | 
|---|
| [1] | 1338 |  | 
|---|
| [8] | 1339 | #if defined(RLIMIT_NOFILE) | 
|---|
|  | 1340 | setrlimit (RLIMIT_NOFILE,  &limits); | 
|---|
|  | 1341 | #elif defined(RLIMIT_OFILE) | 
|---|
|  | 1342 | setrlimit (RLIMIT_OFILE,   &limits); | 
|---|
|  | 1343 | #endif | 
|---|
|  | 1344 |  | 
|---|
| [1] | 1345 | SL_RET0(_("sh_unix_setlimits")); | 
|---|
|  | 1346 | } | 
|---|
|  | 1347 |  | 
|---|
|  | 1348 | static void sh_unix_copyenv(void) | 
|---|
|  | 1349 | { | 
|---|
|  | 1350 | char ** env0 = environ; | 
|---|
|  | 1351 | char ** env1; | 
|---|
|  | 1352 | int   envlen = 0; | 
|---|
| [22] | 1353 | size_t len; | 
|---|
| [1] | 1354 |  | 
|---|
|  | 1355 | SL_ENTER(_("sh_unix_copyenv")); | 
|---|
|  | 1356 |  | 
|---|
|  | 1357 | while (env0 != NULL && env0[envlen] != NULL) { | 
|---|
|  | 1358 | /* printf("%2d: %s\n", envlen, env0[envlen]); */ | 
|---|
|  | 1359 | ++envlen; | 
|---|
|  | 1360 | } | 
|---|
|  | 1361 | ++envlen; | 
|---|
|  | 1362 |  | 
|---|
|  | 1363 | /* printf("-> %2d: slots allocated\n", envlen); */ | 
|---|
|  | 1364 | env1 = malloc (sizeof(char *) * envlen);      /* only once */ | 
|---|
|  | 1365 | if (env1 == NULL) | 
|---|
|  | 1366 | { | 
|---|
|  | 1367 | fprintf(stderr, _("%s: %d: Out of memory\n"), FIL__, __LINE__); | 
|---|
|  | 1368 | SL_RET0(_("sh_unix_copyenv")); | 
|---|
|  | 1369 | } | 
|---|
|  | 1370 | env0   = environ; | 
|---|
|  | 1371 | envlen = 0; | 
|---|
|  | 1372 |  | 
|---|
| [22] | 1373 | while (env0 != NULL && env0[envlen] != NULL) { | 
|---|
|  | 1374 | len = strlen(env0[envlen]) + 1; | 
|---|
|  | 1375 | env1[envlen] = malloc (len); /* only once */ | 
|---|
| [1] | 1376 | if (env1[envlen] == NULL) | 
|---|
|  | 1377 | { | 
|---|
|  | 1378 | fprintf(stderr, _("%s: %d: Out of memory\n"), FIL__, __LINE__); | 
|---|
|  | 1379 | SL_RET0(_("sh_unix_copyenv")); | 
|---|
|  | 1380 | } | 
|---|
| [22] | 1381 | sl_strlcpy(env1[envlen], env0[envlen], len); | 
|---|
| [1] | 1382 | ++envlen; | 
|---|
|  | 1383 | } | 
|---|
|  | 1384 | env1[envlen] = NULL; | 
|---|
|  | 1385 |  | 
|---|
|  | 1386 | environ = env1; | 
|---|
|  | 1387 | SL_RET0(_("sh_unix_copyenv")); | 
|---|
|  | 1388 | } | 
|---|
|  | 1389 |  | 
|---|
|  | 1390 | /* delete all environment variables | 
|---|
|  | 1391 | */ | 
|---|
|  | 1392 | static void sh_unix_zeroenv(void) | 
|---|
|  | 1393 | { | 
|---|
|  | 1394 | char * c; | 
|---|
|  | 1395 | char ** env; | 
|---|
|  | 1396 |  | 
|---|
|  | 1397 | SL_ENTER(_("sh_unix_zeroenv")); | 
|---|
|  | 1398 |  | 
|---|
|  | 1399 | sh_unix_copyenv(); | 
|---|
|  | 1400 | env = environ; | 
|---|
|  | 1401 |  | 
|---|
|  | 1402 | while (env != NULL && *env != NULL) { | 
|---|
|  | 1403 | c = strchr ((*env), '='); | 
|---|
|  | 1404 | #ifdef WITH_MYSQL | 
|---|
|  | 1405 | /* | 
|---|
|  | 1406 | * Skip the MYSQL_UNIX_PORT environment variable; MySQL may need it. | 
|---|
|  | 1407 | */ | 
|---|
|  | 1408 | if (0 == sl_strncmp((*env), _("MYSQL_UNIX_PORT="), 16)) | 
|---|
|  | 1409 | { | 
|---|
|  | 1410 | ++(env); | 
|---|
|  | 1411 | continue; | 
|---|
|  | 1412 | } | 
|---|
| [18] | 1413 | if (0 == sl_strncmp((*env), _("MYSQL_TCP_PORT="), 15)) | 
|---|
|  | 1414 | { | 
|---|
|  | 1415 | ++(env); | 
|---|
|  | 1416 | continue; | 
|---|
|  | 1417 | } | 
|---|
|  | 1418 | if (0 == sl_strncmp((*env), _("MYSQL_HOME="), 11)) | 
|---|
|  | 1419 | { | 
|---|
|  | 1420 | ++(env); | 
|---|
|  | 1421 | continue; | 
|---|
|  | 1422 | } | 
|---|
| [1] | 1423 | #endif | 
|---|
|  | 1424 | #ifdef WITH_ORACLE | 
|---|
|  | 1425 | /* | 
|---|
|  | 1426 | * Skip the ORACLE_HOME environment variable; Oracle may need it. | 
|---|
|  | 1427 | */ | 
|---|
|  | 1428 | if (0 == sl_strncmp((*env), _("ORACLE_HOME="), 12)) | 
|---|
|  | 1429 | { | 
|---|
|  | 1430 | ++(env); | 
|---|
|  | 1431 | continue; | 
|---|
|  | 1432 | } | 
|---|
|  | 1433 | #endif | 
|---|
|  | 1434 | /* | 
|---|
|  | 1435 | * Skip the TZ environment variable. | 
|---|
|  | 1436 | */ | 
|---|
|  | 1437 | if (0 == sl_strncmp((*env), _("TZ="), 3)) | 
|---|
|  | 1438 | { | 
|---|
|  | 1439 | ++(env); | 
|---|
|  | 1440 | continue; | 
|---|
|  | 1441 | } | 
|---|
|  | 1442 | ++(env); | 
|---|
|  | 1443 | if (c != NULL) | 
|---|
|  | 1444 | { | 
|---|
|  | 1445 | ++c; | 
|---|
|  | 1446 | while ((*c) != '\0') { | 
|---|
|  | 1447 | (*c) = '\0'; | 
|---|
|  | 1448 | ++c; | 
|---|
|  | 1449 | } | 
|---|
|  | 1450 | } | 
|---|
|  | 1451 | } | 
|---|
|  | 1452 |  | 
|---|
| [205] | 1453 | #ifdef HAVE_TZSET | 
|---|
|  | 1454 | tzset(); | 
|---|
|  | 1455 | #endif | 
|---|
|  | 1456 |  | 
|---|
| [1] | 1457 | SL_RET0(_("sh_unix_zeroenv")); | 
|---|
|  | 1458 | } | 
|---|
|  | 1459 |  | 
|---|
|  | 1460 |  | 
|---|
|  | 1461 | static void  sh_unix_resettimer(void) | 
|---|
|  | 1462 | { | 
|---|
|  | 1463 | struct itimerval this_timer; | 
|---|
|  | 1464 |  | 
|---|
|  | 1465 | SL_ENTER(_("sh_unix_resettimer")); | 
|---|
|  | 1466 |  | 
|---|
|  | 1467 | this_timer.it_value.tv_sec  = 0; | 
|---|
|  | 1468 | this_timer.it_value.tv_usec = 0; | 
|---|
|  | 1469 |  | 
|---|
|  | 1470 | this_timer.it_interval.tv_sec  = 0; | 
|---|
|  | 1471 | this_timer.it_interval.tv_usec = 0; | 
|---|
|  | 1472 |  | 
|---|
|  | 1473 | setitimer(ITIMER_REAL,    &this_timer, NULL); | 
|---|
|  | 1474 | #if !defined(SH_PROFILE) | 
|---|
|  | 1475 | setitimer(ITIMER_VIRTUAL, &this_timer, NULL); | 
|---|
|  | 1476 | setitimer(ITIMER_PROF,    &this_timer, NULL); | 
|---|
|  | 1477 | #endif | 
|---|
|  | 1478 |  | 
|---|
|  | 1479 | SL_RET0(_("sh_unix_resettimer")); | 
|---|
|  | 1480 | } | 
|---|
|  | 1481 |  | 
|---|
|  | 1482 | static void  sh_unix_resetsignals(void) | 
|---|
|  | 1483 | { | 
|---|
|  | 1484 | int  sig_num; | 
|---|
|  | 1485 | #ifdef NSIG | 
|---|
|  | 1486 | int  max_sig = NSIG; | 
|---|
|  | 1487 | #else | 
|---|
|  | 1488 | int  max_sig = 255; | 
|---|
|  | 1489 | #endif | 
|---|
|  | 1490 | int  test; | 
|---|
|  | 1491 | struct sigaction act, oldact; | 
|---|
|  | 1492 | int  status; | 
|---|
|  | 1493 |  | 
|---|
|  | 1494 | sigset_t set_proc; | 
|---|
|  | 1495 |  | 
|---|
|  | 1496 | SL_ENTER(_("sh_unix_resetsignals")); | 
|---|
|  | 1497 | /* | 
|---|
|  | 1498 | * Reset the current signal mask (inherited from parent process). | 
|---|
|  | 1499 | */ | 
|---|
|  | 1500 |  | 
|---|
|  | 1501 | sigfillset(&set_proc); | 
|---|
|  | 1502 |  | 
|---|
|  | 1503 | do { | 
|---|
|  | 1504 | errno = 0; | 
|---|
|  | 1505 | test  = sigprocmask(SIG_UNBLOCK, &set_proc, NULL); | 
|---|
|  | 1506 | } while (test < 0 && errno == EINTR); | 
|---|
|  | 1507 |  | 
|---|
|  | 1508 | /* | 
|---|
|  | 1509 | * Reset signal handling. | 
|---|
|  | 1510 | */ | 
|---|
|  | 1511 |  | 
|---|
|  | 1512 | act.sa_handler = SIG_DFL;         /* signal action           */ | 
|---|
|  | 1513 | sigemptyset( &act.sa_mask );      /* set an empty mask       */ | 
|---|
|  | 1514 | act.sa_flags = 0;                 /* init sa_flags           */ | 
|---|
|  | 1515 |  | 
|---|
|  | 1516 | for (sig_num = 1; sig_num <= max_sig; ++sig_num) | 
|---|
|  | 1517 | { | 
|---|
|  | 1518 | #if !defined(SH_PROFILE) | 
|---|
|  | 1519 | test = retry_sigaction(FIL__, __LINE__, sig_num,  &act, &oldact); | 
|---|
|  | 1520 | #else | 
|---|
|  | 1521 | test = 0; | 
|---|
|  | 1522 | #endif | 
|---|
|  | 1523 | if ((test == -1) && (errno != EINVAL)) | 
|---|
|  | 1524 | { | 
|---|
| [132] | 1525 | char errbuf[SH_ERRBUF_SIZE]; | 
|---|
| [1] | 1526 | status = errno; | 
|---|
|  | 1527 | sh_error_handle ((-1), FIL__, __LINE__, status, MSG_W_SIG, | 
|---|
| [132] | 1528 | sh_error_message (status, errbuf, sizeof(errbuf)), sig_num); | 
|---|
| [1] | 1529 | } | 
|---|
|  | 1530 | } | 
|---|
|  | 1531 |  | 
|---|
|  | 1532 | SL_RET0(_("sh_unix_resetsignals")); | 
|---|
|  | 1533 | } | 
|---|
|  | 1534 |  | 
|---|
|  | 1535 | /* Get the local hostname (FQDN) | 
|---|
|  | 1536 | */ | 
|---|
|  | 1537 | #include <sys/socket.h> | 
|---|
|  | 1538 |  | 
|---|
|  | 1539 | /* Required for BSD | 
|---|
|  | 1540 | */ | 
|---|
|  | 1541 | #ifdef HAVE_NETINET_IN_H | 
|---|
|  | 1542 | #include <netinet/in.h> | 
|---|
|  | 1543 | #endif | 
|---|
|  | 1544 |  | 
|---|
|  | 1545 | #include <arpa/inet.h> | 
|---|
|  | 1546 |  | 
|---|
| [29] | 1547 | char * sh_unix_h_name (struct hostent * host_entry) | 
|---|
|  | 1548 | { | 
|---|
|  | 1549 | char ** p; | 
|---|
|  | 1550 | if (strchr(host_entry->h_name, '.')) { | 
|---|
|  | 1551 | return host_entry->h_name; | 
|---|
|  | 1552 | } else { | 
|---|
|  | 1553 | for (p = host_entry->h_aliases; *p; ++p) { | 
|---|
|  | 1554 | if (strchr(*p, '.')) | 
|---|
|  | 1555 | return *p; | 
|---|
|  | 1556 | } | 
|---|
|  | 1557 | } | 
|---|
|  | 1558 | return host_entry->h_name; | 
|---|
|  | 1559 | } | 
|---|
|  | 1560 |  | 
|---|
| [1] | 1561 | /* uname() on FreeBSD is broken, because the 'nodename' buf is too small | 
|---|
|  | 1562 | * to hold a valid (leftmost) domain label. | 
|---|
|  | 1563 | */ | 
|---|
|  | 1564 | #if defined(HAVE_UNAME) && !defined(HOST_IS_FREEBSD) | 
|---|
|  | 1565 | #include <sys/utsname.h> | 
|---|
|  | 1566 | void sh_unix_localhost() | 
|---|
|  | 1567 | { | 
|---|
|  | 1568 | struct utsname   buf; | 
|---|
|  | 1569 | struct hostent * he1; | 
|---|
|  | 1570 | int              i; | 
|---|
| [170] | 1571 | int              ddot; | 
|---|
| [1] | 1572 | int              len; | 
|---|
|  | 1573 | char           * p; | 
|---|
|  | 1574 | char             hostname[256]; | 
|---|
|  | 1575 |  | 
|---|
|  | 1576 |  | 
|---|
|  | 1577 | SL_ENTER(_("sh_unix_localhost")); | 
|---|
|  | 1578 |  | 
|---|
|  | 1579 | (void) uname (&buf); | 
|---|
| [22] | 1580 | /* flawfinder: ignore */ /* ff bug, ff sees system() */ | 
|---|
| [1] | 1581 | sl_strlcpy (sh.host.system,  buf.sysname, SH_MINIBUF); | 
|---|
|  | 1582 | sl_strlcpy (sh.host.release, buf.release, SH_MINIBUF); | 
|---|
|  | 1583 | sl_strlcpy (sh.host.machine, buf.machine, SH_MINIBUF); | 
|---|
|  | 1584 |  | 
|---|
|  | 1585 | /* Workaround for cases where nodename could be | 
|---|
|  | 1586 | * a truncated FQDN. | 
|---|
|  | 1587 | */ | 
|---|
|  | 1588 | if (strlen(buf.nodename) == (sizeof(buf.nodename)-1)) | 
|---|
|  | 1589 | { | 
|---|
|  | 1590 | p = strchr(buf.nodename, '.'); | 
|---|
|  | 1591 | if (NULL != p) { | 
|---|
|  | 1592 | *p = '\0'; | 
|---|
|  | 1593 | sl_strlcpy(hostname, buf.nodename, 256); | 
|---|
|  | 1594 | } else { | 
|---|
|  | 1595 | #ifdef HAVE_GETHOSTNAME | 
|---|
|  | 1596 | if (0 != gethostname(hostname, 256)) | 
|---|
|  | 1597 | { | 
|---|
|  | 1598 | sh_error_handle(SH_ERR_WARN, FIL__, __LINE__, 0, MSG_E_SUBGEN, | 
|---|
|  | 1599 | _("nodename returned by uname may be truncated"), | 
|---|
|  | 1600 | _("sh_unix_localhost")); | 
|---|
|  | 1601 | sl_strlcpy (hostname, buf.nodename, 256); | 
|---|
|  | 1602 | } | 
|---|
|  | 1603 | else | 
|---|
|  | 1604 | { | 
|---|
|  | 1605 | hostname[255] = '\0'; | 
|---|
|  | 1606 | } | 
|---|
|  | 1607 | #else | 
|---|
|  | 1608 | sh_error_handle(SH_ERR_WARN, FIL__, __LINE__, 0, MSG_E_SUBGEN, | 
|---|
|  | 1609 | _("nodename returned by uname may be truncated"), | 
|---|
|  | 1610 | _("sh_unix_localhost")); | 
|---|
|  | 1611 | sl_strlcpy(hostname, buf.nodename, 256); | 
|---|
|  | 1612 | #endif | 
|---|
|  | 1613 | } | 
|---|
|  | 1614 | } | 
|---|
|  | 1615 | else | 
|---|
|  | 1616 | { | 
|---|
|  | 1617 | sl_strlcpy(hostname, buf.nodename, 256); | 
|---|
|  | 1618 | } | 
|---|
|  | 1619 |  | 
|---|
| [134] | 1620 | SH_MUTEX_LOCK(mutex_resolv); | 
|---|
| [1] | 1621 | he1 = sh_gethostbyname(hostname); | 
|---|
|  | 1622 |  | 
|---|
| [134] | 1623 | if (he1 != NULL) | 
|---|
|  | 1624 | { | 
|---|
|  | 1625 | sl_strlcpy (sh.host.name, sh_unix_h_name(he1), SH_PATHBUF); | 
|---|
|  | 1626 | } | 
|---|
|  | 1627 | SH_MUTEX_UNLOCK(mutex_resolv); | 
|---|
|  | 1628 |  | 
|---|
| [1] | 1629 | if (he1 == NULL) | 
|---|
|  | 1630 | { | 
|---|
|  | 1631 | dlog(1, FIL__, __LINE__, | 
|---|
|  | 1632 | _("According to uname, your nodename is %s, but your resolver\nlibrary cannot resolve this nodename to a FQDN. For more information, see the entry about self-resolving under 'Most frequently' in the FAQ that you will find in the docs/ subdirectory.\n"), | 
|---|
|  | 1633 | hostname); | 
|---|
|  | 1634 | sl_strlcpy (sh.host.name, hostname,    SH_PATHBUF); | 
|---|
|  | 1635 | } | 
|---|
|  | 1636 |  | 
|---|
|  | 1637 |  | 
|---|
|  | 1638 | /* check whether it looks like a FQDN | 
|---|
|  | 1639 | */ | 
|---|
|  | 1640 | len = sl_strlen(sh.host.name); | 
|---|
| [170] | 1641 | ddot = 0; | 
|---|
| [1] | 1642 | for (i = 0; i < len; ++i) | 
|---|
|  | 1643 | if (sh.host.name[i] == '.') ++ddot; | 
|---|
|  | 1644 |  | 
|---|
|  | 1645 | if (ddot == 0 && he1 != NULL) | 
|---|
|  | 1646 | { | 
|---|
|  | 1647 | dlog(1, FIL__, __LINE__, | 
|---|
|  | 1648 | _("According to uname, your nodename is %s, but your resolver\nlibrary cannot resolve this nodename to a FQDN.\nRather, it resolves this to %s.\nFor more information, see the entry about self-resolving under\n'Most frequently' in the FAQ that you will find in the docs/ subdirectory.\n"), | 
|---|
|  | 1649 | hostname, sh.host.name); | 
|---|
|  | 1650 | sl_strlcpy (sh.host.name, | 
|---|
|  | 1651 | inet_ntoa (*(struct in_addr *) he1->h_addr), | 
|---|
|  | 1652 | SH_PATHBUF); | 
|---|
|  | 1653 | SL_RET0(_("sh_unix_localhost")); | 
|---|
|  | 1654 | } | 
|---|
|  | 1655 |  | 
|---|
|  | 1656 | if (is_numeric(sh.host.name)) | 
|---|
|  | 1657 | { | 
|---|
|  | 1658 | dlog(1, FIL__, __LINE__, | 
|---|
|  | 1659 | _("According to uname, your nodename is %s, but your resolver\nlibrary cannot resolve this nodename to a FQDN.\nRather, it resolves this to %s.\nFor more information, see the entry about self-resolving under\n'Most frequently' in the FAQ that you will find in the docs/ subdirectory.\n"), | 
|---|
|  | 1660 | hostname, sh.host.name); | 
|---|
|  | 1661 | } | 
|---|
|  | 1662 |  | 
|---|
|  | 1663 | SL_RET0(_("sh_unix_localhost")); | 
|---|
|  | 1664 | } | 
|---|
|  | 1665 | #else | 
|---|
|  | 1666 | void sh_unix_localhost() | 
|---|
|  | 1667 | { | 
|---|
|  | 1668 | struct hostent * he1; | 
|---|
|  | 1669 | int              i; | 
|---|
| [170] | 1670 | int              ddot; | 
|---|
| [1] | 1671 | int              len; | 
|---|
|  | 1672 | char             hostname[1024]; | 
|---|
|  | 1673 |  | 
|---|
|  | 1674 |  | 
|---|
|  | 1675 | SL_ENTER(_("sh_unix_localhost")); | 
|---|
|  | 1676 |  | 
|---|
|  | 1677 | (void) gethostname (hostname, 1024); | 
|---|
|  | 1678 | hostname[1023] = '\0'; | 
|---|
| [134] | 1679 |  | 
|---|
|  | 1680 | SH_MUTEX_LOCK(mutex_resolv); | 
|---|
| [1] | 1681 | he1 = sh_gethostbyname(hostname); | 
|---|
|  | 1682 |  | 
|---|
|  | 1683 | if (he1 != NULL) | 
|---|
|  | 1684 | { | 
|---|
| [29] | 1685 | sl_strlcpy (sh.host.name, sh_unix_h_name(he1), SH_PATHBUF); | 
|---|
| [1] | 1686 | } | 
|---|
| [134] | 1687 | SH_MUTEX_UNLOCK(mutex_resolv); | 
|---|
|  | 1688 |  | 
|---|
|  | 1689 | if (he1 == NULL) | 
|---|
| [1] | 1690 | { | 
|---|
|  | 1691 | dlog(1, FIL__, __LINE__, | 
|---|
|  | 1692 | _("According to gethostname, your nodename is %s, but your resolver\nlibrary cannot resolve this nodename to a FQDN.\nFor more information, see the entry about self-resolving under\n'Most frequently' in the FAQ that you will find in the docs/ subdirectory.\n"), | 
|---|
|  | 1693 | hostname); | 
|---|
|  | 1694 | sl_strlcpy (sh.host.name, _("localhost"), SH_PATHBUF); | 
|---|
|  | 1695 | SL_RET0(_("sh_unix_localhost")); | 
|---|
|  | 1696 | } | 
|---|
|  | 1697 |  | 
|---|
|  | 1698 | /* check whether it looks like a FQDN | 
|---|
|  | 1699 | */ | 
|---|
|  | 1700 | len = sl_strlen(sh.host.name); | 
|---|
| [170] | 1701 | ddot = 0; | 
|---|
| [1] | 1702 | for (i = 0; i < len; ++i) | 
|---|
|  | 1703 | if (sh.host.name[i] == '.') ++ddot; | 
|---|
|  | 1704 | if (ddot == 0) | 
|---|
|  | 1705 | { | 
|---|
|  | 1706 | dlog(1, FIL__, __LINE__, | 
|---|
|  | 1707 | _("According to uname, your nodename is %s, but your resolver\nlibrary cannot resolve this nodename to a FQDN.\nRather, it resolves this to %s.\nFor more information, see the entry about self-resolving under\n'Most frequently' in the FAQ that you will find in the docs/ subdirectory.\n"), | 
|---|
|  | 1708 | hostname, sh.host.name); | 
|---|
|  | 1709 | sl_strlcpy (sh.host.name, | 
|---|
|  | 1710 | inet_ntoa (*(struct in_addr *) he1->h_addr), | 
|---|
|  | 1711 | SH_PATHBUF); | 
|---|
|  | 1712 | SL_RET0(_("sh_unix_localhost")); | 
|---|
|  | 1713 | } | 
|---|
|  | 1714 |  | 
|---|
|  | 1715 | if (is_numeric(sh.host.name)) | 
|---|
|  | 1716 | { | 
|---|
|  | 1717 | dlog(1, FIL__, __LINE__, | 
|---|
|  | 1718 | _("According to uname, your nodename is %s, but your resolver\nlibrary cannot resolve this nodename to a FQDN.\nRather, it resolves this to %s.\nFor more information, see the entry about self-resolving under\n'Most frequently' in the FAQ that you will find in the docs/ subdirectory.\n"), | 
|---|
|  | 1719 | hostname, sh.host.name); | 
|---|
|  | 1720 | } | 
|---|
|  | 1721 |  | 
|---|
|  | 1722 | SL_RET0(_("sh_unix_localhost")); | 
|---|
|  | 1723 | } | 
|---|
|  | 1724 | #endif | 
|---|
|  | 1725 |  | 
|---|
|  | 1726 |  | 
|---|
|  | 1727 | void sh_unix_memlock() | 
|---|
|  | 1728 | { | 
|---|
|  | 1729 | SL_ENTER(_("sh_unix_memlock")); | 
|---|
|  | 1730 |  | 
|---|
|  | 1731 | /* do this before dropping privileges | 
|---|
|  | 1732 | */ | 
|---|
|  | 1733 | #if defined(HAVE_MLOCK) && !defined(HAVE_BROKEN_MLOCK) | 
|---|
|  | 1734 | if (skey->mlock_failed == SL_FALSE) | 
|---|
|  | 1735 | { | 
|---|
| [19] | 1736 | if ( (-1) == sh_unix_mlock( FIL__, __LINE__, | 
|---|
|  | 1737 | (char *) skey, sizeof (sh_key_t)) ) | 
|---|
| [1] | 1738 | { | 
|---|
| [134] | 1739 | SH_MUTEX_LOCK_UNSAFE(mutex_skey); | 
|---|
| [1] | 1740 | skey->mlock_failed = SL_TRUE; | 
|---|
| [134] | 1741 | SH_MUTEX_UNLOCK_UNSAFE(mutex_skey); | 
|---|
| [1] | 1742 | } | 
|---|
|  | 1743 | } | 
|---|
|  | 1744 | #else | 
|---|
|  | 1745 | if (skey->mlock_failed == SL_FALSE) | 
|---|
|  | 1746 | { | 
|---|
| [134] | 1747 | SH_MUTEX_LOCK_UNSAFE(mutex_skey); | 
|---|
| [1] | 1748 | skey->mlock_failed = SL_TRUE; | 
|---|
| [134] | 1749 | SH_MUTEX_UNLOCK_UNSAFE(mutex_skey); | 
|---|
| [1] | 1750 | } | 
|---|
|  | 1751 | #endif | 
|---|
|  | 1752 |  | 
|---|
|  | 1753 | SL_RET0(_("sh_unix_memlock")); | 
|---|
|  | 1754 | } | 
|---|
|  | 1755 |  | 
|---|
|  | 1756 | #ifdef SH_WITH_SERVER | 
|---|
|  | 1757 | char * chroot_dir = NULL; | 
|---|
|  | 1758 |  | 
|---|
| [20] | 1759 | int sh_unix_set_chroot(const char * str) | 
|---|
| [1] | 1760 | { | 
|---|
|  | 1761 | size_t len; | 
|---|
|  | 1762 | static int block = 0; | 
|---|
|  | 1763 |  | 
|---|
|  | 1764 | if (block == 1) | 
|---|
|  | 1765 | return 0; | 
|---|
|  | 1766 |  | 
|---|
|  | 1767 | if (str && *str == '/') | 
|---|
|  | 1768 | { | 
|---|
|  | 1769 | len = strlen(str) + 1; | 
|---|
|  | 1770 | chroot_dir = malloc(strlen(str) + 1);  /* only once */ | 
|---|
|  | 1771 | if (!chroot_dir) | 
|---|
|  | 1772 | { | 
|---|
|  | 1773 | fprintf(stderr, _("%s: %d: Out of memory\n"), FIL__, __LINE__); | 
|---|
|  | 1774 | return 1; | 
|---|
|  | 1775 | } | 
|---|
|  | 1776 | sl_strlcpy(chroot_dir, str, len); | 
|---|
|  | 1777 | block = 1; | 
|---|
|  | 1778 | return 0; | 
|---|
|  | 1779 | } | 
|---|
|  | 1780 | return 1; | 
|---|
|  | 1781 | } | 
|---|
|  | 1782 |  | 
|---|
| [170] | 1783 | int sh_unix_chroot(void) | 
|---|
| [1] | 1784 | { | 
|---|
|  | 1785 | int status; | 
|---|
|  | 1786 |  | 
|---|
|  | 1787 | if (chroot_dir != NULL) | 
|---|
|  | 1788 | { | 
|---|
|  | 1789 | status = retry_aud_chdir(FIL__, __LINE__, chroot_dir); | 
|---|
|  | 1790 | if ( (-1) == status ) | 
|---|
|  | 1791 | { | 
|---|
| [132] | 1792 | char errbuf[SH_ERRBUF_SIZE]; | 
|---|
| [1] | 1793 | status = errno; | 
|---|
|  | 1794 | sh_error_handle ((-1), FIL__, __LINE__, status, MSG_W_CHDIR, | 
|---|
| [132] | 1795 | sh_error_message (status, errbuf, sizeof(errbuf)), chroot_dir); | 
|---|
| [1] | 1796 | aud_exit(FIL__, __LINE__, EXIT_FAILURE); | 
|---|
|  | 1797 | } | 
|---|
| [22] | 1798 | /* flawfinder: ignore */ | 
|---|
| [1] | 1799 | return (chroot(chroot_dir)); | 
|---|
|  | 1800 | } | 
|---|
|  | 1801 | return 0; | 
|---|
|  | 1802 | } | 
|---|
|  | 1803 | /* #ifdef SH_WITH_SERVER */ | 
|---|
|  | 1804 | #else | 
|---|
| [170] | 1805 | int sh_unix_chroot(void) { return 0; } | 
|---|
| [1] | 1806 | #endif | 
|---|
|  | 1807 |  | 
|---|
|  | 1808 | /* daemon mode | 
|---|
|  | 1809 | */ | 
|---|
|  | 1810 | static int block_setdeamon = 0; | 
|---|
|  | 1811 |  | 
|---|
| [20] | 1812 | int sh_unix_setdeamon(const char * dummy) | 
|---|
| [1] | 1813 | { | 
|---|
|  | 1814 | int    res = 0; | 
|---|
|  | 1815 |  | 
|---|
|  | 1816 | SL_ENTER(_("sh_unix_setdeamon")); | 
|---|
|  | 1817 |  | 
|---|
|  | 1818 | if (block_setdeamon != 0) | 
|---|
|  | 1819 | SL_RETURN((0),_("sh_unix_setdeamon")); | 
|---|
|  | 1820 |  | 
|---|
|  | 1821 | if (dummy == NULL) | 
|---|
|  | 1822 | sh.flag.isdaemon = ON; | 
|---|
|  | 1823 | else | 
|---|
|  | 1824 | res = sh_util_flagval (dummy, &sh.flag.isdaemon); | 
|---|
|  | 1825 |  | 
|---|
|  | 1826 | if (sh.flag.opts == S_TRUE) | 
|---|
|  | 1827 | block_setdeamon = 1; | 
|---|
|  | 1828 |  | 
|---|
|  | 1829 | SL_RETURN(res, _("sh_unix_setdeamon")); | 
|---|
|  | 1830 | } | 
|---|
|  | 1831 | #if defined(HAVE_LIBPRELUDE) | 
|---|
|  | 1832 | #include "sh_prelude.h" | 
|---|
|  | 1833 | #endif | 
|---|
|  | 1834 |  | 
|---|
| [20] | 1835 | int sh_unix_setnodeamon(const char * dummy) | 
|---|
| [1] | 1836 | { | 
|---|
|  | 1837 | int    res = 0; | 
|---|
| [132] | 1838 |  | 
|---|
| [1] | 1839 | SL_ENTER(_("sh_unix_setnodeamon")); | 
|---|
|  | 1840 |  | 
|---|
|  | 1841 | if (block_setdeamon != 0) | 
|---|
|  | 1842 | SL_RETURN((0),_("sh_unix_setmodeamon")); | 
|---|
|  | 1843 |  | 
|---|
|  | 1844 | if (dummy == NULL) | 
|---|
|  | 1845 | sh.flag.isdaemon = OFF; | 
|---|
|  | 1846 | else | 
|---|
|  | 1847 | res = sh_util_flagval (dummy, &sh.flag.isdaemon); | 
|---|
|  | 1848 |  | 
|---|
|  | 1849 | if (sh.flag.opts == S_TRUE) | 
|---|
|  | 1850 | block_setdeamon = 1; | 
|---|
|  | 1851 |  | 
|---|
|  | 1852 | SL_RETURN(res, _("sh_unix_setnodeamon")); | 
|---|
|  | 1853 | } | 
|---|
|  | 1854 |  | 
|---|
|  | 1855 | int sh_unix_init(int goDaemon) | 
|---|
|  | 1856 | { | 
|---|
|  | 1857 | int    status; | 
|---|
|  | 1858 | uid_t  uid; | 
|---|
|  | 1859 | pid_t  oldpid = getpid(); | 
|---|
|  | 1860 | #if defined(SH_WITH_SERVER) | 
|---|
| [170] | 1861 | extern int sh_socket_open_int (void); | 
|---|
| [1] | 1862 | #endif | 
|---|
| [132] | 1863 | char errbuf[SH_ERRBUF_SIZE]; | 
|---|
| [1] | 1864 |  | 
|---|
|  | 1865 | SL_ENTER(_("sh_unix_init")); | 
|---|
|  | 1866 |  | 
|---|
|  | 1867 | /* fork twice, exit the parent process | 
|---|
|  | 1868 | */ | 
|---|
|  | 1869 | if (goDaemon == 1) { | 
|---|
|  | 1870 |  | 
|---|
|  | 1871 | switch (aud_fork(FIL__, __LINE__)) { | 
|---|
|  | 1872 | case 0:  break;                             /* child process continues */ | 
|---|
|  | 1873 | case -1: SL_RETURN((-1),_("sh_unix_init")); /* error                   */ | 
|---|
|  | 1874 | default: aud__exit(FIL__, __LINE__, 0);     /* parent process exits    */ | 
|---|
|  | 1875 | } | 
|---|
|  | 1876 |  | 
|---|
|  | 1877 | /* Child processes do not inherit page locks across a fork. | 
|---|
|  | 1878 | * Error in next fork would return in this (?) thread of execution. | 
|---|
|  | 1879 | */ | 
|---|
|  | 1880 | sh_unix_memlock(); | 
|---|
|  | 1881 |  | 
|---|
|  | 1882 | setsid();            /* should not fail         */ | 
|---|
| [162] | 1883 | sh.pid = (UINT64) getpid(); | 
|---|
| [1] | 1884 |  | 
|---|
|  | 1885 | switch (aud_fork(FIL__, __LINE__)) { | 
|---|
|  | 1886 | case 0:  break;                             /* child process continues */ | 
|---|
|  | 1887 | case -1: SL_RETURN((-1),_("sh_unix_init")); /* error                   */ | 
|---|
|  | 1888 | default: aud__exit(FIL__, __LINE__, 0);     /* parent process exits    */ | 
|---|
|  | 1889 | } | 
|---|
|  | 1890 |  | 
|---|
|  | 1891 | /* Child processes do not inherit page locks across a fork. | 
|---|
|  | 1892 | */ | 
|---|
|  | 1893 | sh_unix_memlock(); | 
|---|
| [162] | 1894 | sh.pid = (UINT64) getpid(); | 
|---|
| [1] | 1895 |  | 
|---|
|  | 1896 | } else { | 
|---|
|  | 1897 | setsid();            /* should not fail         */ | 
|---|
|  | 1898 | } | 
|---|
|  | 1899 |  | 
|---|
|  | 1900 | /* set working directory | 
|---|
|  | 1901 | */ | 
|---|
|  | 1902 | #ifdef SH_PROFILE | 
|---|
|  | 1903 | status = 0; | 
|---|
|  | 1904 | #else | 
|---|
|  | 1905 | status = retry_aud_chdir(FIL__, __LINE__, "/"); | 
|---|
|  | 1906 | #endif | 
|---|
|  | 1907 | if ( (-1) == status ) | 
|---|
|  | 1908 | { | 
|---|
|  | 1909 | status = errno; | 
|---|
|  | 1910 | sh_error_handle ((-1), FIL__, __LINE__, status, MSG_W_CHDIR, | 
|---|
| [132] | 1911 | sh_error_message (status, errbuf, sizeof(errbuf)), "/"); | 
|---|
| [1] | 1912 | aud_exit(FIL__, __LINE__, EXIT_FAILURE); | 
|---|
|  | 1913 | } | 
|---|
|  | 1914 |  | 
|---|
|  | 1915 | /* reset timers | 
|---|
|  | 1916 | */ | 
|---|
|  | 1917 | sh_unix_resettimer(); | 
|---|
|  | 1918 |  | 
|---|
|  | 1919 | /* signal handlers | 
|---|
|  | 1920 | */ | 
|---|
|  | 1921 | sh_unix_resetsignals(); | 
|---|
|  | 1922 | #if defined(SCREW_IT_UP) | 
|---|
|  | 1923 | sh_sigtrap_prepare(); | 
|---|
|  | 1924 | #endif | 
|---|
|  | 1925 | sh_unix_siginstall  (goDaemon); | 
|---|
|  | 1926 |  | 
|---|
|  | 1927 | /* set file creation mask | 
|---|
|  | 1928 | */ | 
|---|
|  | 1929 | (void) umask (0); /* should not fail */ | 
|---|
|  | 1930 |  | 
|---|
|  | 1931 | /* set resource limits to maximum, and | 
|---|
|  | 1932 | * core dump size to zero | 
|---|
|  | 1933 | */ | 
|---|
|  | 1934 | sh_unix_setlimits(); | 
|---|
|  | 1935 |  | 
|---|
|  | 1936 | /* zero out the environment (like PATH='\0') | 
|---|
|  | 1937 | */ | 
|---|
|  | 1938 | sh_unix_zeroenv(); | 
|---|
|  | 1939 |  | 
|---|
|  | 1940 | if (goDaemon == 1) | 
|---|
|  | 1941 | { | 
|---|
| [92] | 1942 | /* Close first tree file descriptors | 
|---|
| [84] | 1943 | */ | 
|---|
| [92] | 1944 | close (0);  /* if running as daemon */ | 
|---|
|  | 1945 | close (1);  /* if running as daemon */ | 
|---|
|  | 1946 | close (2);  /* if running as daemon */ | 
|---|
| [84] | 1947 |  | 
|---|
|  | 1948 | /* Enable full error logging | 
|---|
|  | 1949 | */ | 
|---|
|  | 1950 | sh_error_only_stderr (S_FALSE); | 
|---|
|  | 1951 |  | 
|---|
|  | 1952 | /* open first three streams to /dev/null | 
|---|
|  | 1953 | */ | 
|---|
|  | 1954 | status = aud_open(FIL__, __LINE__, SL_NOPRIV, _("/dev/null"), O_RDWR, 0); | 
|---|
|  | 1955 | if (status < 0) | 
|---|
|  | 1956 | { | 
|---|
|  | 1957 | status = errno; | 
|---|
|  | 1958 | sh_error_handle((-1), FIL__, __LINE__, status, MSG_E_SUBGEN, | 
|---|
| [132] | 1959 | sh_error_message(status, errbuf, sizeof(errbuf)), _("open")); | 
|---|
| [84] | 1960 | aud_exit(FIL__, __LINE__, EXIT_FAILURE); | 
|---|
|  | 1961 | } | 
|---|
|  | 1962 |  | 
|---|
|  | 1963 | status = retry_aud_dup(FIL__, __LINE__, 0); | 
|---|
|  | 1964 | if (status >= 0) | 
|---|
|  | 1965 | retry_aud_dup(FIL__, __LINE__, 0); | 
|---|
|  | 1966 |  | 
|---|
|  | 1967 | if (status < 0) | 
|---|
|  | 1968 | { | 
|---|
|  | 1969 | status = errno; | 
|---|
|  | 1970 | sh_error_handle((-1), FIL__, __LINE__, status, MSG_E_SUBGEN, | 
|---|
| [132] | 1971 | sh_error_message(status, errbuf, sizeof(errbuf)), _("dup")); | 
|---|
| [84] | 1972 | aud_exit(FIL__, __LINE__, EXIT_FAILURE); | 
|---|
|  | 1973 | } | 
|---|
|  | 1974 |  | 
|---|
| [86] | 1975 | sh_error_enable_unsafe (S_TRUE); | 
|---|
| [1] | 1976 | #if defined(HAVE_LIBPRELUDE) | 
|---|
|  | 1977 | sh_prelude_reset (); | 
|---|
|  | 1978 | #endif | 
|---|
|  | 1979 |  | 
|---|
|  | 1980 | /* --- wait until parent has exited --- | 
|---|
|  | 1981 | */ | 
|---|
|  | 1982 | while (1 == 1) | 
|---|
|  | 1983 | { | 
|---|
|  | 1984 | errno = 0; | 
|---|
|  | 1985 | if (0 > aud_kill (FIL__, __LINE__, oldpid, 0) && errno == ESRCH) | 
|---|
|  | 1986 | { | 
|---|
|  | 1987 | break; | 
|---|
|  | 1988 | } | 
|---|
|  | 1989 | retry_msleep(0, 1); | 
|---|
|  | 1990 | } | 
|---|
|  | 1991 |  | 
|---|
|  | 1992 | /* write PID file | 
|---|
|  | 1993 | */ | 
|---|
|  | 1994 | status = sh_unix_write_pid_file(); | 
|---|
|  | 1995 | if (status < 0) | 
|---|
|  | 1996 | { | 
|---|
|  | 1997 | sl_get_euid(&uid); | 
|---|
|  | 1998 | sh_error_handle ((-1), FIL__, __LINE__, status, MSG_PIDFILE, | 
|---|
|  | 1999 | (long) uid, sh.srvlog.alt); | 
|---|
|  | 2000 | aud_exit(FIL__, __LINE__, EXIT_FAILURE); | 
|---|
|  | 2001 | } | 
|---|
|  | 2002 | #if defined(SH_WITH_SERVER) | 
|---|
|  | 2003 | sh_socket_open_int (); | 
|---|
|  | 2004 | #endif | 
|---|
|  | 2005 | } | 
|---|
|  | 2006 | else | 
|---|
|  | 2007 | { | 
|---|
| [86] | 2008 | sh_error_enable_unsafe (S_TRUE); | 
|---|
| [1] | 2009 | #if defined(HAVE_LIBPRELUDE) | 
|---|
|  | 2010 | sh_prelude_reset (); | 
|---|
|  | 2011 | #endif | 
|---|
|  | 2012 | #if defined(SH_WITH_SERVER) | 
|---|
|  | 2013 | sh_socket_open_int (); | 
|---|
|  | 2014 | #endif | 
|---|
|  | 2015 | } | 
|---|
|  | 2016 |  | 
|---|
|  | 2017 | /* chroot (this is a no-op if no chroot dir is specified | 
|---|
|  | 2018 | */ | 
|---|
|  | 2019 | status = sh_unix_chroot(); | 
|---|
|  | 2020 | if (status < 0) | 
|---|
|  | 2021 | { | 
|---|
|  | 2022 | status = errno; | 
|---|
|  | 2023 | sh_error_handle((-1), FIL__, __LINE__, status, MSG_E_SUBGEN, | 
|---|
| [132] | 2024 | sh_error_message(status, errbuf, sizeof(errbuf)), _("chroot")); | 
|---|
| [1] | 2025 | aud_exit(FIL__, __LINE__, EXIT_FAILURE); | 
|---|
|  | 2026 | } | 
|---|
|  | 2027 |  | 
|---|
|  | 2028 | /* drop capabilities | 
|---|
|  | 2029 | */ | 
|---|
|  | 2030 | sl_drop_cap(); | 
|---|
|  | 2031 |  | 
|---|
|  | 2032 | SL_RETURN((0),_("sh_unix_init")); | 
|---|
|  | 2033 | } | 
|---|
|  | 2034 |  | 
|---|
| [197] | 2035 | /* --- run a command, securely --- */ | 
|---|
|  | 2036 |  | 
|---|
|  | 2037 | int sh_unix_run_command (const char * str) | 
|---|
|  | 2038 | { | 
|---|
|  | 2039 | pid_t  pid; | 
|---|
|  | 2040 | char * arg[4]; | 
|---|
|  | 2041 | char * env[5]; | 
|---|
|  | 2042 | char * path = sh_util_strdup(_("/bin/sh")); | 
|---|
|  | 2043 |  | 
|---|
|  | 2044 | int  status = -1; | 
|---|
|  | 2045 |  | 
|---|
|  | 2046 | arg[0] = sh_util_strdup(_("/bin/sh")); | 
|---|
|  | 2047 | arg[1] = sh_util_strdup(_("-c")); | 
|---|
|  | 2048 | arg[2] = sh_util_strdup(str); | 
|---|
|  | 2049 | arg[3] = NULL; | 
|---|
|  | 2050 |  | 
|---|
|  | 2051 | env[0] = sh_util_strdup(_("PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/ucb")); | 
|---|
|  | 2052 | env[1] = sh_util_strdup(_("SHELL=/bin/sh")); | 
|---|
|  | 2053 | env[2] = sh_util_strdup(_("IFS= \t\n")); | 
|---|
| [199] | 2054 | if (getenv("TZ")) {                         /* flawfinder: ignore */ | 
|---|
|  | 2055 | char * tz = sh_util_strdup(getenv("TZ")); /* flawfinder: ignore */ | 
|---|
|  | 2056 | size_t tzlen = strlen(tz); | 
|---|
|  | 2057 | if (SL_TRUE == sl_ok_adds (4, tzlen)) { | 
|---|
|  | 2058 | env[3] = SH_ALLOC(4+tzlen); | 
|---|
| [197] | 2059 | sl_strlcpy(env[3], "TZ=", 4); | 
|---|
| [199] | 2060 | sl_strlcat(env[3], tz   , 4+tzlen); | 
|---|
| [197] | 2061 | } else { | 
|---|
|  | 2062 | env[3] = NULL; | 
|---|
|  | 2063 | } | 
|---|
|  | 2064 | } else { | 
|---|
|  | 2065 | env[3] = NULL; | 
|---|
|  | 2066 | } | 
|---|
|  | 2067 | env[4] = NULL; | 
|---|
|  | 2068 |  | 
|---|
|  | 2069 | pid = fork(); | 
|---|
|  | 2070 |  | 
|---|
|  | 2071 | if (pid == (pid_t)(-1)) | 
|---|
|  | 2072 | { | 
|---|
|  | 2073 | return -1; | 
|---|
|  | 2074 | } | 
|---|
|  | 2075 |  | 
|---|
|  | 2076 | else if (pid == 0) /* child */ | 
|---|
|  | 2077 | { | 
|---|
|  | 2078 | memset(skey, 0, sizeof(sh_key_t)); | 
|---|
|  | 2079 | (void) umask(S_IRGRP|S_IWGRP|S_IXGRP|S_IROTH|S_IWOTH|S_IXOTH); | 
|---|
|  | 2080 | sh_unix_closeall (3, -1, SL_TRUE); /* in child process */ | 
|---|
|  | 2081 | execve(path, arg, env); | 
|---|
|  | 2082 | _exit(EXIT_FAILURE); | 
|---|
|  | 2083 | } | 
|---|
|  | 2084 |  | 
|---|
|  | 2085 | else /* parent */ | 
|---|
|  | 2086 | { | 
|---|
|  | 2087 | int r; | 
|---|
|  | 2088 |  | 
|---|
| [203] | 2089 | while((r = waitpid(pid, &status, WUNTRACED)) != pid && r != -1) ; | 
|---|
| [197] | 2090 |  | 
|---|
| [199] | 2091 | #if !defined(USE_UNO) | 
|---|
| [197] | 2092 | if (r == -1 || !WIFEXITED(status)) | 
|---|
|  | 2093 | { | 
|---|
|  | 2094 | status = -1; | 
|---|
|  | 2095 | } | 
|---|
|  | 2096 | else | 
|---|
|  | 2097 | { | 
|---|
|  | 2098 | status = WEXITSTATUS(status); | 
|---|
|  | 2099 | } | 
|---|
| [199] | 2100 | #endif | 
|---|
| [197] | 2101 | } | 
|---|
|  | 2102 |  | 
|---|
|  | 2103 | return status; | 
|---|
|  | 2104 | } | 
|---|
|  | 2105 |  | 
|---|
| [1] | 2106 | /******************************************************** | 
|---|
|  | 2107 | * | 
|---|
|  | 2108 | *  TIME | 
|---|
|  | 2109 | * | 
|---|
|  | 2110 | ********************************************************/ | 
|---|
|  | 2111 |  | 
|---|
|  | 2112 | /* Figure out the time offset of the current timezone | 
|---|
|  | 2113 | * in a portable way. | 
|---|
|  | 2114 | */ | 
|---|
|  | 2115 | char * t_zone(const time_t * xx) | 
|---|
|  | 2116 | { | 
|---|
|  | 2117 | struct tm   aa; | 
|---|
|  | 2118 | struct tm   bb; | 
|---|
|  | 2119 | struct tm * cc; | 
|---|
|  | 2120 | int  sign =  0; | 
|---|
|  | 2121 | int  diff =  0; | 
|---|
|  | 2122 | int  hh, mm; | 
|---|
|  | 2123 | static char tz[64]; | 
|---|
|  | 2124 |  | 
|---|
|  | 2125 | SL_ENTER(_("t_zone")); | 
|---|
|  | 2126 |  | 
|---|
| [131] | 2127 | #if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GMTIME_R) | 
|---|
|  | 2128 | cc = gmtime_r (xx, &aa); | 
|---|
|  | 2129 | #else | 
|---|
| [1] | 2130 | cc = gmtime (xx); | 
|---|
|  | 2131 | memcpy (&aa, cc, sizeof(struct tm)); | 
|---|
| [131] | 2132 | #endif | 
|---|
|  | 2133 |  | 
|---|
|  | 2134 | #if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_LOCALTIME_R) | 
|---|
|  | 2135 | cc = localtime_r (xx, &bb); | 
|---|
|  | 2136 | #else | 
|---|
| [1] | 2137 | cc = localtime (xx); | 
|---|
|  | 2138 | memcpy (&bb, cc, sizeof(struct tm)); | 
|---|
| [131] | 2139 | #endif | 
|---|
| [1] | 2140 |  | 
|---|
|  | 2141 | /* Check for datum wrap-around. | 
|---|
|  | 2142 | */ | 
|---|
|  | 2143 | if      (aa.tm_year < bb.tm_year) | 
|---|
|  | 2144 | sign = (-1); | 
|---|
|  | 2145 | else if (aa.tm_mon  < bb.tm_mon) | 
|---|
|  | 2146 | sign = (-1); | 
|---|
|  | 2147 | else if (aa.tm_mday < bb.tm_mday) | 
|---|
|  | 2148 | sign = (-1); | 
|---|
|  | 2149 | else if (bb.tm_year < aa.tm_year) | 
|---|
|  | 2150 | sign = ( 1); | 
|---|
|  | 2151 | else if (bb.tm_mon  < aa.tm_mon) | 
|---|
|  | 2152 | sign = ( 1); | 
|---|
|  | 2153 | else if (bb.tm_mday < aa.tm_mday) | 
|---|
|  | 2154 | sign = ( 1); | 
|---|
|  | 2155 |  | 
|---|
|  | 2156 | diff = aa.tm_hour * 60 + aa.tm_min; | 
|---|
|  | 2157 | diff = (bb.tm_hour * 60 + bb.tm_min) - diff; | 
|---|
|  | 2158 | diff = diff - (sign * 24 * 60);   /* datum wrap-around correction */ | 
|---|
|  | 2159 | hh = diff / 60; | 
|---|
|  | 2160 | mm = diff - (hh * 60); | 
|---|
|  | 2161 | sprintf (tz, _("%+03d%02d"), hh, mm);                /* known to fit  */ | 
|---|
|  | 2162 |  | 
|---|
|  | 2163 | SL_RETURN(tz, _("t_zone")); | 
|---|
|  | 2164 | } | 
|---|
|  | 2165 |  | 
|---|
|  | 2166 | unsigned long sh_unix_longtime () | 
|---|
|  | 2167 | { | 
|---|
|  | 2168 | return ((unsigned long)time(NULL)); | 
|---|
|  | 2169 | } | 
|---|
|  | 2170 |  | 
|---|
|  | 2171 | #ifdef HAVE_GETTIMEOFDAY | 
|---|
|  | 2172 | unsigned long sh_unix_notime () | 
|---|
|  | 2173 | { | 
|---|
|  | 2174 | struct timeval  tv; | 
|---|
|  | 2175 |  | 
|---|
|  | 2176 | gettimeofday (&tv, NULL); | 
|---|
|  | 2177 |  | 
|---|
|  | 2178 | return ((unsigned long)(tv.tv_sec + tv.tv_usec * 10835 + getpid() + getppid())); | 
|---|
|  | 2179 |  | 
|---|
|  | 2180 | } | 
|---|
|  | 2181 | #endif | 
|---|
|  | 2182 |  | 
|---|
|  | 2183 | static int count_dev_time = 0; | 
|---|
|  | 2184 |  | 
|---|
|  | 2185 | void reset_count_dev_time(void) | 
|---|
|  | 2186 | { | 
|---|
|  | 2187 | count_dev_time = 0; | 
|---|
|  | 2188 | return; | 
|---|
|  | 2189 | } | 
|---|
|  | 2190 |  | 
|---|
| [22] | 2191 | int sh_unix_settimeserver (const char * address) | 
|---|
| [1] | 2192 | { | 
|---|
|  | 2193 |  | 
|---|
|  | 2194 | SL_ENTER(_("sh_unix_settimeserver")); | 
|---|
|  | 2195 |  | 
|---|
|  | 2196 | if (address != NULL && count_dev_time < 2 | 
|---|
|  | 2197 | && sl_strlen(address) < SH_PATHBUF) | 
|---|
|  | 2198 | { | 
|---|
|  | 2199 | if (count_dev_time == 0) | 
|---|
|  | 2200 | sl_strlcpy (sh.srvtime.name, address, SH_PATHBUF); | 
|---|
|  | 2201 | else | 
|---|
|  | 2202 | sl_strlcpy (sh.srvtime.alt,  address, SH_PATHBUF); | 
|---|
|  | 2203 |  | 
|---|
|  | 2204 | ++count_dev_time; | 
|---|
|  | 2205 | SL_RETURN((0), _("sh_unix_settimeserver")); | 
|---|
|  | 2206 | } | 
|---|
|  | 2207 | SL_RETURN((-1), _("sh_unix_settimeserver")); | 
|---|
|  | 2208 | } | 
|---|
|  | 2209 |  | 
|---|
|  | 2210 |  | 
|---|
|  | 2211 | #ifdef HAVE_NTIME | 
|---|
|  | 2212 | #define UNIXEPOCH 2208988800UL  /* difference between Unix time and net time | 
|---|
|  | 2213 | * The UNIX EPOCH starts in 1970. | 
|---|
|  | 2214 | */ | 
|---|
|  | 2215 | #include <sys/socket.h> | 
|---|
|  | 2216 | #include <netinet/in.h> | 
|---|
|  | 2217 | #include <arpa/inet.h> | 
|---|
|  | 2218 | #include <netdb.h> | 
|---|
|  | 2219 | #include <ctype.h> | 
|---|
|  | 2220 | #endif | 
|---|
|  | 2221 |  | 
|---|
|  | 2222 | /* Timeserver service.               */ | 
|---|
|  | 2223 | /* define is missing on HP-UX 10.20  */ | 
|---|
|  | 2224 | #ifndef IPPORT_TIMESERVER | 
|---|
|  | 2225 | #define IPPORT_TIMESERVER 37 | 
|---|
|  | 2226 | #endif | 
|---|
|  | 2227 |  | 
|---|
| [132] | 2228 | char * sh_unix_time (time_t thetime, char * buffer, size_t len) | 
|---|
| [1] | 2229 | { | 
|---|
|  | 2230 |  | 
|---|
|  | 2231 | int           status; | 
|---|
| [132] | 2232 | char          AsciiTime[81];                       /* local time   */ | 
|---|
| [1] | 2233 | time_t        time_now; | 
|---|
|  | 2234 | struct tm   * time_ptr; | 
|---|
| [131] | 2235 | #if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_LOCALTIME_R) | 
|---|
|  | 2236 | struct tm     time_tm; | 
|---|
|  | 2237 | #endif | 
|---|
| [1] | 2238 | #ifdef SH_USE_XML | 
|---|
|  | 2239 | static char   deftime[] = N_("0000-00-00T00:00:00"); /* default time */ | 
|---|
|  | 2240 | #else | 
|---|
|  | 2241 | static char   deftime[] = N_("[0000-00-00T00:00:00]"); /* default time */ | 
|---|
|  | 2242 | #endif | 
|---|
|  | 2243 |  | 
|---|
|  | 2244 | #ifdef HAVE_NTIME | 
|---|
|  | 2245 | int    fd;                    /* network file descriptor                  */ | 
|---|
|  | 2246 | u_char net_time[4];           /* remote time in network format            */ | 
|---|
|  | 2247 | static int failerr = 0;       /* no net time                              */ | 
|---|
|  | 2248 | int    fail = 0;              /* no net time                              */ | 
|---|
|  | 2249 | int    errflag; | 
|---|
|  | 2250 | char   errmsg[256]; | 
|---|
|  | 2251 | char   error_call[SH_MINIBUF]; | 
|---|
|  | 2252 | int    error_num; | 
|---|
|  | 2253 | #endif | 
|---|
|  | 2254 |  | 
|---|
|  | 2255 | SL_ENTER(_("sh_unix_time")); | 
|---|
|  | 2256 |  | 
|---|
|  | 2257 | #ifdef HAVE_NTIME | 
|---|
|  | 2258 | if (thetime == 0) | 
|---|
|  | 2259 | { | 
|---|
|  | 2260 | if (sh.srvtime.name[0] == '\0') | 
|---|
|  | 2261 | { | 
|---|
|  | 2262 | fail = 1; | 
|---|
|  | 2263 | (void) time (&time_now); | 
|---|
|  | 2264 | } | 
|---|
|  | 2265 | else /* have a timeserver address */ | 
|---|
|  | 2266 | { | 
|---|
|  | 2267 | fd = connect_port_2 (sh.srvtime.name, sh.srvtime.alt, | 
|---|
|  | 2268 | IPPORT_TIMESERVER, | 
|---|
|  | 2269 | error_call, &error_num, errmsg, sizeof(errmsg)); | 
|---|
|  | 2270 | if (fd >= 0) | 
|---|
|  | 2271 | { | 
|---|
|  | 2272 | if (4 != read_port (fd, (char *) net_time, 4, &errflag, 2)) | 
|---|
|  | 2273 | { | 
|---|
|  | 2274 | fail = 1; | 
|---|
|  | 2275 | sh_error_handle ((-1), FIL__, __LINE__, errflag, | 
|---|
|  | 2276 | MSG_E_NLOST, | 
|---|
|  | 2277 | _("time"), sh.srvtime.name); | 
|---|
|  | 2278 | } | 
|---|
|  | 2279 | close(fd); | 
|---|
|  | 2280 | } | 
|---|
|  | 2281 | else | 
|---|
|  | 2282 | { | 
|---|
|  | 2283 | sh_error_handle ((-1), FIL__, __LINE__, error_num, | 
|---|
|  | 2284 | MSG_E_NET, errmsg, error_call, | 
|---|
|  | 2285 | _("time"), sh.srvtime.name); | 
|---|
|  | 2286 | fail = 1; | 
|---|
|  | 2287 | } | 
|---|
|  | 2288 |  | 
|---|
|  | 2289 | if (fail == 0) | 
|---|
|  | 2290 | { | 
|---|
|  | 2291 | time_now = ntohl(* (long *) net_time) - UNIXEPOCH; | 
|---|
|  | 2292 | /* fprintf(stderr, "TIME IS %ld\n", time_now); */ | 
|---|
|  | 2293 | if (failerr == 1) { | 
|---|
|  | 2294 | failerr = 0; | 
|---|
|  | 2295 | sh_error_handle ((-1), FIL__, __LINE__, 0, | 
|---|
|  | 2296 | MSG_E_NEST, | 
|---|
|  | 2297 | _("time"), sh.srvtime.name); | 
|---|
|  | 2298 | } | 
|---|
|  | 2299 | } | 
|---|
|  | 2300 | else | 
|---|
|  | 2301 | { | 
|---|
|  | 2302 | (void) time (&time_now); | 
|---|
|  | 2303 | if (failerr == 0) | 
|---|
|  | 2304 | { | 
|---|
|  | 2305 | failerr = 1; | 
|---|
|  | 2306 | sh_error_handle ((-1), FIL__, __LINE__, errflag, | 
|---|
|  | 2307 | MSG_SRV_FAIL, | 
|---|
|  | 2308 | _("time"), sh.srvtime.name); | 
|---|
|  | 2309 | } | 
|---|
|  | 2310 | } | 
|---|
|  | 2311 | } | 
|---|
|  | 2312 | } | 
|---|
|  | 2313 | else | 
|---|
|  | 2314 | { | 
|---|
|  | 2315 | time_now = thetime; | 
|---|
|  | 2316 | } | 
|---|
|  | 2317 |  | 
|---|
|  | 2318 | /* #ifdef HAVE_NTIME */ | 
|---|
|  | 2319 | #else | 
|---|
|  | 2320 |  | 
|---|
|  | 2321 | if (thetime == 0) | 
|---|
|  | 2322 | { | 
|---|
|  | 2323 | (void) time (&time_now); | 
|---|
|  | 2324 | } | 
|---|
|  | 2325 | else | 
|---|
|  | 2326 | { | 
|---|
|  | 2327 | time_now = thetime; | 
|---|
|  | 2328 | } | 
|---|
|  | 2329 |  | 
|---|
|  | 2330 | /* #ifdef HAVE_NTIME */ | 
|---|
|  | 2331 | #endif | 
|---|
|  | 2332 |  | 
|---|
| [132] | 2333 | if (time_now == (-1) ) | 
|---|
|  | 2334 | { | 
|---|
|  | 2335 | sl_strlcpy(buffer, _(deftime), len); | 
|---|
|  | 2336 | SL_RETURN(buffer, _("sh_unix_time")); | 
|---|
|  | 2337 | } | 
|---|
| [1] | 2338 | else | 
|---|
| [131] | 2339 | { | 
|---|
|  | 2340 | #if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_LOCALTIME_R) | 
|---|
|  | 2341 | time_ptr   = localtime_r (&time_now, &time_tm); | 
|---|
|  | 2342 | #else | 
|---|
|  | 2343 | time_ptr   = localtime (&time_now); | 
|---|
|  | 2344 | #endif | 
|---|
|  | 2345 | } | 
|---|
| [1] | 2346 | if (time_ptr != NULL) | 
|---|
|  | 2347 | { | 
|---|
| [132] | 2348 | status = strftime (AsciiTime, sizeof(AsciiTime), | 
|---|
| [1] | 2349 | #ifdef SH_USE_XML | 
|---|
|  | 2350 | _("%Y-%m-%dT%H:%M:%S%%s"), | 
|---|
|  | 2351 | #else | 
|---|
|  | 2352 | _("[%Y-%m-%dT%H:%M:%S%%s]"), | 
|---|
|  | 2353 | #endif | 
|---|
|  | 2354 | time_ptr); | 
|---|
|  | 2355 |  | 
|---|
| [132] | 2356 | sl_snprintf(buffer, len, AsciiTime, t_zone(&time_now)); | 
|---|
| [1] | 2357 |  | 
|---|
| [132] | 2358 | if ( (status == 0) || (status == sizeof(AsciiTime)) ) | 
|---|
|  | 2359 | { | 
|---|
|  | 2360 | sl_strlcpy(buffer, _(deftime), len); | 
|---|
|  | 2361 | SL_RETURN( buffer, _("sh_unix_time")); | 
|---|
|  | 2362 | } | 
|---|
| [1] | 2363 | else | 
|---|
| [132] | 2364 | { | 
|---|
|  | 2365 | SL_RETURN(buffer, _("sh_unix_time")); | 
|---|
|  | 2366 | } | 
|---|
| [1] | 2367 | } | 
|---|
|  | 2368 |  | 
|---|
|  | 2369 | /* last resort | 
|---|
|  | 2370 | */ | 
|---|
| [132] | 2371 | sl_strlcpy(buffer, _(deftime), len); | 
|---|
|  | 2372 | SL_RETURN( buffer, _("sh_unix_time")); | 
|---|
| [1] | 2373 | } | 
|---|
|  | 2374 |  | 
|---|
|  | 2375 | static int sh_unix_use_localtime = S_FALSE; | 
|---|
|  | 2376 |  | 
|---|
|  | 2377 | /* whether to use localtime for file timesatams in logs | 
|---|
|  | 2378 | */ | 
|---|
| [22] | 2379 | int sh_unix_uselocaltime (const char * c) | 
|---|
| [1] | 2380 | { | 
|---|
|  | 2381 | int i; | 
|---|
|  | 2382 | SL_ENTER(_("sh_unix_uselocaltime")); | 
|---|
|  | 2383 | i = sh_util_flagval(c, &(sh_unix_use_localtime)); | 
|---|
|  | 2384 |  | 
|---|
|  | 2385 | SL_RETURN(i, _("sh_unix_uselocaltime")); | 
|---|
|  | 2386 | } | 
|---|
|  | 2387 |  | 
|---|
| [132] | 2388 | char * sh_unix_gmttime (time_t thetime, char * buffer, size_t len) | 
|---|
| [1] | 2389 | { | 
|---|
|  | 2390 |  | 
|---|
|  | 2391 | int           status; | 
|---|
|  | 2392 |  | 
|---|
|  | 2393 | struct tm   * time_ptr; | 
|---|
| [131] | 2394 | #if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) | 
|---|
|  | 2395 | struct tm     time_tm; | 
|---|
|  | 2396 | #endif | 
|---|
| [132] | 2397 | char   AsciiTime[81];                       /* GMT time   */ | 
|---|
| [1] | 2398 | #ifdef SH_USE_XML | 
|---|
|  | 2399 | static char   deftime[] = N_("0000-00-00T00:00:00"); /* default time */ | 
|---|
|  | 2400 | #else | 
|---|
|  | 2401 | static char   deftime[] = N_("[0000-00-00T00:00:00]"); /* default time */ | 
|---|
|  | 2402 | #endif | 
|---|
|  | 2403 |  | 
|---|
|  | 2404 | SL_ENTER(_("sh_unix_gmttime")); | 
|---|
|  | 2405 |  | 
|---|
|  | 2406 | if (sh_unix_use_localtime == S_FALSE) | 
|---|
| [131] | 2407 | { | 
|---|
|  | 2408 | #if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GMTIME_R) | 
|---|
|  | 2409 | time_ptr   = gmtime_r (&thetime, &time_tm); | 
|---|
|  | 2410 | #else | 
|---|
|  | 2411 | time_ptr   = gmtime (&thetime); | 
|---|
|  | 2412 | #endif | 
|---|
|  | 2413 | } | 
|---|
| [1] | 2414 | else | 
|---|
| [131] | 2415 | { | 
|---|
|  | 2416 | #if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_LOCALTIME_R) | 
|---|
|  | 2417 | time_ptr   = localtime_r (&thetime, &time_tm); | 
|---|
|  | 2418 | #else | 
|---|
|  | 2419 | time_ptr   = localtime (&thetime); | 
|---|
|  | 2420 | #endif | 
|---|
|  | 2421 | } | 
|---|
| [1] | 2422 | if (time_ptr != NULL) | 
|---|
|  | 2423 | { | 
|---|
|  | 2424 | status = strftime (AsciiTime, 80, | 
|---|
|  | 2425 | #ifdef SH_USE_XML | 
|---|
|  | 2426 | _("%Y-%m-%dT%H:%M:%S"), | 
|---|
|  | 2427 | #else | 
|---|
|  | 2428 | _("[%Y-%m-%dT%H:%M:%S]"), | 
|---|
|  | 2429 | #endif | 
|---|
|  | 2430 | time_ptr); | 
|---|
|  | 2431 |  | 
|---|
| [132] | 2432 | if ( (status == 0) || (status == 80) ) | 
|---|
|  | 2433 | sl_strlcpy(buffer, _(deftime), len); | 
|---|
| [1] | 2434 | else | 
|---|
| [132] | 2435 | sl_strlcpy(buffer, AsciiTime, len); | 
|---|
|  | 2436 | SL_RETURN( buffer, _("sh_unix_gmttime")); | 
|---|
| [1] | 2437 | } | 
|---|
|  | 2438 |  | 
|---|
|  | 2439 | /* last resort | 
|---|
|  | 2440 | */ | 
|---|
| [132] | 2441 | sl_strlcpy(buffer, _(deftime), len); | 
|---|
|  | 2442 | SL_RETURN( buffer, _("sh_unix_gmttime")); | 
|---|
| [1] | 2443 | } | 
|---|
|  | 2444 |  | 
|---|
|  | 2445 |  | 
|---|
| [132] | 2446 | char *  sh_unix_getUIDdir (int level, uid_t uid, char * out, size_t len) | 
|---|
| [1] | 2447 | { | 
|---|
|  | 2448 | struct passwd * tempres; | 
|---|
|  | 2449 | int    status = 0; | 
|---|
| [131] | 2450 | #if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GETPWUID_R) | 
|---|
|  | 2451 | struct passwd pwd; | 
|---|
|  | 2452 | char   buffer[SH_PWBUF_SIZE]; | 
|---|
|  | 2453 | #endif | 
|---|
| [132] | 2454 | char errbuf[SH_ERRBUF_SIZE]; | 
|---|
| [1] | 2455 |  | 
|---|
|  | 2456 | SL_ENTER(_("sh_unix_getUIDdir")); | 
|---|
|  | 2457 |  | 
|---|
| [131] | 2458 | #if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GETPWUID_R) | 
|---|
|  | 2459 | sh_getpwuid_r(uid, &pwd, buffer, sizeof(buffer), &tempres); | 
|---|
|  | 2460 | #else | 
|---|
| [1] | 2461 | errno = 0; | 
|---|
|  | 2462 | tempres = sh_getpwuid(uid); | 
|---|
|  | 2463 | status = errno; | 
|---|
| [131] | 2464 | #endif | 
|---|
| [1] | 2465 |  | 
|---|
|  | 2466 | if (tempres == NULL) { | 
|---|
|  | 2467 | sh_error_handle (level, FIL__, __LINE__, EINVAL, MSG_E_PWNULL, | 
|---|
| [132] | 2468 | sh_error_message(status, errbuf, sizeof(errbuf)), | 
|---|
| [1] | 2469 | _("getpwuid"), (long) uid, _("completely missing")); | 
|---|
|  | 2470 | SL_RETURN( NULL, _("sh_unix_getUIDdir")); | 
|---|
|  | 2471 | } | 
|---|
|  | 2472 |  | 
|---|
|  | 2473 | if (tempres->pw_dir != NULL) { | 
|---|
| [132] | 2474 | sl_strlcpy(out, tempres->pw_dir, len); | 
|---|
|  | 2475 | SL_RETURN( out, _("sh_unix_getUIDdir")); | 
|---|
| [1] | 2476 | } else { | 
|---|
|  | 2477 | sh_error_handle (level, FIL__, __LINE__, EINVAL, MSG_E_PWNULL, | 
|---|
| [132] | 2478 | sh_error_message(status, errbuf, sizeof(errbuf)), | 
|---|
| [1] | 2479 | _("getpwuid"), (long) uid, _("pw_dir")); | 
|---|
|  | 2480 | SL_RETURN( NULL, _("sh_unix_getUIDdir")); | 
|---|
|  | 2481 | } | 
|---|
|  | 2482 | } | 
|---|
|  | 2483 |  | 
|---|
| [133] | 2484 | SH_MUTEX_STATIC(mutex_getUIDname, PTHREAD_MUTEX_INITIALIZER); | 
|---|
| [132] | 2485 |  | 
|---|
|  | 2486 | char *  sh_unix_getUIDname (int level, uid_t uid, char * out, size_t len) | 
|---|
| [1] | 2487 | { | 
|---|
|  | 2488 | struct passwd * tempres; | 
|---|
| [131] | 2489 | #if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GETPWUID_R) | 
|---|
|  | 2490 | struct passwd pwd; | 
|---|
|  | 2491 | char   buffer[SH_PWBUF_SIZE]; | 
|---|
|  | 2492 | #endif | 
|---|
| [1] | 2493 | int             status = 0; | 
|---|
|  | 2494 | static uid_t    old_uid; | 
|---|
|  | 2495 | static char     name[32] = { '\0' }; | 
|---|
| [132] | 2496 | char errbuf[SH_ERRBUF_SIZE]; | 
|---|
| [1] | 2497 |  | 
|---|
|  | 2498 | SL_ENTER(_("sh_unix_getUIDname")); | 
|---|
|  | 2499 |  | 
|---|
|  | 2500 | if ((uid == old_uid) && (name[0] != '\0')) { | 
|---|
| [132] | 2501 | out[0] = '\0'; | 
|---|
| [133] | 2502 | SH_MUTEX_LOCK_UNSAFE(mutex_getUIDname); | 
|---|
| [132] | 2503 | if ((uid == old_uid) && (name[0] != '\0')) { | 
|---|
|  | 2504 | sl_strlcpy(out, name, len); | 
|---|
|  | 2505 | } | 
|---|
| [133] | 2506 | SH_MUTEX_UNLOCK_UNSAFE(mutex_getUIDname); | 
|---|
| [132] | 2507 | if (out[0] != '\0') | 
|---|
|  | 2508 | SL_RETURN( out, _("sh_unix_getUIDname")); | 
|---|
| [1] | 2509 | } | 
|---|
|  | 2510 |  | 
|---|
| [131] | 2511 | #if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GETPWUID_R) | 
|---|
|  | 2512 | sh_getpwuid_r(uid, &pwd, buffer, sizeof(buffer), &tempres); | 
|---|
|  | 2513 | #else | 
|---|
| [1] | 2514 | errno = 0; | 
|---|
|  | 2515 | tempres = sh_getpwuid(uid); | 
|---|
|  | 2516 | status = errno; | 
|---|
| [131] | 2517 | #endif | 
|---|
| [1] | 2518 |  | 
|---|
|  | 2519 | if (tempres == NULL) { | 
|---|
|  | 2520 | sh_error_handle (level, FIL__, __LINE__, EINVAL, MSG_E_PWNULL, | 
|---|
| [132] | 2521 | sh_error_message(status, errbuf, sizeof(errbuf)), | 
|---|
| [1] | 2522 | _("getpwuid"), (long) uid, _("completely missing")); | 
|---|
|  | 2523 | SL_RETURN( NULL, _("sh_unix_getUIDname")); | 
|---|
|  | 2524 | } | 
|---|
|  | 2525 |  | 
|---|
|  | 2526 |  | 
|---|
|  | 2527 | if (tempres->pw_name != NULL) { | 
|---|
| [133] | 2528 | SH_MUTEX_LOCK_UNSAFE(mutex_getUIDname); | 
|---|
| [1] | 2529 | sl_strlcpy(name, tempres->pw_name, sizeof(name)); | 
|---|
|  | 2530 | old_uid = uid; | 
|---|
| [132] | 2531 | sl_strlcpy(out, name, len); | 
|---|
| [133] | 2532 | SH_MUTEX_UNLOCK_UNSAFE(mutex_getUIDname); | 
|---|
| [132] | 2533 | SL_RETURN( out, _("sh_unix_getUIDname")); | 
|---|
| [1] | 2534 | } else { | 
|---|
|  | 2535 | sh_error_handle (level, FIL__, __LINE__, EINVAL, MSG_E_PWNULL, | 
|---|
| [132] | 2536 | sh_error_message(status, errbuf, sizeof(errbuf)), | 
|---|
| [1] | 2537 | _("getpwuid"), (long) uid, _("pw_user")); | 
|---|
|  | 2538 | SL_RETURN( NULL, _("sh_unix_getUIDname")); | 
|---|
|  | 2539 | } | 
|---|
|  | 2540 | } | 
|---|
|  | 2541 |  | 
|---|
| [133] | 2542 | SH_MUTEX_STATIC(mutex_getGIDname, PTHREAD_MUTEX_INITIALIZER); | 
|---|
| [132] | 2543 |  | 
|---|
|  | 2544 | char *  sh_unix_getGIDname (int level, gid_t gid, char * out, size_t len) | 
|---|
| [1] | 2545 | { | 
|---|
|  | 2546 | struct group  * tempres; | 
|---|
|  | 2547 | int             status = 0; | 
|---|
|  | 2548 | static gid_t    old_gid; | 
|---|
|  | 2549 | static char     name[32] = { '\0' }; | 
|---|
| [131] | 2550 | #if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GETGRGID_R) | 
|---|
|  | 2551 | struct group    grp; | 
|---|
|  | 2552 | char            buffer[SH_GRBUF_SIZE]; | 
|---|
|  | 2553 | #endif | 
|---|
| [132] | 2554 | char errbuf[SH_ERRBUF_SIZE]; | 
|---|
| [131] | 2555 |  | 
|---|
| [1] | 2556 |  | 
|---|
|  | 2557 | SL_ENTER(_("sh_unix_getGIDname")); | 
|---|
|  | 2558 |  | 
|---|
|  | 2559 | if ((gid == old_gid) && (name[0] != '\0')) { | 
|---|
| [132] | 2560 | out[0] = '\0'; | 
|---|
| [133] | 2561 | SH_MUTEX_LOCK_UNSAFE(mutex_getGIDname); | 
|---|
| [132] | 2562 | if ((gid == old_gid) && (name[0] != '\0')) { | 
|---|
|  | 2563 | sl_strlcpy(out, name, len); | 
|---|
|  | 2564 | } | 
|---|
| [133] | 2565 | SH_MUTEX_UNLOCK_UNSAFE(mutex_getGIDname); | 
|---|
| [132] | 2566 | if (out[0] != '\0') | 
|---|
|  | 2567 | SL_RETURN( out, _("sh_unix_getGIDname")); | 
|---|
| [1] | 2568 | } | 
|---|
| [132] | 2569 |  | 
|---|
| [131] | 2570 | #if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GETGRGID_R) | 
|---|
|  | 2571 | status = sh_getgrgid_r(gid, &grp, buffer, sizeof(buffer), &tempres); | 
|---|
|  | 2572 | #else | 
|---|
| [1] | 2573 | errno = 0; | 
|---|
|  | 2574 | tempres = sh_getgrgid(gid); | 
|---|
|  | 2575 | status = errno; | 
|---|
| [131] | 2576 | #endif | 
|---|
| [1] | 2577 |  | 
|---|
|  | 2578 | if (tempres == NULL) { | 
|---|
|  | 2579 | sh_error_handle (level, FIL__, __LINE__, EINVAL, MSG_E_GRNULL, | 
|---|
| [132] | 2580 | sh_error_message(status, errbuf, sizeof(errbuf)), | 
|---|
| [1] | 2581 | _("getgrgid"), (long) gid, _("completely missing")); | 
|---|
|  | 2582 |  | 
|---|
|  | 2583 | SL_RETURN( NULL, _("sh_unix_getGIDname")); | 
|---|
|  | 2584 | } | 
|---|
|  | 2585 |  | 
|---|
|  | 2586 | if (tempres->gr_name != NULL) { | 
|---|
| [133] | 2587 | SH_MUTEX_LOCK_UNSAFE(mutex_getGIDname); | 
|---|
| [1] | 2588 | sl_strlcpy(name, tempres->gr_name, sizeof(name)); | 
|---|
|  | 2589 | old_gid = gid; | 
|---|
| [132] | 2590 | sl_strlcpy(out, name, len); | 
|---|
| [133] | 2591 | SH_MUTEX_UNLOCK_UNSAFE(mutex_getGIDname); | 
|---|
| [132] | 2592 | SL_RETURN( out, _("sh_unix_getGIDname")); | 
|---|
| [1] | 2593 | } else { | 
|---|
|  | 2594 | sh_error_handle (level, FIL__, __LINE__, EINVAL, MSG_E_GRNULL, | 
|---|
| [132] | 2595 | sh_error_message(status, errbuf, sizeof(errbuf)), | 
|---|
| [1] | 2596 | _("getgrgid"), (long) gid, _("gr_name")); | 
|---|
|  | 2597 | SL_RETURN( NULL, _("sh_unix_getGIDname")); | 
|---|
|  | 2598 | } | 
|---|
|  | 2599 | } | 
|---|
|  | 2600 |  | 
|---|
|  | 2601 | int sh_unix_getUser () | 
|---|
|  | 2602 | { | 
|---|
|  | 2603 | char          * p; | 
|---|
|  | 2604 | uid_t  seuid, sruid; | 
|---|
| [132] | 2605 | char   user[USER_MAX]; | 
|---|
|  | 2606 | char   dir[SH_PATHBUF]; | 
|---|
| [1] | 2607 |  | 
|---|
|  | 2608 | SL_ENTER(_("sh_unix_getUser")); | 
|---|
|  | 2609 |  | 
|---|
|  | 2610 | seuid =  geteuid(); | 
|---|
|  | 2611 |  | 
|---|
|  | 2612 | sh.effective.uid = seuid; | 
|---|
|  | 2613 |  | 
|---|
| [132] | 2614 | p = sh_unix_getUIDdir (SH_ERR_ERR, seuid, dir, sizeof(dir)); | 
|---|
| [1] | 2615 |  | 
|---|
|  | 2616 | if (p == NULL) | 
|---|
|  | 2617 | SL_RETURN((-1), _("sh_unix_getUser")); | 
|---|
|  | 2618 | else | 
|---|
|  | 2619 | { | 
|---|
|  | 2620 | if (sl_strlen(p) >= SH_PATHBUF) { | 
|---|
|  | 2621 | sh_error_handle (SH_ERR_ERR, FIL__, __LINE__, EINVAL, MSG_E_PWLONG, | 
|---|
|  | 2622 | _("getpwuid"), (long) seuid, _("pw_home")); | 
|---|
|  | 2623 | SL_RETURN((-1), _("sh_unix_getUser")); | 
|---|
|  | 2624 | } else { | 
|---|
|  | 2625 | sl_strlcpy ( sh.effective.home, p, SH_PATHBUF); | 
|---|
|  | 2626 | } | 
|---|
|  | 2627 | } | 
|---|
|  | 2628 |  | 
|---|
|  | 2629 | sruid = getuid(); | 
|---|
|  | 2630 |  | 
|---|
|  | 2631 | sh.real.uid = sruid; | 
|---|
|  | 2632 |  | 
|---|
| [132] | 2633 | p = sh_unix_getUIDname (SH_ERR_ERR, sruid, user, sizeof(user)); | 
|---|
| [1] | 2634 | if (p == NULL) | 
|---|
|  | 2635 | SL_RETURN((-1), _("sh_unix_getUser")); | 
|---|
|  | 2636 | else | 
|---|
|  | 2637 | { | 
|---|
|  | 2638 | if (sl_strlen(p) >= USER_MAX) { | 
|---|
|  | 2639 | sh_error_handle (SH_ERR_ERR, FIL__, __LINE__, EINVAL, MSG_E_PWLONG, | 
|---|
|  | 2640 | _("getpwuid"), (long) sruid, _("pw_user")); | 
|---|
|  | 2641 | SL_RETURN((-1), _("sh_unix_getUser")); | 
|---|
|  | 2642 | } else { | 
|---|
|  | 2643 | sl_strlcpy ( sh.real.user, p, USER_MAX); | 
|---|
|  | 2644 | } | 
|---|
|  | 2645 | } | 
|---|
|  | 2646 |  | 
|---|
| [132] | 2647 | p = sh_unix_getUIDdir (SH_ERR_ERR, sruid, dir, sizeof(dir)); | 
|---|
| [1] | 2648 |  | 
|---|
|  | 2649 | if (p == NULL) | 
|---|
|  | 2650 | SL_RETURN((-1), _("sh_unix_getUser")); | 
|---|
|  | 2651 | else | 
|---|
|  | 2652 | { | 
|---|
|  | 2653 | if (sl_strlen(p) >= SH_PATHBUF) { | 
|---|
|  | 2654 | sh_error_handle (SH_ERR_ERR, FIL__, __LINE__, EINVAL, MSG_E_PWLONG, | 
|---|
|  | 2655 | _("getpwuid"), (long) sruid, _("pw_home")); | 
|---|
|  | 2656 | SL_RETURN((-1), _("sh_unix_getUser")); | 
|---|
|  | 2657 | } else { | 
|---|
|  | 2658 | sl_strlcpy ( sh.real.home, p, SH_PATHBUF); | 
|---|
|  | 2659 | } | 
|---|
|  | 2660 | } | 
|---|
|  | 2661 |  | 
|---|
|  | 2662 | SL_RETURN((0), _("sh_unix_getUser")); | 
|---|
|  | 2663 |  | 
|---|
|  | 2664 | /* notreached */ | 
|---|
|  | 2665 | } | 
|---|
|  | 2666 |  | 
|---|
|  | 2667 |  | 
|---|
|  | 2668 | int sh_unix_getline (SL_TICKET fd, char * line, int sizeofline) | 
|---|
|  | 2669 | { | 
|---|
|  | 2670 | register int  count; | 
|---|
|  | 2671 | register int  n = 0; | 
|---|
|  | 2672 | char          c; | 
|---|
|  | 2673 |  | 
|---|
|  | 2674 | SL_ENTER(_("sh_unix_getline")); | 
|---|
|  | 2675 |  | 
|---|
|  | 2676 | if (sizeofline < 2) { | 
|---|
| [34] | 2677 | line[0] = '\0'; | 
|---|
| [1] | 2678 | SL_RETURN((0), _("sh_unix_getline")); | 
|---|
|  | 2679 | } | 
|---|
|  | 2680 |  | 
|---|
| [34] | 2681 | --sizeofline; | 
|---|
|  | 2682 |  | 
|---|
| [1] | 2683 | while (n < sizeofline) { | 
|---|
|  | 2684 |  | 
|---|
|  | 2685 | count = sl_read (fd, &c, 1); | 
|---|
|  | 2686 |  | 
|---|
|  | 2687 | /* end of file | 
|---|
|  | 2688 | */ | 
|---|
|  | 2689 | if (count < 1) { | 
|---|
|  | 2690 | line[n] = '\0'; | 
|---|
|  | 2691 | n = -1; | 
|---|
|  | 2692 | break; | 
|---|
|  | 2693 | } | 
|---|
|  | 2694 |  | 
|---|
|  | 2695 | if (/* c != '\0' && */ c != '\n') { | 
|---|
|  | 2696 | line[n] = c; | 
|---|
|  | 2697 | ++n; | 
|---|
|  | 2698 | } else if (c == '\n') { | 
|---|
|  | 2699 | if (n > 0) { | 
|---|
|  | 2700 | line[n] = '\0'; | 
|---|
|  | 2701 | break; | 
|---|
|  | 2702 | } else { | 
|---|
|  | 2703 | line[n] = '\n'; /* get newline only if only char on line */ | 
|---|
|  | 2704 | ++n; | 
|---|
|  | 2705 | line[n] = '\0'; | 
|---|
|  | 2706 | break; | 
|---|
|  | 2707 | } | 
|---|
|  | 2708 | } else { | 
|---|
|  | 2709 | line[n] = '\0'; | 
|---|
|  | 2710 | break; | 
|---|
|  | 2711 | } | 
|---|
|  | 2712 |  | 
|---|
|  | 2713 | } | 
|---|
|  | 2714 |  | 
|---|
|  | 2715 |  | 
|---|
|  | 2716 | line[sizeofline] = '\0';  /* make sure line is terminated */ | 
|---|
|  | 2717 | SL_RETURN((n), _("sh_unix_getline")); | 
|---|
|  | 2718 | } | 
|---|
|  | 2719 |  | 
|---|
|  | 2720 |  | 
|---|
|  | 2721 | #if defined (SH_WITH_CLIENT) || defined (SH_STANDALONE) | 
|---|
|  | 2722 |  | 
|---|
|  | 2723 | /************************************************************** | 
|---|
|  | 2724 | * | 
|---|
|  | 2725 | * --- FILE INFO --- | 
|---|
|  | 2726 | * | 
|---|
|  | 2727 | **************************************************************/ | 
|---|
|  | 2728 |  | 
|---|
| [10] | 2729 | #if (defined(__linux__) && (defined(HAVE_LINUX_EXT2_FS_H) || defined(HAVE_EXT2FS_EXT2_FS_H))) || defined(HAVE_STAT_FLAGS) | 
|---|
| [1] | 2730 |  | 
|---|
| [10] | 2731 | #if defined(__linux__) | 
|---|
| [1] | 2732 |  | 
|---|
|  | 2733 | /* --- Determine ext2fs file attributes. --- | 
|---|
|  | 2734 | */ | 
|---|
|  | 2735 | #include <sys/ioctl.h> | 
|---|
|  | 2736 | #if defined(HAVE_EXT2FS_EXT2_FS_H) | 
|---|
|  | 2737 | #include <ext2fs/ext2_fs.h> | 
|---|
|  | 2738 | #else | 
|---|
|  | 2739 | #include <linux/ext2_fs.h> | 
|---|
|  | 2740 | #endif | 
|---|
|  | 2741 |  | 
|---|
| [10] | 2742 | /* __linux__ includes */ | 
|---|
|  | 2743 | #endif | 
|---|
|  | 2744 |  | 
|---|
| [1] | 2745 | static | 
|---|
|  | 2746 | int sh_unix_getinfo_attr (char * name, | 
|---|
|  | 2747 | unsigned long * flags, | 
|---|
|  | 2748 | char * c_attr, | 
|---|
| [10] | 2749 | int fd, struct stat * buf) | 
|---|
| [1] | 2750 | { | 
|---|
|  | 2751 |  | 
|---|
|  | 2752 | /* TAKEN FROM: | 
|---|
|  | 2753 | * | 
|---|
|  | 2754 | * lsattr.c             - List file attributes on an ext2 file system | 
|---|
|  | 2755 | * | 
|---|
|  | 2756 | * Copyright (C) 1993, 1994  Remy Card <card@masi.ibp.fr> | 
|---|
|  | 2757 | *                           Laboratoire MASI, Institut Blaise Pascal | 
|---|
|  | 2758 | *                           Universite Pierre et Marie Curie (Paris VI) | 
|---|
|  | 2759 | * | 
|---|
|  | 2760 | * This file can be redistributed under the terms of the GNU General | 
|---|
|  | 2761 | * Public License | 
|---|
|  | 2762 | */ | 
|---|
|  | 2763 |  | 
|---|
|  | 2764 | #ifdef HAVE_STAT_FLAGS | 
|---|
|  | 2765 |  | 
|---|
|  | 2766 | SL_ENTER(_("sh_unix_getinfo_attr")); | 
|---|
|  | 2767 |  | 
|---|
|  | 2768 | *flags = 0; | 
|---|
|  | 2769 |  | 
|---|
| [10] | 2770 | /* cast to void to avoid compiler warning about unused parameters */ | 
|---|
|  | 2771 | (void) fd; | 
|---|
|  | 2772 | (void) name; | 
|---|
| [1] | 2773 |  | 
|---|
| [10] | 2774 | #ifdef UF_NODUMP | 
|---|
|  | 2775 | if (buf->st_flags & UF_NODUMP) { | 
|---|
|  | 2776 | *flags |= UF_NODUMP; | 
|---|
|  | 2777 | c_attr[0] = 'd'; | 
|---|
|  | 2778 | } | 
|---|
|  | 2779 | #endif | 
|---|
| [1] | 2780 | #ifdef UF_IMMUTABLE | 
|---|
| [10] | 2781 | if (buf->st_flags & UF_IMMUTABLE) { | 
|---|
|  | 2782 | *flags |= UF_IMMUTABLE; | 
|---|
|  | 2783 | c_attr[1] = 'i'; | 
|---|
|  | 2784 | } | 
|---|
| [1] | 2785 | #endif | 
|---|
|  | 2786 | #ifdef UF_APPEND | 
|---|
| [10] | 2787 | if (buf->st_flags & UF_APPEND) { | 
|---|
|  | 2788 | *flags |= UF_APPEND; | 
|---|
|  | 2789 | c_attr[2] = 'a'; | 
|---|
|  | 2790 | } | 
|---|
| [1] | 2791 | #endif | 
|---|
| [10] | 2792 | #ifdef UF_NOUNLINK | 
|---|
|  | 2793 | if (buf->st_flags & UF_NOUNLINK) { | 
|---|
|  | 2794 | *flags |= UF_NOUNLINK; | 
|---|
|  | 2795 | c_attr[3] = 'u'; | 
|---|
|  | 2796 | } | 
|---|
| [1] | 2797 | #endif | 
|---|
| [10] | 2798 | #ifdef UF_OPAQUE | 
|---|
|  | 2799 | if (buf->st_flags & UF_OPAQUE) { | 
|---|
|  | 2800 | *flags |= UF_OPAQUE; | 
|---|
|  | 2801 | c_attr[4] = 'o'; | 
|---|
|  | 2802 | } | 
|---|
|  | 2803 | #endif | 
|---|
|  | 2804 | #ifdef SF_ARCHIVED | 
|---|
|  | 2805 | if (buf->st_flags & SF_ARCHIVED) { | 
|---|
|  | 2806 | *flags |= SF_ARCHIVED; | 
|---|
|  | 2807 | c_attr[5] = 'R'; | 
|---|
|  | 2808 | } | 
|---|
|  | 2809 |  | 
|---|
|  | 2810 | #endif | 
|---|
|  | 2811 | #ifdef SF_IMMUTABLE | 
|---|
|  | 2812 | if (buf->st_flags & SF_IMMUTABLE) { | 
|---|
|  | 2813 | *flags |= SF_IMMUTABLE; | 
|---|
|  | 2814 | c_attr[6] = 'I'; | 
|---|
|  | 2815 | } | 
|---|
|  | 2816 | #endif | 
|---|
|  | 2817 | #ifdef SF_APPEND | 
|---|
|  | 2818 | if (buf->st_flags & SF_APPEND) { | 
|---|
|  | 2819 | *flags |= SF_APPEND; | 
|---|
|  | 2820 | c_attr[7] = 'A'; | 
|---|
|  | 2821 | } | 
|---|
|  | 2822 | #endif | 
|---|
|  | 2823 | #ifdef SF_NOUNLINK | 
|---|
|  | 2824 | if (buf->st_flags & SF_NOUNLINK) { | 
|---|
|  | 2825 | *flags |= SF_NOUNLINK; | 
|---|
|  | 2826 | c_attr[8] = 'U'; | 
|---|
|  | 2827 | } | 
|---|
|  | 2828 | #endif | 
|---|
| [1] | 2829 |  | 
|---|
| [10] | 2830 | /* ! HAVE_STAT_FLAGS */ | 
|---|
| [1] | 2831 | #else | 
|---|
|  | 2832 |  | 
|---|
|  | 2833 | #ifdef HAVE_EXT2_IOCTLS | 
|---|
|  | 2834 | int /* fd, */ r, f; | 
|---|
|  | 2835 |  | 
|---|
|  | 2836 | SL_ENTER(_("sh_unix_getinfo_attr")); | 
|---|
|  | 2837 |  | 
|---|
|  | 2838 | *flags = 0; | 
|---|
| [10] | 2839 | (void) buf; | 
|---|
| [1] | 2840 |  | 
|---|
|  | 2841 | /* open() -> aud_open() R.Wichmann | 
|---|
|  | 2842 | fd = aud_open (FIL__, __LINE__, SL_YESPRIV, name, O_RDONLY|O_NONBLOCK, 0); | 
|---|
|  | 2843 | */ | 
|---|
|  | 2844 |  | 
|---|
|  | 2845 | if (fd == -1 || name == NULL) | 
|---|
|  | 2846 | SL_RETURN(-1, _("sh_unix_getinfo_attr")); | 
|---|
|  | 2847 |  | 
|---|
|  | 2848 |  | 
|---|
|  | 2849 | r = ioctl (fd, EXT2_IOC_GETFLAGS, &f); | 
|---|
|  | 2850 | /* close (fd); */ | 
|---|
|  | 2851 |  | 
|---|
|  | 2852 | if (r == -1) | 
|---|
|  | 2853 | SL_RETURN(-1, _("sh_unix_getinfo_attr")); | 
|---|
|  | 2854 |  | 
|---|
| [10] | 2855 | if (f == 0) | 
|---|
|  | 2856 | SL_RETURN(0, _("sh_unix_getinfo_attr")); | 
|---|
|  | 2857 |  | 
|---|
| [1] | 2858 | *flags = f; | 
|---|
|  | 2859 |  | 
|---|
|  | 2860 | /* ! HAVE_EXT2_IOCTLS */ | 
|---|
|  | 2861 | #else | 
|---|
|  | 2862 |  | 
|---|
|  | 2863 | SL_ENTER(_("sh_unix_getinfo_attr")); | 
|---|
|  | 2864 |  | 
|---|
|  | 2865 | *flags = 0;                                     /* modified by R.Wichmann */ | 
|---|
|  | 2866 |  | 
|---|
|  | 2867 | /* ! HAVE_EXT2_IOCTLS */ | 
|---|
|  | 2868 | #endif | 
|---|
|  | 2869 | /* | 
|---|
|  | 2870 | * END | 
|---|
|  | 2871 | * | 
|---|
|  | 2872 | * lsattr.c             - List file attributes on an ext2 file system | 
|---|
|  | 2873 | */ | 
|---|
|  | 2874 |  | 
|---|
| [10] | 2875 | if (*flags == 0) | 
|---|
|  | 2876 | goto theend; | 
|---|
|  | 2877 |  | 
|---|
| [1] | 2878 | #ifdef EXT2_SECRM_FL | 
|---|
|  | 2879 | if ( (*flags & EXT2_SECRM_FL) != 0  )   c_attr[0] = 's'; | 
|---|
|  | 2880 | #endif | 
|---|
|  | 2881 | #ifdef EXT2_UNRM_FL | 
|---|
|  | 2882 | if ( (*flags & EXT2_UNRM_FL) != 0   )   c_attr[1] = 'u'; | 
|---|
|  | 2883 | #endif | 
|---|
|  | 2884 | #ifdef EXT2_SYNC_FL | 
|---|
|  | 2885 | if ( (*flags & EXT2_SYNC_FL) != 0    )  c_attr[2] = 'S'; | 
|---|
|  | 2886 | #endif | 
|---|
|  | 2887 | #ifdef EXT2_IMMUTABLE_FL | 
|---|
|  | 2888 | if ( (*flags & EXT2_IMMUTABLE_FL) != 0) c_attr[3] = 'i'; | 
|---|
|  | 2889 | #endif | 
|---|
|  | 2890 | #ifdef EXT2_APPEND_FL | 
|---|
|  | 2891 | if ( (*flags & EXT2_APPEND_FL) != 0  )  c_attr[4] = 'a'; | 
|---|
|  | 2892 | #endif | 
|---|
|  | 2893 | #ifdef EXT2_NODUMP_FL | 
|---|
|  | 2894 | if ( (*flags & EXT2_NODUMP_FL) != 0  )  c_attr[5] = 'd'; | 
|---|
|  | 2895 | #endif | 
|---|
|  | 2896 | #ifdef EXT2_NOATIME_FL | 
|---|
|  | 2897 | if ( (*flags & EXT2_NOATIME_FL) != 0)   c_attr[6] = 'A'; | 
|---|
|  | 2898 | #endif | 
|---|
|  | 2899 | #ifdef EXT2_COMPR_FL | 
|---|
|  | 2900 | if ( (*flags & EXT2_COMPR_FL) != 0   )  c_attr[7] = 'c'; | 
|---|
|  | 2901 | #endif | 
|---|
| [10] | 2902 |  | 
|---|
|  | 2903 | #ifdef EXT2_TOPDIR_FL | 
|---|
|  | 2904 | if ( (*flags & EXT2_TOPDIR_FL) != 0  )  c_attr[8] = 'T'; | 
|---|
| [1] | 2905 | #endif | 
|---|
| [10] | 2906 | #ifdef EXT2_DIRSYNC_FL | 
|---|
|  | 2907 | if ( (*flags & EXT2_DIRSYNC_FL) != 0 )  c_attr[9] = 'D'; | 
|---|
| [1] | 2908 | #endif | 
|---|
| [10] | 2909 | #ifdef EXT2_NOTAIL_FL | 
|---|
|  | 2910 | if ( (*flags & EXT2_NOTAIL_FL) != 0  )  c_attr[10] = 't'; | 
|---|
| [1] | 2911 | #endif | 
|---|
| [10] | 2912 | #ifdef EXT2_JOURNAL_DATA_FL | 
|---|
|  | 2913 | if ( (*flags & EXT2_JOURNAL_DATA_FL) != 0)  c_attr[11] = 'j'; | 
|---|
| [1] | 2914 | #endif | 
|---|
|  | 2915 |  | 
|---|
| [10] | 2916 | theend: | 
|---|
|  | 2917 | /* ext2 */ | 
|---|
|  | 2918 | #endif | 
|---|
|  | 2919 |  | 
|---|
| [1] | 2920 | c_attr[12] = '\0'; | 
|---|
|  | 2921 |  | 
|---|
|  | 2922 | SL_RETURN(0, _("sh_unix_getinfo_attr")); | 
|---|
|  | 2923 | } | 
|---|
|  | 2924 | #else | 
|---|
|  | 2925 | static | 
|---|
|  | 2926 | int sh_unix_getinfo_attr (char * name, | 
|---|
|  | 2927 | unsigned long * flags, | 
|---|
|  | 2928 | char * c_attr, | 
|---|
| [10] | 2929 | int fd, struct stat * buf) | 
|---|
| [1] | 2930 | { | 
|---|
|  | 2931 | return 0; | 
|---|
|  | 2932 | } | 
|---|
|  | 2933 |  | 
|---|
| [10] | 2934 | /* defined(__linux__) || defined(HAVE_STAT_FLAGS) */ | 
|---|
| [1] | 2935 | #endif | 
|---|
|  | 2936 |  | 
|---|
|  | 2937 | /* determine file type | 
|---|
|  | 2938 | */ | 
|---|
|  | 2939 | static | 
|---|
|  | 2940 | int sh_unix_getinfo_type (struct stat * buf, | 
|---|
|  | 2941 | ShFileType * type, | 
|---|
|  | 2942 | char * c_mode) | 
|---|
|  | 2943 | { | 
|---|
|  | 2944 | SL_ENTER(_("sh_unix_getinfo_type")); | 
|---|
|  | 2945 |  | 
|---|
|  | 2946 | if      ( S_ISREG(buf->st_mode)  ) { | 
|---|
|  | 2947 | (*type)   = SH_FILE_REGULAR; | 
|---|
|  | 2948 | c_mode[0] = '-'; | 
|---|
|  | 2949 | } | 
|---|
|  | 2950 | else if ( S_ISLNK(buf->st_mode)  ) { | 
|---|
|  | 2951 | (*type)   = SH_FILE_SYMLINK; | 
|---|
|  | 2952 | c_mode[0] = 'l'; | 
|---|
|  | 2953 | } | 
|---|
|  | 2954 | else if ( S_ISDIR(buf->st_mode)  ) { | 
|---|
|  | 2955 | (*type)   = SH_FILE_DIRECTORY; | 
|---|
|  | 2956 | c_mode[0] = 'd'; | 
|---|
|  | 2957 | } | 
|---|
|  | 2958 | else if ( S_ISCHR(buf->st_mode)  ) { | 
|---|
|  | 2959 | (*type)   = SH_FILE_CDEV; | 
|---|
|  | 2960 | c_mode[0] = 'c'; | 
|---|
|  | 2961 | } | 
|---|
|  | 2962 | else if ( S_ISBLK(buf->st_mode)  ) { | 
|---|
|  | 2963 | (*type)   = SH_FILE_BDEV; | 
|---|
|  | 2964 | c_mode[0] = 'b'; | 
|---|
|  | 2965 | } | 
|---|
|  | 2966 | else if ( S_ISFIFO(buf->st_mode) ) { | 
|---|
|  | 2967 | (*type)   = SH_FILE_FIFO; | 
|---|
|  | 2968 | c_mode[0] = '|'; | 
|---|
|  | 2969 | } | 
|---|
|  | 2970 | else if ( S_ISSOCK(buf->st_mode) ) { | 
|---|
|  | 2971 | (*type)   = SH_FILE_SOCKET; | 
|---|
|  | 2972 | c_mode[0] = 's'; | 
|---|
|  | 2973 | } | 
|---|
| [40] | 2974 | else if ( S_ISDOOR(buf->st_mode) ) { | 
|---|
|  | 2975 | (*type)   = SH_FILE_DOOR; | 
|---|
|  | 2976 | c_mode[0] = 'D'; | 
|---|
|  | 2977 | } | 
|---|
|  | 2978 | else if ( S_ISPORT(buf->st_mode) ) { | 
|---|
|  | 2979 | (*type)   = SH_FILE_PORT; | 
|---|
|  | 2980 | c_mode[0] = 'P'; | 
|---|
|  | 2981 | } | 
|---|
| [1] | 2982 | else                              { | 
|---|
|  | 2983 | (*type)   = SH_FILE_UNKNOWN; | 
|---|
|  | 2984 | c_mode[0] = '?'; | 
|---|
|  | 2985 | } | 
|---|
|  | 2986 |  | 
|---|
|  | 2987 | SL_RETURN(0, _("sh_unix_getinfo_type")); | 
|---|
|  | 2988 | } | 
|---|
|  | 2989 |  | 
|---|
|  | 2990 | int sh_unix_get_ftype(char * fullpath) | 
|---|
|  | 2991 | { | 
|---|
| [149] | 2992 | char        c_mode[CMODE_SIZE]; | 
|---|
| [1] | 2993 | struct stat buf; | 
|---|
|  | 2994 | ShFileType  type; | 
|---|
|  | 2995 | int         res; | 
|---|
|  | 2996 |  | 
|---|
|  | 2997 | SL_ENTER(_("sh_unix_get_ftype")); | 
|---|
|  | 2998 |  | 
|---|
|  | 2999 | res = retry_lstat(FIL__, __LINE__, fullpath, &buf); | 
|---|
|  | 3000 |  | 
|---|
|  | 3001 | if (res < 0) | 
|---|
|  | 3002 | SL_RETURN(SH_FILE_UNKNOWN, _("sh_unix_getinfo_type")); | 
|---|
|  | 3003 |  | 
|---|
|  | 3004 | sh_unix_getinfo_type (&buf, &type, c_mode); | 
|---|
|  | 3005 |  | 
|---|
|  | 3006 | SL_RETURN(type, _("sh_unix_get_ftype")); | 
|---|
|  | 3007 | } | 
|---|
|  | 3008 |  | 
|---|
|  | 3009 |  | 
|---|
|  | 3010 | static | 
|---|
|  | 3011 | int  sh_unix_getinfo_mode (struct stat *buf, | 
|---|
|  | 3012 | unsigned int * mode, | 
|---|
|  | 3013 | char * c_mode) | 
|---|
|  | 3014 | { | 
|---|
|  | 3015 |  | 
|---|
|  | 3016 | SL_ENTER(_("sh_unix_getinfo_mode")); | 
|---|
|  | 3017 |  | 
|---|
|  | 3018 | (*mode) = buf->st_mode; | 
|---|
|  | 3019 |  | 
|---|
|  | 3020 | /* make 'ls'-like string */ | 
|---|
|  | 3021 |  | 
|---|
|  | 3022 | if ( (buf->st_mode & S_IRUSR) != 0 )  c_mode[1] = 'r'; | 
|---|
|  | 3023 | if ( (buf->st_mode & S_IWUSR) != 0 )  c_mode[2] = 'w'; | 
|---|
|  | 3024 | if ( (buf->st_mode & S_IXUSR) != 0 ) { | 
|---|
|  | 3025 | if ((buf->st_mode & S_ISUID) != 0 ) c_mode[3] = 's'; | 
|---|
|  | 3026 | else                                c_mode[3] = 'x'; | 
|---|
|  | 3027 | } else { | 
|---|
|  | 3028 | if ((buf->st_mode & S_ISUID) != 0 ) c_mode[3] = 'S'; | 
|---|
|  | 3029 | } | 
|---|
|  | 3030 |  | 
|---|
|  | 3031 | if ( (buf->st_mode & S_IRGRP) != 0 )  c_mode[4] = 'r'; | 
|---|
|  | 3032 | if ( (buf->st_mode & S_IWGRP) != 0 )  c_mode[5] = 'w'; | 
|---|
|  | 3033 | if ( (buf->st_mode & S_IXGRP) != 0 )  { | 
|---|
|  | 3034 | if ((buf->st_mode & S_ISGID) != 0 ) c_mode[6] = 's'; | 
|---|
|  | 3035 | else                                c_mode[6] = 'x'; | 
|---|
|  | 3036 | } else { | 
|---|
|  | 3037 | if ((buf->st_mode & S_ISGID) != 0 ) c_mode[6] = 'S'; | 
|---|
|  | 3038 | } | 
|---|
|  | 3039 |  | 
|---|
|  | 3040 | if ( (buf->st_mode & S_IROTH) != 0 )  c_mode[7] = 'r'; | 
|---|
|  | 3041 | if ( (buf->st_mode & S_IWOTH) != 0 )  c_mode[8] = 'w'; | 
|---|
|  | 3042 | #ifdef S_ISVTX  /* not POSIX */ | 
|---|
|  | 3043 | if ( (buf->st_mode & S_IXOTH) != 0 )  { | 
|---|
|  | 3044 | if ((buf->st_mode & S_ISVTX) != 0 ) c_mode[9] = 't'; | 
|---|
|  | 3045 | else                                c_mode[9] = 'x'; | 
|---|
|  | 3046 | } else { | 
|---|
|  | 3047 | if ((buf->st_mode & S_ISVTX) != 0 ) c_mode[9] = 'T'; | 
|---|
|  | 3048 | } | 
|---|
|  | 3049 | #else | 
|---|
|  | 3050 | if ( (buf->st_mode & S_IXOTH) != 0 )  c_mode[9] = 'x'; | 
|---|
|  | 3051 | #endif | 
|---|
|  | 3052 |  | 
|---|
|  | 3053 | SL_RETURN(0, _("sh_unix_getinfo_mode")); | 
|---|
|  | 3054 | } | 
|---|
|  | 3055 |  | 
|---|
|  | 3056 |  | 
|---|
|  | 3057 | long IO_Limit = 0; | 
|---|
|  | 3058 |  | 
|---|
|  | 3059 | void sh_unix_io_pause () | 
|---|
|  | 3060 | { | 
|---|
|  | 3061 | long runtime; | 
|---|
|  | 3062 | float          someval; | 
|---|
|  | 3063 | unsigned long  sometime; | 
|---|
|  | 3064 |  | 
|---|
|  | 3065 | if (IO_Limit == 0) | 
|---|
|  | 3066 | { | 
|---|
|  | 3067 | return; | 
|---|
|  | 3068 | } | 
|---|
|  | 3069 | else | 
|---|
|  | 3070 | { | 
|---|
|  | 3071 | runtime = (long) (time(NULL) - sh.statistics.time_start); | 
|---|
|  | 3072 |  | 
|---|
|  | 3073 | if (runtime > 0 && (long)(sh.statistics.bytes_hashed/runtime) > IO_Limit) | 
|---|
|  | 3074 | { | 
|---|
|  | 3075 | someval  = sh.statistics.bytes_hashed - (IO_Limit * runtime); | 
|---|
|  | 3076 | someval /= (float) IO_Limit; | 
|---|
|  | 3077 | if (someval < 1.0) | 
|---|
|  | 3078 | { | 
|---|
|  | 3079 | someval *= 1000;  /* milliseconds in a second */ | 
|---|
|  | 3080 | sometime = (unsigned long) someval; | 
|---|
|  | 3081 | retry_msleep(0, sometime); | 
|---|
|  | 3082 | } | 
|---|
|  | 3083 | else | 
|---|
|  | 3084 | { | 
|---|
|  | 3085 | sometime = (unsigned long) someval; | 
|---|
|  | 3086 | retry_msleep (sometime, 0); | 
|---|
|  | 3087 | } | 
|---|
|  | 3088 | } | 
|---|
|  | 3089 | } | 
|---|
|  | 3090 | return; | 
|---|
|  | 3091 | } | 
|---|
|  | 3092 |  | 
|---|
| [22] | 3093 | int sh_unix_set_io_limit (const char * c) | 
|---|
| [1] | 3094 | { | 
|---|
|  | 3095 | long val; | 
|---|
|  | 3096 |  | 
|---|
|  | 3097 | SL_ENTER(_("sh_unix_set_io_limit")); | 
|---|
|  | 3098 |  | 
|---|
|  | 3099 | val = strtol (c, (char **)NULL, 10); | 
|---|
|  | 3100 | if (val < 0) | 
|---|
|  | 3101 | sh_error_handle ((-1), FIL__, __LINE__, EINVAL, MSG_EINVALS, | 
|---|
|  | 3102 | _("set I/O limit"), c); | 
|---|
|  | 3103 |  | 
|---|
|  | 3104 | val = (val < 0 ? 0 : val); | 
|---|
|  | 3105 |  | 
|---|
|  | 3106 | IO_Limit = val * 1024; | 
|---|
|  | 3107 | SL_RETURN( 0, _("sh_unix_set_io_limit")); | 
|---|
|  | 3108 | } | 
|---|
|  | 3109 |  | 
|---|
|  | 3110 | /* obtain file info | 
|---|
|  | 3111 | */ | 
|---|
|  | 3112 | extern int flag_err_debug; | 
|---|
|  | 3113 |  | 
|---|
|  | 3114 | #include "sh_ignore.h" | 
|---|
|  | 3115 |  | 
|---|
| [19] | 3116 | int sh_unix_checksum_size (char * filename, struct stat * fbuf, | 
|---|
| [133] | 3117 | char * fileHash, int alert_timeout, SL_TICKET fd) | 
|---|
| [19] | 3118 | { | 
|---|
|  | 3119 | file_type tmpFile; | 
|---|
|  | 3120 | int status; | 
|---|
|  | 3121 |  | 
|---|
|  | 3122 | SL_ENTER(_("sh_unix_checksum_size")); | 
|---|
|  | 3123 |  | 
|---|
| [169] | 3124 | tmpFile.link_path = NULL; | 
|---|
|  | 3125 |  | 
|---|
| [59] | 3126 | if (sh.flag.checkSum != SH_CHECK_INIT) | 
|---|
|  | 3127 | { | 
|---|
|  | 3128 | /* lookup file in database */ | 
|---|
|  | 3129 | status = sh_hash_get_it (filename, &tmpFile); | 
|---|
|  | 3130 | if (status != 0) { | 
|---|
|  | 3131 | goto out; | 
|---|
|  | 3132 | } | 
|---|
|  | 3133 | } | 
|---|
|  | 3134 | else | 
|---|
|  | 3135 | { | 
|---|
|  | 3136 | tmpFile.size = fbuf->st_size; | 
|---|
|  | 3137 | } | 
|---|
| [19] | 3138 |  | 
|---|
|  | 3139 | /* if last < current get checksum */ | 
|---|
|  | 3140 | if (tmpFile.size < fbuf->st_size) | 
|---|
|  | 3141 | { | 
|---|
| [133] | 3142 | char hashbuf[KEYBUF_SIZE]; | 
|---|
| [153] | 3143 | UINT64 local_length = (UINT64) (tmpFile.size < 0 ? 0 : tmpFile.size); | 
|---|
| [22] | 3144 | sl_strlcpy(fileHash, | 
|---|
| [153] | 3145 | sh_tiger_generic_hash (filename, fd, &(local_length), | 
|---|
| [133] | 3146 | alert_timeout, hashbuf, sizeof(hashbuf)), | 
|---|
| [59] | 3147 | KEY_LEN+1); | 
|---|
| [68] | 3148 |  | 
|---|
| [107] | 3149 | /* return */ | 
|---|
| [167] | 3150 | if (tmpFile.link_path)   SH_FREE(tmpFile.link_path); | 
|---|
| [19] | 3151 | SL_RETURN( 0, _("sh_unix_checksum_size")); | 
|---|
|  | 3152 | } | 
|---|
|  | 3153 |  | 
|---|
|  | 3154 | out: | 
|---|
| [167] | 3155 | if (tmpFile.link_path)   SH_FREE(tmpFile.link_path); | 
|---|
| [93] | 3156 | sl_strlcpy(fileHash, SH_KEY_NULL, KEY_LEN+1); | 
|---|
| [19] | 3157 | SL_RETURN( -1, _("sh_unix_checksum_size")); | 
|---|
|  | 3158 | } | 
|---|
|  | 3159 |  | 
|---|
| [68] | 3160 | int sh_unix_check_selinux = S_FALSE; | 
|---|
|  | 3161 | int sh_unix_check_acl     = S_FALSE; | 
|---|
|  | 3162 |  | 
|---|
|  | 3163 | #ifdef USE_ACL | 
|---|
|  | 3164 |  | 
|---|
|  | 3165 | #include <sys/acl.h> | 
|---|
|  | 3166 | static char * sh_unix_getinfo_acl (char * path, int fd, struct stat * buf) | 
|---|
|  | 3167 | { | 
|---|
|  | 3168 | /* system.posix_acl_access, system.posix_acl_default | 
|---|
|  | 3169 | */ | 
|---|
|  | 3170 | char *  out  = NULL; | 
|---|
|  | 3171 | char *  collect = NULL; | 
|---|
|  | 3172 | char *  tmp; | 
|---|
|  | 3173 | char *  out_compact; | 
|---|
|  | 3174 | ssize_t len; | 
|---|
|  | 3175 | acl_t   result; | 
|---|
|  | 3176 |  | 
|---|
|  | 3177 | SL_ENTER(_("sh_unix_getinfo_acl")); | 
|---|
|  | 3178 |  | 
|---|
|  | 3179 | result = (fd == -1) ? | 
|---|
|  | 3180 | acl_get_file (path, ACL_TYPE_ACCESS) : | 
|---|
|  | 3181 | acl_get_fd   (fd); | 
|---|
|  | 3182 |  | 
|---|
|  | 3183 | if (result) | 
|---|
|  | 3184 | { | 
|---|
|  | 3185 | out = acl_to_text (result, &len); | 
|---|
|  | 3186 | if (out && (len > 0)) { | 
|---|
|  | 3187 | out_compact = sh_util_acl_compact (out, len); | 
|---|
|  | 3188 | acl_free(out); | 
|---|
|  | 3189 | if (out_compact) | 
|---|
|  | 3190 | { | 
|---|
|  | 3191 | collect = sh_util_strconcat (_("acl_access:"), out_compact, NULL); | 
|---|
|  | 3192 | SH_FREE(out_compact); | 
|---|
|  | 3193 | } | 
|---|
|  | 3194 | } | 
|---|
|  | 3195 | acl_free(result); | 
|---|
|  | 3196 | } | 
|---|
|  | 3197 |  | 
|---|
|  | 3198 |  | 
|---|
|  | 3199 | if ( S_ISDIR(buf->st_mode) ) | 
|---|
|  | 3200 | { | 
|---|
|  | 3201 | result = acl_get_file (path, ACL_TYPE_DEFAULT); | 
|---|
|  | 3202 |  | 
|---|
|  | 3203 | if (result) | 
|---|
|  | 3204 | { | 
|---|
|  | 3205 | out = acl_to_text (result, &len); | 
|---|
|  | 3206 | if (out && (len > 0)) { | 
|---|
|  | 3207 | out_compact = sh_util_acl_compact (out, len); | 
|---|
|  | 3208 | acl_free(out); | 
|---|
|  | 3209 | if (out_compact) { | 
|---|
|  | 3210 | if (collect) { | 
|---|
|  | 3211 | tmp = sh_util_strconcat (_("acl_default:"), | 
|---|
|  | 3212 | out_compact, ":", collect, NULL); | 
|---|
|  | 3213 | SH_FREE(collect); | 
|---|
|  | 3214 | } | 
|---|
|  | 3215 | else { | 
|---|
|  | 3216 | tmp = sh_util_strconcat (_("acl_default:"), out_compact, NULL); | 
|---|
|  | 3217 | } | 
|---|
|  | 3218 | SH_FREE(out_compact); | 
|---|
|  | 3219 | collect = tmp; | 
|---|
|  | 3220 | } | 
|---|
|  | 3221 | } | 
|---|
|  | 3222 | acl_free(result); | 
|---|
|  | 3223 | } | 
|---|
|  | 3224 | } | 
|---|
|  | 3225 |  | 
|---|
|  | 3226 | SL_RETURN((collect),_("sh_unix_getinfo_acl")); | 
|---|
|  | 3227 | } | 
|---|
|  | 3228 | #endif | 
|---|
|  | 3229 |  | 
|---|
|  | 3230 | #ifdef USE_XATTR | 
|---|
|  | 3231 |  | 
|---|
|  | 3232 | #include <attr/xattr.h> | 
|---|
|  | 3233 | static char * sh_unix_getinfo_xattr_int (char * path, int fd, char * name) | 
|---|
|  | 3234 | { | 
|---|
|  | 3235 | char *  out   = NULL; | 
|---|
|  | 3236 | char *  tmp   = NULL; | 
|---|
|  | 3237 | size_t  size  = 256; | 
|---|
|  | 3238 | ssize_t result; | 
|---|
|  | 3239 |  | 
|---|
|  | 3240 | SL_ENTER(_("sh_unix_getinfo_xattr_int")); | 
|---|
|  | 3241 |  | 
|---|
|  | 3242 | out = SH_ALLOC(size); | 
|---|
|  | 3243 |  | 
|---|
|  | 3244 | result = (fd == -1) ? | 
|---|
|  | 3245 | lgetxattr (path, name, out, size-1) : | 
|---|
|  | 3246 | fgetxattr (fd,   name, out, size-1); | 
|---|
|  | 3247 |  | 
|---|
|  | 3248 | if (result == -1 && errno == ERANGE) | 
|---|
|  | 3249 | { | 
|---|
|  | 3250 | SH_FREE(out); | 
|---|
|  | 3251 | result = (fd == -1) ? | 
|---|
|  | 3252 | lgetxattr (path, name, NULL, 0) : | 
|---|
|  | 3253 | fgetxattr (fd,   name, NULL, 0); | 
|---|
|  | 3254 | size = result + 1; | 
|---|
|  | 3255 | out  = SH_ALLOC(size); | 
|---|
|  | 3256 | result = (fd == -1) ? | 
|---|
|  | 3257 | lgetxattr (path, name, out, size-1) : | 
|---|
|  | 3258 | fgetxattr (fd,   name, out, size-1); | 
|---|
|  | 3259 | } | 
|---|
|  | 3260 |  | 
|---|
|  | 3261 | if ((result > 0) && ((size_t)result < size)) | 
|---|
|  | 3262 | { | 
|---|
|  | 3263 | out[size-1] = '\0'; | 
|---|
|  | 3264 | tmp = out; | 
|---|
|  | 3265 | } | 
|---|
|  | 3266 | else | 
|---|
|  | 3267 | { | 
|---|
|  | 3268 | SH_FREE(out); | 
|---|
|  | 3269 | } | 
|---|
|  | 3270 |  | 
|---|
|  | 3271 | SL_RETURN((tmp),_("sh_unix_getinfo_xattr_int")); | 
|---|
|  | 3272 | } | 
|---|
|  | 3273 |  | 
|---|
|  | 3274 |  | 
|---|
|  | 3275 | static char * sh_unix_getinfo_xattr (char * path, int fd, struct stat * buf) | 
|---|
|  | 3276 | { | 
|---|
|  | 3277 | /* system.posix_acl_access, system.posix_acl_default, security.selinux | 
|---|
|  | 3278 | */ | 
|---|
|  | 3279 | char *  tmp; | 
|---|
|  | 3280 | char *  out  = NULL; | 
|---|
|  | 3281 | char *  collect = NULL; | 
|---|
|  | 3282 |  | 
|---|
|  | 3283 | SL_ENTER(_("sh_unix_getinfo_xattr")); | 
|---|
|  | 3284 |  | 
|---|
|  | 3285 | #ifdef USE_ACL | 
|---|
|  | 3286 | /* | 
|---|
|  | 3287 | * we need the acl_get_fd/acl_get_file functions, getxattr will only | 
|---|
|  | 3288 | * yield the raw bytes | 
|---|
|  | 3289 | */ | 
|---|
|  | 3290 | if (sh_unix_check_acl == S_TRUE) | 
|---|
|  | 3291 | { | 
|---|
|  | 3292 | out = sh_unix_getinfo_acl(path, fd, buf); | 
|---|
|  | 3293 |  | 
|---|
|  | 3294 | if (out) | 
|---|
|  | 3295 | { | 
|---|
|  | 3296 | collect = out; | 
|---|
|  | 3297 | } | 
|---|
|  | 3298 | } | 
|---|
|  | 3299 | #endif | 
|---|
|  | 3300 |  | 
|---|
| [105] | 3301 | if (sh_unix_check_selinux == S_TRUE) | 
|---|
|  | 3302 | { | 
|---|
|  | 3303 | out = sh_unix_getinfo_xattr_int(path, fd, _("security.selinux")); | 
|---|
| [68] | 3304 |  | 
|---|
| [105] | 3305 | if (out) | 
|---|
|  | 3306 | { | 
|---|
|  | 3307 | if (collect) { | 
|---|
|  | 3308 | tmp = sh_util_strconcat(_("selinux:"), out, ":", collect, NULL); | 
|---|
|  | 3309 | SH_FREE(collect); | 
|---|
|  | 3310 | } | 
|---|
|  | 3311 | else { | 
|---|
|  | 3312 | tmp = sh_util_strconcat(_("selinux:"), out, NULL); | 
|---|
|  | 3313 | } | 
|---|
|  | 3314 | SH_FREE(out); | 
|---|
|  | 3315 | collect = tmp; | 
|---|
|  | 3316 | } | 
|---|
| [68] | 3317 | } | 
|---|
|  | 3318 |  | 
|---|
|  | 3319 | SL_RETURN((collect),_("sh_unix_getinfo_xattr")); | 
|---|
|  | 3320 | } | 
|---|
|  | 3321 | #endif | 
|---|
|  | 3322 |  | 
|---|
|  | 3323 | #ifdef USE_XATTR | 
|---|
|  | 3324 | int sh_unix_setcheckselinux (const char * c) | 
|---|
|  | 3325 | { | 
|---|
|  | 3326 | int i; | 
|---|
|  | 3327 | SL_ENTER(_("sh_unix_setcheckselinux")); | 
|---|
|  | 3328 | i = sh_util_flagval(c, &(sh_unix_check_selinux)); | 
|---|
|  | 3329 |  | 
|---|
|  | 3330 | SL_RETURN(i, _("sh_unix_setcheckselinux")); | 
|---|
|  | 3331 | } | 
|---|
|  | 3332 | #endif | 
|---|
|  | 3333 |  | 
|---|
|  | 3334 | #ifdef USE_ACL | 
|---|
|  | 3335 | int sh_unix_setcheckacl (const char * c) | 
|---|
|  | 3336 | { | 
|---|
|  | 3337 | int i; | 
|---|
|  | 3338 | SL_ENTER(_("sh_unix_setcheckacl")); | 
|---|
|  | 3339 | i = sh_util_flagval(c, &(sh_unix_check_acl)); | 
|---|
|  | 3340 |  | 
|---|
|  | 3341 | SL_RETURN(i, _("sh_unix_setcheckacl")); | 
|---|
|  | 3342 | } | 
|---|
|  | 3343 | #endif | 
|---|
|  | 3344 |  | 
|---|
| [169] | 3345 | #ifdef HAVE_LIBZ | 
|---|
|  | 3346 | #include <zlib.h> | 
|---|
|  | 3347 | #endif | 
|---|
|  | 3348 |  | 
|---|
| [1] | 3349 | int sh_unix_getinfo (int level, char * filename, file_type * theFile, | 
|---|
|  | 3350 | char * fileHash, int policy) | 
|---|
|  | 3351 | { | 
|---|
|  | 3352 | char          timestr[81]; | 
|---|
|  | 3353 | long          runtim; | 
|---|
|  | 3354 | struct stat   buf; | 
|---|
|  | 3355 | struct stat   lbuf; | 
|---|
|  | 3356 | struct stat   fbuf; | 
|---|
|  | 3357 | int           stat_return; | 
|---|
| [192] | 3358 | int           stat_errno = 0; | 
|---|
| [8] | 3359 |  | 
|---|
| [1] | 3360 | ShFileType    type; | 
|---|
|  | 3361 | unsigned int  mode; | 
|---|
|  | 3362 | char        * tmp; | 
|---|
|  | 3363 | char        * tmp2; | 
|---|
| [8] | 3364 |  | 
|---|
| [1] | 3365 | char        * linknamebuf; | 
|---|
|  | 3366 | int           linksize; | 
|---|
|  | 3367 |  | 
|---|
|  | 3368 | extern int get_the_fd (SL_TICKET ticket); | 
|---|
|  | 3369 |  | 
|---|
|  | 3370 | SL_TICKET     rval_open; | 
|---|
| [192] | 3371 | int           err_open = 0; | 
|---|
|  | 3372 |  | 
|---|
| [1] | 3373 | int           fd; | 
|---|
|  | 3374 | int           fstat_return; | 
|---|
| [192] | 3375 | int           fstat_errno = 0; | 
|---|
|  | 3376 |  | 
|---|
| [167] | 3377 | sh_string   * content = NULL; | 
|---|
|  | 3378 |  | 
|---|
| [1] | 3379 | time_t        tend; | 
|---|
|  | 3380 | time_t        tstart; | 
|---|
|  | 3381 |  | 
|---|
|  | 3382 |  | 
|---|
|  | 3383 | char * path = NULL; | 
|---|
|  | 3384 |  | 
|---|
|  | 3385 | int alert_timeout   = 120; | 
|---|
|  | 3386 |  | 
|---|
|  | 3387 | path = theFile->fullpath; | 
|---|
|  | 3388 |  | 
|---|
|  | 3389 | SL_ENTER(_("sh_unix_getinfo")); | 
|---|
|  | 3390 |  | 
|---|
|  | 3391 | /* --- Stat the file, and get checksum. --- | 
|---|
|  | 3392 | */ | 
|---|
|  | 3393 | tstart = time(NULL); | 
|---|
| [8] | 3394 |  | 
|---|
| [1] | 3395 | stat_return = retry_lstat (FIL__, __LINE__, | 
|---|
|  | 3396 | path /* theFile->fullpath */, &buf); | 
|---|
|  | 3397 |  | 
|---|
| [192] | 3398 | if (stat_return) | 
|---|
|  | 3399 | stat_errno = errno; | 
|---|
|  | 3400 |  | 
|---|
| [8] | 3401 | fd           = -1; | 
|---|
|  | 3402 | fstat_return = -1; | 
|---|
|  | 3403 | rval_open    = -1; | 
|---|
|  | 3404 |  | 
|---|
| [167] | 3405 | theFile->link_path = NULL; | 
|---|
|  | 3406 |  | 
|---|
| [1] | 3407 | if (stat_return == 0 && S_ISREG(buf.st_mode)) | 
|---|
|  | 3408 | { | 
|---|
|  | 3409 | rval_open = sl_open_fastread (path /* theFile->fullpath */, SL_YESPRIV); | 
|---|
| [192] | 3410 | if (SL_ISERROR(rval_open)) | 
|---|
|  | 3411 | err_open = errno; | 
|---|
| [1] | 3412 |  | 
|---|
|  | 3413 | alert_timeout = 120; /* this is per 8K block now ! */ | 
|---|
|  | 3414 |  | 
|---|
| [8] | 3415 | if (path[1] == 'p' && path[5] == '/' && path[2] == 'r' && | 
|---|
|  | 3416 | path[3] == 'o' && path[4] == 'c' && path[0] == '/') | 
|---|
| [1] | 3417 | { | 
|---|
|  | 3418 | /* seven is magic */ | 
|---|
|  | 3419 | alert_timeout = 7; | 
|---|
|  | 3420 | } | 
|---|
| [8] | 3421 |  | 
|---|
|  | 3422 | fd = get_the_fd(rval_open); | 
|---|
| [1] | 3423 | } | 
|---|
|  | 3424 |  | 
|---|
|  | 3425 | tend = time(NULL); | 
|---|
|  | 3426 |  | 
|---|
|  | 3427 | /* An unprivileged user may slow lstat/open to a crawl | 
|---|
|  | 3428 | * with clever path/symlink setup | 
|---|
|  | 3429 | */ | 
|---|
|  | 3430 | if ((tend - tstart) > (time_t) /* 60 */ 6) | 
|---|
|  | 3431 | { | 
|---|
|  | 3432 | tmp2 = sh_util_safe_name (theFile->fullpath); | 
|---|
|  | 3433 | sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_FI_TOOLATE, | 
|---|
|  | 3434 | (long)(tend - tstart), tmp2); | 
|---|
|  | 3435 | SH_FREE(tmp2); | 
|---|
|  | 3436 | } | 
|---|
| [8] | 3437 |  | 
|---|
| [1] | 3438 | if (fd >= 0) | 
|---|
| [192] | 3439 | { | 
|---|
|  | 3440 | fstat_return = retry_fstat (FIL__, __LINE__, fd, &fbuf); | 
|---|
|  | 3441 | if (fstat_return) | 
|---|
|  | 3442 | fstat_errno = errno; | 
|---|
|  | 3443 | } | 
|---|
| [1] | 3444 | else | 
|---|
| [192] | 3445 | { | 
|---|
|  | 3446 | fd = -1; | 
|---|
|  | 3447 | } | 
|---|
| [8] | 3448 |  | 
|---|
| [1] | 3449 |  | 
|---|
|  | 3450 | /* ---  case 1: lstat failed  --- | 
|---|
|  | 3451 | */ | 
|---|
|  | 3452 | if (stat_return != 0) | 
|---|
|  | 3453 | { | 
|---|
|  | 3454 | stat_return = errno; | 
|---|
|  | 3455 | if (!SL_ISERROR(rval_open)) | 
|---|
|  | 3456 | sl_close(rval_open); | 
|---|
|  | 3457 | if (sh.flag.checkSum == SH_CHECK_INIT || | 
|---|
|  | 3458 | (sh_hash_have_it (theFile->fullpath) >= 0 && | 
|---|
| [114] | 3459 | (!SH_FFLAG_REPORTED_SET(theFile->file_reported)))) | 
|---|
| [1] | 3460 | { | 
|---|
|  | 3461 | if (S_FALSE == sh_ignore_chk_del(theFile->fullpath)) { | 
|---|
| [132] | 3462 | char errbuf[SH_ERRBUF_SIZE]; | 
|---|
| [192] | 3463 | uid_t euid; | 
|---|
|  | 3464 | (void) sl_get_euid(&euid); | 
|---|
| [1] | 3465 | tmp2 = sh_util_safe_name (theFile->fullpath); | 
|---|
| [192] | 3466 | sh_error_handle (level, FIL__, __LINE__, stat_return, MSG_FI_STAT, | 
|---|
|  | 3467 | _("lstat"), | 
|---|
|  | 3468 | sh_error_message (stat_errno, errbuf, sizeof(errbuf)), | 
|---|
|  | 3469 | (long) euid, | 
|---|
| [132] | 3470 | tmp2); | 
|---|
| [1] | 3471 | SH_FREE(tmp2); | 
|---|
|  | 3472 | } | 
|---|
|  | 3473 | } | 
|---|
|  | 3474 | SL_RETURN((-1),_("sh_unix_getinfo")); | 
|---|
|  | 3475 | } | 
|---|
|  | 3476 |  | 
|---|
| [8] | 3477 | /* ---  case 2: not a regular file  --- | 
|---|
| [1] | 3478 | */ | 
|---|
|  | 3479 | else if (! S_ISREG(buf.st_mode)) | 
|---|
|  | 3480 | { | 
|---|
|  | 3481 | if (fileHash != NULL) | 
|---|
| [93] | 3482 | sl_strlcpy(fileHash, SH_KEY_NULL, KEY_LEN+1); | 
|---|
| [1] | 3483 | } | 
|---|
|  | 3484 |  | 
|---|
|  | 3485 | /* ---  case 3a: a regular file, fstat ok --- | 
|---|
|  | 3486 | */ | 
|---|
|  | 3487 | else if (fstat_return == 0 && | 
|---|
|  | 3488 | buf.st_mode == fbuf.st_mode && | 
|---|
|  | 3489 | buf.st_ino  == fbuf.st_ino  && | 
|---|
|  | 3490 | buf.st_uid  == fbuf.st_uid  && | 
|---|
|  | 3491 | buf.st_gid  == fbuf.st_gid  && | 
|---|
|  | 3492 | buf.st_dev  == fbuf.st_dev ) | 
|---|
|  | 3493 | { | 
|---|
|  | 3494 | if (fileHash != NULL) | 
|---|
|  | 3495 | { | 
|---|
|  | 3496 | if ((theFile->check_mask & MODI_CHK) == 0) | 
|---|
|  | 3497 | { | 
|---|
| [93] | 3498 | sl_strlcpy(fileHash, SH_KEY_NULL, KEY_LEN+1); | 
|---|
| [1] | 3499 | } | 
|---|
| [19] | 3500 | else if ((theFile->check_mask & MODI_PREL) != 0 && | 
|---|
| [1] | 3501 | S_TRUE == sh_prelink_iself(rval_open, fbuf.st_size, | 
|---|
| [102] | 3502 | alert_timeout, theFile->fullpath)) | 
|---|
| [1] | 3503 | { | 
|---|
|  | 3504 | if (0 != sh_prelink_run (theFile->fullpath, | 
|---|
|  | 3505 | fileHash, alert_timeout)) | 
|---|
| [93] | 3506 | sl_strlcpy(fileHash, SH_KEY_NULL, KEY_LEN+1); | 
|---|
| [1] | 3507 | } | 
|---|
|  | 3508 | else | 
|---|
|  | 3509 | { | 
|---|
| [133] | 3510 | char hashbuf[KEYBUF_SIZE]; | 
|---|
| [151] | 3511 | UINT64 length_nolim = TIGER_NOLIM; | 
|---|
| [167] | 3512 |  | 
|---|
| [170] | 3513 | if (MODI_TXT_ENABLED(theFile->check_mask) && fbuf.st_size < (10 * SH_TXT_MAX)) | 
|---|
| [167] | 3514 | { | 
|---|
|  | 3515 | sl_init_content (rval_open, fbuf.st_size); | 
|---|
|  | 3516 | } | 
|---|
|  | 3517 |  | 
|---|
| [22] | 3518 | sl_strlcpy(fileHash, | 
|---|
|  | 3519 | sh_tiger_generic_hash (theFile->fullpath, | 
|---|
| [151] | 3520 | rval_open, &length_nolim, | 
|---|
| [133] | 3521 | alert_timeout, | 
|---|
|  | 3522 | hashbuf, sizeof(hashbuf)), | 
|---|
| [22] | 3523 | KEY_LEN+1); | 
|---|
| [167] | 3524 |  | 
|---|
|  | 3525 | content = sl_get_content(rval_open); | 
|---|
| [169] | 3526 | content = sh_string_copy(content); | 
|---|
| [167] | 3527 |  | 
|---|
| [19] | 3528 | if ((theFile->check_mask & MODI_SGROW) != 0) | 
|---|
|  | 3529 | { | 
|---|
| [151] | 3530 | fbuf.st_size = (off_t) length_nolim; | 
|---|
|  | 3531 | buf.st_size  = fbuf.st_size; | 
|---|
| [19] | 3532 | sl_rewind(rval_open); | 
|---|
|  | 3533 | sh_unix_checksum_size (theFile->fullpath, &fbuf, | 
|---|
|  | 3534 | &fileHash[KEY_LEN + 1], | 
|---|
| [133] | 3535 | alert_timeout, rval_open); | 
|---|
| [19] | 3536 | } | 
|---|
| [1] | 3537 | } | 
|---|
|  | 3538 | } | 
|---|
|  | 3539 | } | 
|---|
|  | 3540 |  | 
|---|
|  | 3541 | /* ---  case 3b: a regular file, fstat ok, but different --- | 
|---|
|  | 3542 | */ | 
|---|
|  | 3543 | else if (fstat_return == 0 && S_ISREG(fbuf.st_mode)) | 
|---|
|  | 3544 | { | 
|---|
|  | 3545 | memcpy (&buf, &fbuf, sizeof( struct stat )); | 
|---|
|  | 3546 |  | 
|---|
|  | 3547 | if (fileHash != NULL) | 
|---|
|  | 3548 | { | 
|---|
|  | 3549 | if ((theFile->check_mask & MODI_CHK) == 0) | 
|---|
|  | 3550 | { | 
|---|
| [93] | 3551 | sl_strlcpy(fileHash, SH_KEY_NULL, KEY_LEN+1); | 
|---|
| [1] | 3552 | } | 
|---|
|  | 3553 | else if (policy == SH_LEVEL_PRELINK && | 
|---|
|  | 3554 | S_TRUE == sh_prelink_iself(rval_open, fbuf.st_size, | 
|---|
| [102] | 3555 | alert_timeout, theFile->fullpath)) | 
|---|
| [1] | 3556 | { | 
|---|
|  | 3557 | if (0 != sh_prelink_run (theFile->fullpath, | 
|---|
|  | 3558 | fileHash, alert_timeout)) | 
|---|
| [93] | 3559 | sl_strlcpy(fileHash, SH_KEY_NULL, KEY_LEN+1); | 
|---|
| [1] | 3560 | } | 
|---|
|  | 3561 | else | 
|---|
|  | 3562 | { | 
|---|
| [133] | 3563 | char hashbuf[KEYBUF_SIZE]; | 
|---|
| [151] | 3564 | UINT64 length_nolim = TIGER_NOLIM; | 
|---|
| [167] | 3565 |  | 
|---|
| [170] | 3566 | if (MODI_TXT_ENABLED(theFile->check_mask) && fbuf.st_size < (10 * SH_TXT_MAX)) | 
|---|
| [167] | 3567 | { | 
|---|
|  | 3568 | sl_init_content (rval_open, fbuf.st_size); | 
|---|
|  | 3569 | } | 
|---|
|  | 3570 |  | 
|---|
| [1] | 3571 | sl_strlcpy(fileHash, | 
|---|
| [133] | 3572 | sh_tiger_generic_hash (theFile->fullpath, rval_open, | 
|---|
| [151] | 3573 | &length_nolim, | 
|---|
| [133] | 3574 | alert_timeout, | 
|---|
|  | 3575 | hashbuf, sizeof(hashbuf)), | 
|---|
| [1] | 3576 | KEY_LEN + 1); | 
|---|
| [167] | 3577 |  | 
|---|
|  | 3578 | content = sl_get_content(rval_open); | 
|---|
| [169] | 3579 | content = sh_string_copy(content); | 
|---|
| [167] | 3580 |  | 
|---|
| [19] | 3581 | if ((theFile->check_mask & MODI_SGROW) != 0) | 
|---|
|  | 3582 | { | 
|---|
| [151] | 3583 | fbuf.st_size = (off_t) length_nolim; | 
|---|
|  | 3584 | buf.st_size  = fbuf.st_size; | 
|---|
| [19] | 3585 | sl_rewind(rval_open); | 
|---|
|  | 3586 | sh_unix_checksum_size (theFile->fullpath, &fbuf, | 
|---|
|  | 3587 | &fileHash[KEY_LEN + 1], | 
|---|
| [133] | 3588 | alert_timeout, rval_open); | 
|---|
| [19] | 3589 | } | 
|---|
| [1] | 3590 | } | 
|---|
|  | 3591 | } | 
|---|
|  | 3592 | } | 
|---|
|  | 3593 |  | 
|---|
|  | 3594 | /* ---  case 4: a regular file, fstat failed --- | 
|---|
|  | 3595 | */ | 
|---|
|  | 3596 |  | 
|---|
| [192] | 3597 | else    /* fstat_return != 0 or !S_ISREG(fbuf.st_mode) or open() failed */ | 
|---|
| [1] | 3598 | { | 
|---|
| [185] | 3599 | uid_t   euid; | 
|---|
| [192] | 3600 |  | 
|---|
| [1] | 3601 | if (fileHash != NULL) | 
|---|
| [93] | 3602 | sl_strlcpy(fileHash, SH_KEY_NULL, KEY_LEN+1); | 
|---|
| [1] | 3603 |  | 
|---|
| [65] | 3604 | if ((theFile->check_mask & MODI_CHK) != 0) | 
|---|
|  | 3605 | { | 
|---|
|  | 3606 | tmp2 = sh_util_safe_name (theFile->fullpath); | 
|---|
| [185] | 3607 |  | 
|---|
| [200] | 3608 |  | 
|---|
|  | 3609 | if (fd >= 0 && fstat_return != 0) | 
|---|
| [185] | 3610 | { | 
|---|
| [192] | 3611 | char errbuf[SH_ERRBUF_SIZE]; | 
|---|
| [185] | 3612 | (void) sl_get_euid(&euid); | 
|---|
| [192] | 3613 |  | 
|---|
|  | 3614 | sh_error_handle (level, FIL__, __LINE__, stat_return, MSG_FI_STAT, | 
|---|
|  | 3615 | _("fstat"), | 
|---|
|  | 3616 | sh_error_message (fstat_errno, errbuf, sizeof(errbuf)), | 
|---|
|  | 3617 | (long) euid, | 
|---|
|  | 3618 | tmp2); | 
|---|
| [185] | 3619 | } | 
|---|
| [200] | 3620 | else if (fd >= 0 && !S_ISREG(fbuf.st_mode)) | 
|---|
| [185] | 3621 | { | 
|---|
| [192] | 3622 | sh_error_handle (level, FIL__, __LINE__, fstat_errno, | 
|---|
| [185] | 3623 | MSG_E_NOTREG, tmp2); | 
|---|
|  | 3624 | } | 
|---|
|  | 3625 | else | 
|---|
|  | 3626 | { | 
|---|
| [192] | 3627 | char errbuf[SH_ERRBUF_SIZE]; | 
|---|
|  | 3628 | char errbuf2[SH_ERRBUF_SIZE]; | 
|---|
|  | 3629 | sl_strlcpy(errbuf, sl_error_string(rval_open), sizeof(errbuf)); | 
|---|
|  | 3630 | sh_error_message(err_open, errbuf2, sizeof(errbuf2)); | 
|---|
|  | 3631 | sh_error_handle (level, FIL__, __LINE__, err_open, | 
|---|
|  | 3632 | MSG_E_READ, errbuf, errbuf2, tmp2); | 
|---|
| [185] | 3633 | } | 
|---|
| [65] | 3634 | SH_FREE(tmp2); | 
|---|
|  | 3635 | } | 
|---|
| [1] | 3636 | } | 
|---|
|  | 3637 |  | 
|---|
|  | 3638 |  | 
|---|
|  | 3639 | /* --- Determine file type. --- | 
|---|
|  | 3640 | */ | 
|---|
| [149] | 3641 | memset (theFile->c_mode, '-', CMODE_SIZE-1); | 
|---|
|  | 3642 | theFile->c_mode[CMODE_SIZE-1] = '\0'; | 
|---|
| [8] | 3643 |  | 
|---|
| [149] | 3644 | memset (theFile->link_c_mode, '-', CMODE_SIZE-1); | 
|---|
|  | 3645 | theFile->link_c_mode[CMODE_SIZE-1] = '\0'; | 
|---|
| [1] | 3646 |  | 
|---|
|  | 3647 | sh_unix_getinfo_type (&buf, &type, theFile->c_mode); | 
|---|
|  | 3648 | theFile->type = type; | 
|---|
|  | 3649 |  | 
|---|
| [10] | 3650 | #if defined(__linux__) || defined(HAVE_STAT_FLAGS) | 
|---|
| [1] | 3651 |  | 
|---|
|  | 3652 | /* --- Determine file attributes. --- | 
|---|
|  | 3653 | */ | 
|---|
| [149] | 3654 | memset (theFile->c_attributes, '-', ATTRBUF_SIZE); | 
|---|
|  | 3655 | theFile->c_attributes[ATTRBUF_USED] = '\0'; | 
|---|
| [1] | 3656 | theFile->attributes      =    0; | 
|---|
|  | 3657 |  | 
|---|
|  | 3658 | if (theFile->c_mode[0] != 'c' && theFile->c_mode[0] != 'b' && | 
|---|
|  | 3659 | theFile->c_mode[0] != 'l' ) | 
|---|
|  | 3660 | sh_unix_getinfo_attr(theFile->fullpath, | 
|---|
| [10] | 3661 | &theFile->attributes, theFile->c_attributes, | 
|---|
|  | 3662 | fd, &buf); | 
|---|
| [1] | 3663 | #endif | 
|---|
|  | 3664 |  | 
|---|
| [105] | 3665 | #if defined(USE_XATTR) && defined(USE_ACL) | 
|---|
|  | 3666 | if (sh_unix_check_selinux == S_TRUE || sh_unix_check_acl == S_TRUE) | 
|---|
|  | 3667 | theFile->attr_string = sh_unix_getinfo_xattr (theFile->fullpath, fd, &buf); | 
|---|
|  | 3668 | #elif defined(USE_XATTR) | 
|---|
| [68] | 3669 | if (sh_unix_check_selinux == S_TRUE) | 
|---|
|  | 3670 | theFile->attr_string = sh_unix_getinfo_xattr (theFile->fullpath, fd, &buf); | 
|---|
|  | 3671 | #elif defined(USE_ACL) | 
|---|
|  | 3672 | if (sh_unix_check_acl == S_TRUE) | 
|---|
|  | 3673 | theFile->attr_string = sh_unix_getinfo_acl (theFile->fullpath, fd, &buf); | 
|---|
|  | 3674 | #else | 
|---|
|  | 3675 | theFile->attr_string = NULL; | 
|---|
|  | 3676 | #endif | 
|---|
|  | 3677 |  | 
|---|
| [1] | 3678 | if (!SL_ISERROR(rval_open)) | 
|---|
|  | 3679 | sl_close(rval_open); | 
|---|
|  | 3680 |  | 
|---|
|  | 3681 |  | 
|---|
|  | 3682 | /* --- I/O limit. --- | 
|---|
|  | 3683 | */ | 
|---|
|  | 3684 | if (IO_Limit > 0) | 
|---|
|  | 3685 | { | 
|---|
|  | 3686 | runtim = (long) (time(NULL) - sh.statistics.time_start); | 
|---|
|  | 3687 |  | 
|---|
|  | 3688 | if (runtim > 0 && (long)(sh.statistics.bytes_hashed/runtim) > IO_Limit) | 
|---|
|  | 3689 | retry_msleep(1, 0); | 
|---|
|  | 3690 | } | 
|---|
|  | 3691 |  | 
|---|
|  | 3692 | /* --- Determine permissions. --- | 
|---|
|  | 3693 | */ | 
|---|
|  | 3694 | sh_unix_getinfo_mode (&buf, &mode, theFile->c_mode); | 
|---|
|  | 3695 |  | 
|---|
|  | 3696 | /* --- Trivia. --- | 
|---|
|  | 3697 | */ | 
|---|
|  | 3698 | theFile->dev       = buf.st_dev; | 
|---|
|  | 3699 | theFile->ino       = buf.st_ino; | 
|---|
|  | 3700 | theFile->mode      = buf.st_mode; | 
|---|
|  | 3701 | theFile->hardlinks = buf.st_nlink; | 
|---|
|  | 3702 | theFile->owner     = buf.st_uid; | 
|---|
|  | 3703 | theFile->group     = buf.st_gid; | 
|---|
|  | 3704 | theFile->rdev      = buf.st_rdev; | 
|---|
|  | 3705 | theFile->size      = buf.st_size; | 
|---|
|  | 3706 | theFile->blksize   = (unsigned long) buf.st_blksize; | 
|---|
|  | 3707 | theFile->blocks    = (unsigned long) buf.st_blocks; | 
|---|
|  | 3708 | theFile->atime     = buf.st_atime; | 
|---|
|  | 3709 | theFile->mtime     = buf.st_mtime; | 
|---|
|  | 3710 | theFile->ctime     = buf.st_ctime; | 
|---|
|  | 3711 |  | 
|---|
|  | 3712 |  | 
|---|
|  | 3713 | /* --- Owner and group. --- | 
|---|
|  | 3714 | */ | 
|---|
|  | 3715 |  | 
|---|
| [132] | 3716 | if (NULL == sh_unix_getGIDname(SH_ERR_ALL, buf.st_gid, theFile->c_group, GROUP_MAX+1)) { | 
|---|
| [1] | 3717 |  | 
|---|
|  | 3718 | tmp2 = sh_util_safe_name (theFile->fullpath); | 
|---|
|  | 3719 |  | 
|---|
|  | 3720 | if (policy == SH_LEVEL_ALLIGNORE) | 
|---|
|  | 3721 | { | 
|---|
|  | 3722 | sh_error_handle (SH_ERR_ALL, FIL__, __LINE__, ENOENT, | 
|---|
|  | 3723 | MSG_FI_NOGRP, | 
|---|
|  | 3724 | (long) buf.st_gid, tmp2); | 
|---|
|  | 3725 | } | 
|---|
|  | 3726 | else | 
|---|
|  | 3727 | { | 
|---|
|  | 3728 | sh_error_handle (ShDFLevel[SH_ERR_T_NAME], FIL__, __LINE__, ENOENT, | 
|---|
|  | 3729 | MSG_FI_NOGRP, | 
|---|
|  | 3730 | (long) buf.st_gid, tmp2); | 
|---|
|  | 3731 | } | 
|---|
|  | 3732 | SH_FREE(tmp2); | 
|---|
|  | 3733 | sl_snprintf(theFile->c_group, GROUP_MAX+1, "%d", (long) buf.st_gid); | 
|---|
|  | 3734 | } | 
|---|
|  | 3735 |  | 
|---|
|  | 3736 |  | 
|---|
| [137] | 3737 | if (NULL == sh_unix_getUIDname(SH_ERR_ALL, buf.st_uid, theFile->c_owner, USER_MAX+1)) { | 
|---|
| [1] | 3738 |  | 
|---|
|  | 3739 | tmp2 = sh_util_safe_name (theFile->fullpath); | 
|---|
|  | 3740 |  | 
|---|
|  | 3741 | if (policy == SH_LEVEL_ALLIGNORE) | 
|---|
|  | 3742 | { | 
|---|
|  | 3743 | sh_error_handle (SH_ERR_ALL, FIL__, __LINE__, ENOENT, | 
|---|
|  | 3744 | MSG_FI_NOUSR, | 
|---|
|  | 3745 | (long) buf.st_uid, tmp2); | 
|---|
|  | 3746 | } | 
|---|
|  | 3747 | else | 
|---|
|  | 3748 | { | 
|---|
|  | 3749 | sh_error_handle (ShDFLevel[SH_ERR_T_NAME], FIL__, __LINE__, ENOENT, | 
|---|
|  | 3750 | MSG_FI_NOUSR, | 
|---|
|  | 3751 | (long) buf.st_uid, tmp2); | 
|---|
|  | 3752 | } | 
|---|
|  | 3753 | SH_FREE(tmp2); | 
|---|
|  | 3754 | sl_snprintf(theFile->c_owner, USER_MAX+1, "%d", (long) buf.st_uid); | 
|---|
|  | 3755 | } | 
|---|
|  | 3756 |  | 
|---|
|  | 3757 | /* --- Output the file. --- | 
|---|
|  | 3758 | */ | 
|---|
|  | 3759 | if (flag_err_debug == SL_TRUE) | 
|---|
|  | 3760 | { | 
|---|
|  | 3761 | tmp2 = sh_util_safe_name ((filename == NULL) ? | 
|---|
|  | 3762 | theFile->fullpath : filename); | 
|---|
| [137] | 3763 | (void) sh_unix_time(theFile->mtime, timestr, sizeof(timestr)); | 
|---|
| [1] | 3764 | sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_FI_LIST, | 
|---|
|  | 3765 | theFile->c_mode, | 
|---|
|  | 3766 | theFile->hardlinks, | 
|---|
|  | 3767 | theFile->c_owner, | 
|---|
|  | 3768 | theFile->c_group, | 
|---|
|  | 3769 | (unsigned long) theFile->size, | 
|---|
|  | 3770 | timestr, | 
|---|
|  | 3771 | tmp2); | 
|---|
|  | 3772 | SH_FREE(tmp2); | 
|---|
|  | 3773 | } | 
|---|
|  | 3774 |  | 
|---|
|  | 3775 | /* --- Check for links. --- | 
|---|
|  | 3776 | */ | 
|---|
|  | 3777 | if (theFile->c_mode[0] == 'l') | 
|---|
|  | 3778 | { | 
|---|
|  | 3779 | linknamebuf = SH_ALLOC(PATH_MAX); | 
|---|
|  | 3780 |  | 
|---|
| [22] | 3781 | /* flawfinder: ignore */ | 
|---|
| [1] | 3782 | linksize    = readlink (theFile->fullpath, linknamebuf, PATH_MAX-1); | 
|---|
|  | 3783 |  | 
|---|
|  | 3784 | if (linksize < (PATH_MAX-1) && linksize >= 0) | 
|---|
|  | 3785 | linknamebuf[linksize] = '\0'; | 
|---|
|  | 3786 | else | 
|---|
|  | 3787 | linknamebuf[PATH_MAX-1] = '\0'; | 
|---|
|  | 3788 |  | 
|---|
|  | 3789 | if (linksize < 0) | 
|---|
|  | 3790 | { | 
|---|
| [132] | 3791 | char errbuf[SH_ERRBUF_SIZE]; | 
|---|
| [1] | 3792 | linksize = errno; | 
|---|
|  | 3793 | tmp2 = sh_util_safe_name (theFile->fullpath); | 
|---|
|  | 3794 | sh_error_handle (level, FIL__, __LINE__, linksize, MSG_FI_RDLNK, | 
|---|
| [132] | 3795 | sh_error_message (linksize, errbuf, sizeof(errbuf)), tmp2); | 
|---|
| [1] | 3796 | SH_FREE(tmp2); | 
|---|
|  | 3797 | SH_FREE(linknamebuf); | 
|---|
| [167] | 3798 | theFile->link_path = sh_util_strdup("-"); | 
|---|
| [1] | 3799 | SL_RETURN((-1),_("sh_unix_getinfo")); | 
|---|
|  | 3800 | } | 
|---|
| [138] | 3801 |  | 
|---|
| [167] | 3802 | if (linknamebuf[0] == '/') | 
|---|
|  | 3803 | { | 
|---|
|  | 3804 | theFile->link_path = sh_util_strdup (linknamebuf); | 
|---|
|  | 3805 | } | 
|---|
|  | 3806 | else | 
|---|
|  | 3807 | { | 
|---|
|  | 3808 | tmp = sh_util_dirname(theFile->fullpath); | 
|---|
|  | 3809 | if (tmp) { | 
|---|
|  | 3810 | theFile->link_path = SH_ALLOC(PATH_MAX); | 
|---|
|  | 3811 | sl_strlcpy (theFile->link_path, tmp, PATH_MAX); | 
|---|
|  | 3812 | SH_FREE(tmp); | 
|---|
|  | 3813 | } else { | 
|---|
|  | 3814 | theFile->link_path = SH_ALLOC(PATH_MAX); | 
|---|
|  | 3815 | theFile->link_path[0] = '\0'; | 
|---|
|  | 3816 | } | 
|---|
|  | 3817 | /* | 
|---|
|  | 3818 | * Only attach '/' if not root directory. Handle "//", which | 
|---|
|  | 3819 | * according to POSIX is implementation-defined, and may be | 
|---|
|  | 3820 | * different from "/" (however, three or more '/' will collapse | 
|---|
|  | 3821 | * to one). | 
|---|
|  | 3822 | */ | 
|---|
|  | 3823 | tmp = theFile->link_path; while (*tmp == '/') ++tmp; | 
|---|
|  | 3824 | if (*tmp != '\0') | 
|---|
|  | 3825 | { | 
|---|
|  | 3826 | sl_strlcat (theFile->link_path, "/", PATH_MAX); | 
|---|
|  | 3827 | } | 
|---|
|  | 3828 | sl_strlcat (theFile->link_path, linknamebuf, PATH_MAX); | 
|---|
|  | 3829 | } | 
|---|
|  | 3830 |  | 
|---|
|  | 3831 | /* stat the link | 
|---|
|  | 3832 | */ | 
|---|
|  | 3833 | stat_return = retry_lstat (FIL__, __LINE__, theFile->link_path, &lbuf); | 
|---|
|  | 3834 |  | 
|---|
|  | 3835 | /* check for error | 
|---|
|  | 3836 | */ | 
|---|
|  | 3837 | if (stat_return != 0) | 
|---|
|  | 3838 | { | 
|---|
|  | 3839 | stat_return = errno; | 
|---|
|  | 3840 | tmp  = sh_util_safe_name (theFile->fullpath); | 
|---|
|  | 3841 | tmp2 = sh_util_safe_name (theFile->link_path); | 
|---|
|  | 3842 | if (stat_return != ENOENT) | 
|---|
|  | 3843 | { | 
|---|
| [192] | 3844 | uid_t euid; | 
|---|
| [167] | 3845 | char errbuf[SH_ERRBUF_SIZE]; | 
|---|
| [192] | 3846 |  | 
|---|
|  | 3847 | (void) sl_get_euid(&euid); | 
|---|
| [167] | 3848 | sh_error_handle (level, FIL__, __LINE__, stat_return, | 
|---|
| [192] | 3849 | MSG_FI_STAT, | 
|---|
|  | 3850 | _("lstat"), | 
|---|
| [167] | 3851 | sh_error_message (stat_return,errbuf, sizeof(errbuf)), | 
|---|
| [192] | 3852 | (long) euid, | 
|---|
| [167] | 3853 | tmp2); | 
|---|
|  | 3854 | } | 
|---|
|  | 3855 | else | 
|---|
|  | 3856 | { | 
|---|
|  | 3857 | /* a dangling link -- everybody seems to have plenty of them | 
|---|
|  | 3858 | */ | 
|---|
|  | 3859 | sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_FI_DLNK, | 
|---|
|  | 3860 | tmp, tmp2); | 
|---|
|  | 3861 | } | 
|---|
|  | 3862 | theFile->linkisok = BAD; | 
|---|
| [93] | 3863 | SH_FREE(tmp); | 
|---|
| [167] | 3864 | SH_FREE(tmp2); | 
|---|
|  | 3865 | SH_FREE(linknamebuf); | 
|---|
|  | 3866 | /* | 
|---|
|  | 3867 | * changed Tue Feb 10 16:16:13 CET 2004: | 
|---|
|  | 3868 | *  add dangling symlinks into database | 
|---|
|  | 3869 | * SL_RETURN((-1),_("sh_unix_getinfo")); | 
|---|
|  | 3870 | */ | 
|---|
|  | 3871 | theFile->linkmode = 0; | 
|---|
|  | 3872 | SL_RETURN((0),_("sh_unix_getinfo")); | 
|---|
| [93] | 3873 | } | 
|---|
| [1] | 3874 |  | 
|---|
| [167] | 3875 | theFile->linkisok = GOOD; | 
|---|
|  | 3876 |  | 
|---|
|  | 3877 |  | 
|---|
|  | 3878 | /* --- Determine file type. --- | 
|---|
|  | 3879 | */ | 
|---|
|  | 3880 | sh_unix_getinfo_type (&lbuf, &type, theFile->link_c_mode); | 
|---|
|  | 3881 | theFile->type = type; | 
|---|
|  | 3882 |  | 
|---|
|  | 3883 | /* --- Determine permissions. --- | 
|---|
|  | 3884 | */ | 
|---|
|  | 3885 | sh_unix_getinfo_mode (&lbuf, &mode, theFile->link_c_mode); | 
|---|
|  | 3886 | theFile->linkmode = lbuf.st_mode; | 
|---|
|  | 3887 |  | 
|---|
|  | 3888 | /* --- Output the link. --- | 
|---|
|  | 3889 | */ | 
|---|
|  | 3890 | if (theFile->linkisok == GOOD) | 
|---|
|  | 3891 | { | 
|---|
|  | 3892 | tmp2 = sh_util_safe_name (linknamebuf); | 
|---|
|  | 3893 | sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_FI_LLNK, | 
|---|
|  | 3894 | theFile->link_c_mode, tmp2); | 
|---|
|  | 3895 | SH_FREE(tmp2); | 
|---|
|  | 3896 | } | 
|---|
|  | 3897 | SH_FREE(linknamebuf); | 
|---|
|  | 3898 | } | 
|---|
|  | 3899 | else /* not a link */ | 
|---|
|  | 3900 | { | 
|---|
|  | 3901 | if (content) | 
|---|
|  | 3902 | { | 
|---|
| [169] | 3903 | #ifdef HAVE_LIBZ | 
|---|
| [171] | 3904 | unsigned long   clen; | 
|---|
|  | 3905 | unsigned char * compressed; | 
|---|
|  | 3906 | #ifdef HAVE_COMPRESSBOUND | 
|---|
|  | 3907 | clen       = compressBound(sh_string_len(content)); | 
|---|
|  | 3908 | #else | 
|---|
|  | 3909 | if (sh_string_len(content) > 10*SH_TXT_MAX) | 
|---|
|  | 3910 | clen = SH_TXT_MAX; | 
|---|
|  | 3911 | else | 
|---|
|  | 3912 | clen = 13 + (int)(1.0001*sh_string_len(content)); | 
|---|
|  | 3913 | #endif | 
|---|
|  | 3914 | compressed = SH_ALLOC(clen); | 
|---|
| [169] | 3915 | if (Z_OK == compress(compressed, &clen, | 
|---|
|  | 3916 | (unsigned char *) sh_string_str(content), | 
|---|
|  | 3917 | sh_string_len(content))) | 
|---|
|  | 3918 | { | 
|---|
|  | 3919 | if (clen < SH_TXT_MAX) | 
|---|
|  | 3920 | { | 
|---|
|  | 3921 | sh_util_base64_enc_alloc (&(theFile->link_path), | 
|---|
|  | 3922 | (char *) compressed, clen); | 
|---|
|  | 3923 | } | 
|---|
|  | 3924 | else | 
|---|
|  | 3925 | { | 
|---|
|  | 3926 | char tmsg[128]; | 
|---|
|  | 3927 | char * tpath = sh_util_safe_name (theFile->fullpath); | 
|---|
|  | 3928 | sl_snprintf(tmsg, sizeof(tmsg), | 
|---|
|  | 3929 | _("compressed file too large (%lu bytes)"), | 
|---|
|  | 3930 | clen); | 
|---|
|  | 3931 | sh_error_handle (SH_ERR_WARN, FIL__, __LINE__, -1, | 
|---|
|  | 3932 | MSG_E_SUBGPATH, tmsg, | 
|---|
|  | 3933 | _("sh_unix_getinfo"), tpath); | 
|---|
|  | 3934 | SH_FREE(tpath); | 
|---|
|  | 3935 | } | 
|---|
|  | 3936 | } | 
|---|
|  | 3937 | SH_FREE(compressed); | 
|---|
|  | 3938 | #endif | 
|---|
|  | 3939 | sh_string_destroy(&content); | 
|---|
| [167] | 3940 | } | 
|---|
|  | 3941 | } | 
|---|
| [1] | 3942 | SL_RETURN((0),_("sh_unix_getinfo")); | 
|---|
|  | 3943 | } | 
|---|
|  | 3944 |  | 
|---|
|  | 3945 | /*  #if defined (SH_WITH_CLIENT) || defined (SH_STANDALONE)  */ | 
|---|
|  | 3946 | #endif | 
|---|
|  | 3947 |  | 
|---|
| [169] | 3948 | int sh_unix_unlock(char * lockfile, char * flag) | 
|---|
|  | 3949 | { | 
|---|
|  | 3950 | int         error = 0; | 
|---|
|  | 3951 |  | 
|---|
|  | 3952 | SL_ENTER(_("sh_unix_unlock")); | 
|---|
| [1] | 3953 |  | 
|---|
| [169] | 3954 | if (sh.flag.isdaemon == S_FALSE && flag == NULL) | 
|---|
|  | 3955 | SL_RETURN((0),_("sh_unix_unlock")); | 
|---|
|  | 3956 |  | 
|---|
|  | 3957 | /* --- Logfile is not locked to us. --- | 
|---|
|  | 3958 | */ | 
|---|
|  | 3959 | if (sh.flag.islocked == BAD && flag != NULL) | 
|---|
|  | 3960 | SL_RETURN((-1),_("sh_unix_unlock")); | 
|---|
|  | 3961 |  | 
|---|
|  | 3962 | /* --- Check whether the directory is secure. --- | 
|---|
|  | 3963 | */ | 
|---|
|  | 3964 | if (0 != tf_trust_check (lockfile, SL_YESPRIV)) | 
|---|
|  | 3965 | SL_RETURN((-1),_("sh_unix_unlock")); | 
|---|
|  | 3966 |  | 
|---|
|  | 3967 | /* --- Delete the lock file. --- | 
|---|
|  | 3968 | */ | 
|---|
|  | 3969 | error = retry_aud_unlink (FIL__, __LINE__, lockfile); | 
|---|
|  | 3970 |  | 
|---|
|  | 3971 | if (error == 0) | 
|---|
|  | 3972 | { | 
|---|
|  | 3973 | if (flag != NULL) | 
|---|
|  | 3974 | sh.flag.islocked = BAD; /* not locked anymore */ | 
|---|
|  | 3975 | } | 
|---|
|  | 3976 | else if (flag != NULL) | 
|---|
|  | 3977 | { | 
|---|
|  | 3978 | char errbuf[SH_ERRBUF_SIZE]; | 
|---|
|  | 3979 | error = errno; | 
|---|
|  | 3980 | sh_error_handle ((-1), FIL__, __LINE__, error, MSG_E_UNLNK, | 
|---|
|  | 3981 | sh_error_message(error, errbuf, sizeof(errbuf)), | 
|---|
|  | 3982 | lockfile); | 
|---|
|  | 3983 | SL_RETURN((-1),_("sh_unix_unlock")); | 
|---|
|  | 3984 | } | 
|---|
|  | 3985 | SL_RETURN((0),_("sh_unix_unlock")); | 
|---|
|  | 3986 | } | 
|---|
|  | 3987 |  | 
|---|
|  | 3988 | int sh_unix_lock (char * lockfile, char * flag) | 
|---|
|  | 3989 | { | 
|---|
|  | 3990 | int filed; | 
|---|
|  | 3991 | int errnum; | 
|---|
|  | 3992 | char myPid[64]; | 
|---|
|  | 3993 | SL_TICKET  fd; | 
|---|
|  | 3994 | extern int get_the_fd (SL_TICKET ticket); | 
|---|
|  | 3995 |  | 
|---|
|  | 3996 | SL_ENTER(_("sh_unix_lock")); | 
|---|
|  | 3997 |  | 
|---|
|  | 3998 | sprintf (myPid, "%ld\n", (long) sh.pid);             /* known to fit  */ | 
|---|
|  | 3999 |  | 
|---|
|  | 4000 | fd = sl_open_safe_rdwr (lockfile, SL_YESPRIV);       /* fails if file exists */ | 
|---|
|  | 4001 |  | 
|---|
|  | 4002 | if (!SL_ISERROR(fd)) | 
|---|
|  | 4003 | { | 
|---|
|  | 4004 | errnum = sl_write (fd, myPid, sl_strlen(myPid)); | 
|---|
|  | 4005 | filed = get_the_fd(fd); | 
|---|
|  | 4006 | fchmod (filed, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH); | 
|---|
|  | 4007 | sl_close (fd); | 
|---|
|  | 4008 |  | 
|---|
|  | 4009 | if (!SL_ISERROR(errnum)) | 
|---|
|  | 4010 | { | 
|---|
|  | 4011 | if (flag != NULL) | 
|---|
|  | 4012 | sh.flag.islocked = GOOD; | 
|---|
|  | 4013 | SL_RETURN((0),_("sh_unix_lock")); | 
|---|
|  | 4014 | } | 
|---|
|  | 4015 | } | 
|---|
|  | 4016 |  | 
|---|
|  | 4017 | TPT((0, FIL__, __LINE__, _("msg=<open pid file failed>\n"))); | 
|---|
|  | 4018 | if (flag != NULL) | 
|---|
|  | 4019 | sh.flag.islocked       = BAD; | 
|---|
|  | 4020 | SL_RETURN((-1),_("sh_unix_lock")); | 
|---|
|  | 4021 |  | 
|---|
|  | 4022 | /* notreached */ | 
|---|
|  | 4023 | } | 
|---|
|  | 4024 |  | 
|---|
|  | 4025 |  | 
|---|
| [1] | 4026 | /* check whether file is locked | 
|---|
|  | 4027 | */ | 
|---|
|  | 4028 | int sh_unix_test_and_lock (char * filename, char * lockfile) | 
|---|
|  | 4029 | { | 
|---|
|  | 4030 | static        struct stat   buf; | 
|---|
|  | 4031 | int           status = 0; | 
|---|
|  | 4032 |  | 
|---|
|  | 4033 |  | 
|---|
|  | 4034 | SL_TICKET     fd; | 
|---|
|  | 4035 | char          line_in[128]; | 
|---|
|  | 4036 |  | 
|---|
|  | 4037 | SL_ENTER(_("sh_unix_test_and_lock")); | 
|---|
|  | 4038 |  | 
|---|
|  | 4039 | status = retry_lstat (FIL__, __LINE__, lockfile, &buf); | 
|---|
|  | 4040 |  | 
|---|
|  | 4041 | /* --- No lock file found, try to lock. --- | 
|---|
|  | 4042 | */ | 
|---|
|  | 4043 |  | 
|---|
|  | 4044 | if (status < 0 && errno == ENOENT) | 
|---|
|  | 4045 | { | 
|---|
|  | 4046 | if (0 == sh_unix_lock (lockfile, filename)) | 
|---|
|  | 4047 | { | 
|---|
|  | 4048 | if (filename != NULL) | 
|---|
|  | 4049 | sh.flag.islocked = GOOD; | 
|---|
|  | 4050 | SL_RETURN((0),_("sh_unix_test_and_lock")); | 
|---|
|  | 4051 | } | 
|---|
| [76] | 4052 | else | 
|---|
|  | 4053 | { | 
|---|
|  | 4054 | sh_error_handle ((-1), FIL__, __LINE__, status, | 
|---|
|  | 4055 | MSG_E_SUBGEN, | 
|---|
|  | 4056 | (filename == NULL) ? _("Cannot create PID file") : _("Cannot create lock file"), | 
|---|
|  | 4057 | _("sh_unix_test_and_lock")); | 
|---|
|  | 4058 | SL_RETURN((-1),_("sh_unix_test_and_lock")); | 
|---|
|  | 4059 | } | 
|---|
| [1] | 4060 | } | 
|---|
|  | 4061 | else if (status == 0 && buf.st_size == 0) | 
|---|
|  | 4062 | { | 
|---|
|  | 4063 | if (filename != NULL) | 
|---|
|  | 4064 | sh.flag.islocked = GOOD; | 
|---|
|  | 4065 | sh_unix_unlock (lockfile, filename); | 
|---|
|  | 4066 | if (filename != NULL) | 
|---|
|  | 4067 | sh.flag.islocked = BAD; | 
|---|
|  | 4068 | if (0 == sh_unix_lock (lockfile, filename)) | 
|---|
|  | 4069 | { | 
|---|
|  | 4070 | if (filename != NULL) | 
|---|
|  | 4071 | sh.flag.islocked = GOOD; | 
|---|
|  | 4072 | SL_RETURN((0),_("sh_unix_test_and_lock")); | 
|---|
|  | 4073 | } | 
|---|
|  | 4074 | else | 
|---|
|  | 4075 | { | 
|---|
| [76] | 4076 | sh_error_handle ((-1), FIL__, __LINE__, status, | 
|---|
|  | 4077 | MSG_E_SUBGEN, | 
|---|
|  | 4078 | (filename == NULL) ? _("Cannot create PID file") : _("Cannot create lock file"), | 
|---|
|  | 4079 | _("sh_unix_test_and_lock")); | 
|---|
| [1] | 4080 | SL_RETURN((-1),_("sh_unix_test_and_lock")); | 
|---|
|  | 4081 | } | 
|---|
|  | 4082 | } | 
|---|
|  | 4083 |  | 
|---|
|  | 4084 | /* --- Check on lock. --- | 
|---|
|  | 4085 | */ | 
|---|
|  | 4086 |  | 
|---|
|  | 4087 | if (status >= 0) | 
|---|
|  | 4088 | { | 
|---|
|  | 4089 | fd = sl_open_read (lockfile, SL_YESPRIV); | 
|---|
|  | 4090 | if (SL_ISERROR(fd)) | 
|---|
|  | 4091 | sh_error_handle ((-1), FIL__, __LINE__, fd, | 
|---|
|  | 4092 | MSG_E_SUBGEN, | 
|---|
|  | 4093 | (filename == NULL) ? _("Cannot open PID file for read") : _("Cannot open lock file for read"), | 
|---|
|  | 4094 | _("sh_unix_test_and_lock")); | 
|---|
|  | 4095 | } | 
|---|
|  | 4096 | else | 
|---|
|  | 4097 | fd = -1; | 
|---|
|  | 4098 |  | 
|---|
|  | 4099 | if (!SL_ISERROR(fd)) | 
|---|
|  | 4100 | { | 
|---|
|  | 4101 | /* read the PID in the lock file | 
|---|
|  | 4102 | */ | 
|---|
| [76] | 4103 | status = sl_read (fd, line_in, sizeof(line_in)); | 
|---|
|  | 4104 | line_in[sizeof(line_in)-1] = '\0'; | 
|---|
| [1] | 4105 |  | 
|---|
|  | 4106 | /* convert to numeric | 
|---|
|  | 4107 | */ | 
|---|
|  | 4108 | if (status > 0) | 
|---|
|  | 4109 | { | 
|---|
|  | 4110 | errno  = 0; | 
|---|
|  | 4111 | status = strtol(line_in, (char **)NULL, 10); | 
|---|
|  | 4112 | if (errno == ERANGE || status <= 0) | 
|---|
|  | 4113 | { | 
|---|
|  | 4114 | sh_error_handle ((-1), FIL__, __LINE__, status, | 
|---|
|  | 4115 | MSG_E_SUBGEN, | 
|---|
|  | 4116 | (filename == NULL) ? _("Bad PID in PID file") : _("Bad PID in lock file"), | 
|---|
|  | 4117 | _("sh_unix_test_and_lock")); | 
|---|
|  | 4118 |  | 
|---|
|  | 4119 | status = -1; | 
|---|
|  | 4120 | } | 
|---|
|  | 4121 | } | 
|---|
|  | 4122 | else | 
|---|
|  | 4123 | { | 
|---|
|  | 4124 | sh_error_handle ((-1), FIL__, __LINE__, status, | 
|---|
|  | 4125 | MSG_E_SUBGEN, | 
|---|
|  | 4126 | (filename == NULL) ? _("Cannot read PID file") : _("Cannot read lock file"), | 
|---|
|  | 4127 | _("sh_unix_test_and_lock")); | 
|---|
|  | 4128 | } | 
|---|
|  | 4129 | sl_close(fd); | 
|---|
|  | 4130 |  | 
|---|
| [162] | 4131 | if (status > 0 && (unsigned int) status == sh.pid) | 
|---|
| [1] | 4132 | { | 
|---|
|  | 4133 | if (filename != NULL) | 
|---|
|  | 4134 | sh.flag.islocked = GOOD; | 
|---|
|  | 4135 | SL_RETURN((0),_("sh_unix_test_and_lock")); | 
|---|
|  | 4136 | } | 
|---|
|  | 4137 |  | 
|---|
|  | 4138 |  | 
|---|
|  | 4139 | /* --- Check whether the process exists. --- | 
|---|
|  | 4140 | */ | 
|---|
|  | 4141 | if (status > 0) | 
|---|
|  | 4142 | { | 
|---|
|  | 4143 | errno  = 0; | 
|---|
|  | 4144 | status = aud_kill (FIL__, __LINE__, status, 0); | 
|---|
|  | 4145 |  | 
|---|
|  | 4146 | /* Does not exist, so remove the stale lock | 
|---|
|  | 4147 | * and create a new one. | 
|---|
|  | 4148 | */ | 
|---|
|  | 4149 | if (status < 0 && errno == ESRCH) | 
|---|
|  | 4150 | { | 
|---|
|  | 4151 | if (filename != NULL) | 
|---|
|  | 4152 | sh.flag.islocked = GOOD; | 
|---|
|  | 4153 | if (0 != sh_unix_unlock(lockfile, filename) && (filename !=NULL)) | 
|---|
|  | 4154 | sh.flag.islocked = BAD; | 
|---|
|  | 4155 | else | 
|---|
|  | 4156 | { | 
|---|
|  | 4157 | if (0 == sh_unix_lock  (lockfile, filename)) | 
|---|
|  | 4158 | { | 
|---|
|  | 4159 | if (filename != NULL) | 
|---|
|  | 4160 | sh.flag.islocked = GOOD; | 
|---|
|  | 4161 | SL_RETURN((0),_("sh_unix_test_and_lock")); | 
|---|
|  | 4162 | } | 
|---|
|  | 4163 | else | 
|---|
|  | 4164 | { | 
|---|
|  | 4165 | sh_error_handle ((-1), FIL__, __LINE__, status, | 
|---|
|  | 4166 | MSG_E_SUBGEN, | 
|---|
|  | 4167 | (filename == NULL) ? _("Cannot create PID file") : _("Cannot create lock file"), | 
|---|
|  | 4168 | _("sh_unix_test_and_lock")); | 
|---|
|  | 4169 | } | 
|---|
|  | 4170 | if (filename != NULL) | 
|---|
|  | 4171 | sh.flag.islocked = BAD; | 
|---|
|  | 4172 | } | 
|---|
|  | 4173 | } | 
|---|
|  | 4174 | else | 
|---|
|  | 4175 | { | 
|---|
|  | 4176 | sh_error_handle ((-1), FIL__, __LINE__, status, | 
|---|
|  | 4177 | MSG_E_SUBGEN, | 
|---|
|  | 4178 | (filename == NULL) ? _("Cannot remove stale PID file, PID may be a running process") : _("Cannot remove stale lock file, PID may be a running process"), | 
|---|
|  | 4179 | _("sh_unix_test_and_lock")); | 
|---|
|  | 4180 | if (filename != NULL) | 
|---|
|  | 4181 | sh.flag.islocked = BAD; | 
|---|
|  | 4182 | } | 
|---|
|  | 4183 | } | 
|---|
|  | 4184 | } | 
|---|
|  | 4185 | SL_RETURN((-1),_("sh_unix_testlock")); | 
|---|
|  | 4186 | } | 
|---|
|  | 4187 |  | 
|---|
|  | 4188 | /* write the PID file | 
|---|
|  | 4189 | */ | 
|---|
|  | 4190 | int sh_unix_write_pid_file() | 
|---|
|  | 4191 | { | 
|---|
|  | 4192 | return sh_unix_test_and_lock(NULL, sh.srvlog.alt); | 
|---|
|  | 4193 | } | 
|---|
|  | 4194 |  | 
|---|
|  | 4195 | /* write lock for filename | 
|---|
|  | 4196 | */ | 
|---|
|  | 4197 | int sh_unix_write_lock_file(char * filename) | 
|---|
|  | 4198 | { | 
|---|
| [34] | 4199 | size_t len; | 
|---|
|  | 4200 | int    res; | 
|---|
| [1] | 4201 | char * lockfile; | 
|---|
|  | 4202 |  | 
|---|
|  | 4203 | if (filename == NULL) | 
|---|
|  | 4204 | return (-1); | 
|---|
|  | 4205 |  | 
|---|
| [34] | 4206 | len = sl_strlen(filename); | 
|---|
|  | 4207 | if (sl_ok_adds(len, 6)) | 
|---|
|  | 4208 | len += 6; | 
|---|
|  | 4209 | lockfile = SH_ALLOC(len); | 
|---|
|  | 4210 | sl_strlcpy(lockfile, filename,   len); | 
|---|
|  | 4211 | sl_strlcat(lockfile, _(".lock"), len); | 
|---|
|  | 4212 | res = sh_unix_test_and_lock(filename, lockfile); | 
|---|
| [1] | 4213 | SH_FREE(lockfile); | 
|---|
| [34] | 4214 | return res; | 
|---|
| [1] | 4215 | } | 
|---|
|  | 4216 |  | 
|---|
|  | 4217 | /* rm lock for filename | 
|---|
|  | 4218 | */ | 
|---|
|  | 4219 | int sh_unix_rm_lock_file(char * filename) | 
|---|
|  | 4220 | { | 
|---|
| [34] | 4221 | size_t len; | 
|---|
|  | 4222 | int res; | 
|---|
| [1] | 4223 | char * lockfile; | 
|---|
|  | 4224 |  | 
|---|
|  | 4225 | if (filename == NULL) | 
|---|
|  | 4226 | return (-1); | 
|---|
|  | 4227 |  | 
|---|
| [34] | 4228 | len = sl_strlen(filename); | 
|---|
|  | 4229 | if (sl_ok_adds(len, 6)) | 
|---|
|  | 4230 | len += 6; | 
|---|
|  | 4231 | lockfile = SH_ALLOC(len); | 
|---|
|  | 4232 | sl_strlcpy(lockfile, filename,   len); | 
|---|
|  | 4233 | sl_strlcat(lockfile, _(".lock"), len); | 
|---|
|  | 4234 |  | 
|---|
|  | 4235 | res = sh_unix_unlock(lockfile, filename); | 
|---|
| [1] | 4236 | SH_FREE(lockfile); | 
|---|
| [34] | 4237 | return res; | 
|---|
| [1] | 4238 | } | 
|---|
|  | 4239 |  | 
|---|
|  | 4240 | /* rm lock for filename | 
|---|
|  | 4241 | */ | 
|---|
|  | 4242 | int sh_unix_rm_pid_file() | 
|---|
|  | 4243 | { | 
|---|
|  | 4244 | return sh_unix_unlock(sh.srvlog.alt, NULL); | 
|---|
|  | 4245 | } | 
|---|
|  | 4246 |  | 
|---|
|  | 4247 | /* Test whether file exists | 
|---|
|  | 4248 | */ | 
|---|
| [78] | 4249 | int sh_unix_file_exists(char * path) | 
|---|
| [1] | 4250 | { | 
|---|
|  | 4251 | struct stat buf; | 
|---|
|  | 4252 |  | 
|---|
| [78] | 4253 | SL_ENTER(_("sh_unix_file_exists")); | 
|---|
| [1] | 4254 |  | 
|---|
|  | 4255 | if (-1 == retry_stat(FIL__, __LINE__, path, &buf)) | 
|---|
| [78] | 4256 | SL_RETURN( S_FALSE, _("sh_unix_file_exists")); | 
|---|
| [1] | 4257 | else | 
|---|
| [78] | 4258 | SL_RETURN( S_TRUE,  _("sh_unix_file_exists")); | 
|---|
| [1] | 4259 | } | 
|---|
|  | 4260 |  | 
|---|
|  | 4261 |  | 
|---|
| [78] | 4262 | /* Test whether file exists, is a character device, and allows read | 
|---|
|  | 4263 | * access. | 
|---|
| [1] | 4264 | */ | 
|---|
| [78] | 4265 | int sh_unix_device_readable(int fd) | 
|---|
| [1] | 4266 | { | 
|---|
|  | 4267 | struct stat buf; | 
|---|
|  | 4268 |  | 
|---|
| [78] | 4269 | SL_ENTER(_("sh_unix_device_readable")); | 
|---|
| [1] | 4270 |  | 
|---|
|  | 4271 | if (retry_fstat(FIL__, __LINE__, fd, &buf) == -1) | 
|---|
| [78] | 4272 | SL_RETURN( (-1), _("sh_unix_device_readable")); | 
|---|
|  | 4273 | else if ( S_ISCHR(buf.st_mode) &&  0 != (S_IROTH & buf.st_mode) ) | 
|---|
|  | 4274 | SL_RETURN( (0), _("sh_unix_device_readable")); | 
|---|
| [1] | 4275 | else | 
|---|
| [78] | 4276 | SL_RETURN( (-1), _("sh_unix_device_readable")); | 
|---|
| [1] | 4277 | } | 
|---|
|  | 4278 |  | 
|---|
|  | 4279 | static char preq[16]; | 
|---|
|  | 4280 |  | 
|---|
|  | 4281 | /* return true if database is remote | 
|---|
|  | 4282 | */ | 
|---|
|  | 4283 | int file_is_remote () | 
|---|
|  | 4284 | { | 
|---|
|  | 4285 | static int init = 0; | 
|---|
| [42] | 4286 | struct stat buf; | 
|---|
| [1] | 4287 |  | 
|---|
|  | 4288 | SL_ENTER(_("file_is_remote")); | 
|---|
|  | 4289 |  | 
|---|
|  | 4290 | if (init == 0) | 
|---|
|  | 4291 | { | 
|---|
|  | 4292 | sl_strlcpy(preq, _("REQ_FROM_SERVER"), 16); | 
|---|
|  | 4293 | ++init; | 
|---|
|  | 4294 | } | 
|---|
|  | 4295 | if (0 == sl_strncmp (sh.data.path, preq, 15)) | 
|---|
|  | 4296 | { | 
|---|
| [42] | 4297 | if (sh.data.path[15] != '\0') /* should be start of path */ | 
|---|
|  | 4298 | { | 
|---|
|  | 4299 | if (0 == stat(&(sh.data.path[15]), &buf)) | 
|---|
|  | 4300 | { | 
|---|
|  | 4301 | SL_RETURN( S_FALSE, _("file_is_remote")); | 
|---|
|  | 4302 | } | 
|---|
|  | 4303 | } | 
|---|
| [1] | 4304 | SL_RETURN( S_TRUE, _("file_is_remote")); | 
|---|
|  | 4305 | } | 
|---|
|  | 4306 | SL_RETURN( S_FALSE, _("file_is_remote")); | 
|---|
|  | 4307 | } | 
|---|
|  | 4308 |  | 
|---|
|  | 4309 | /* Return the path to the configuration/database file. | 
|---|
|  | 4310 | */ | 
|---|
|  | 4311 | char * file_path(char what, char flag) | 
|---|
|  | 4312 | { | 
|---|
|  | 4313 | static int init = 0; | 
|---|
|  | 4314 |  | 
|---|
|  | 4315 | SL_ENTER(_("file_path")); | 
|---|
|  | 4316 |  | 
|---|
|  | 4317 | if (init == 0) | 
|---|
|  | 4318 | { | 
|---|
|  | 4319 | sl_strlcpy(preq, _("REQ_FROM_SERVER"), 16); | 
|---|
|  | 4320 | ++init; | 
|---|
|  | 4321 | } | 
|---|
|  | 4322 |  | 
|---|
|  | 4323 | switch (what) | 
|---|
|  | 4324 | { | 
|---|
|  | 4325 |  | 
|---|
|  | 4326 | case 'C': | 
|---|
|  | 4327 | if (0 == sl_strncmp (sh.conf.path, preq, 15)) | 
|---|
|  | 4328 | { | 
|---|
|  | 4329 | #if defined(SH_WITH_SERVER) | 
|---|
|  | 4330 | if (sh.flag.isserver == S_TRUE && sl_strlen(sh.conf.path) == 15) | 
|---|
|  | 4331 | SL_RETURN( NULL, _("file_path")); | 
|---|
|  | 4332 | if (sh.flag.isserver == S_TRUE) | 
|---|
|  | 4333 | SL_RETURN( &(sh.conf.path[15]), _("file_path")); | 
|---|
|  | 4334 | #endif | 
|---|
|  | 4335 | if (flag == 'R') | 
|---|
|  | 4336 | SL_RETURN( preq, _("file_path")); | 
|---|
|  | 4337 | if (flag == 'I') | 
|---|
|  | 4338 | { | 
|---|
|  | 4339 | if (sl_strlen(sh.conf.path) == 15) | 
|---|
|  | 4340 | SL_RETURN( NULL, _("file_path")); | 
|---|
|  | 4341 | else | 
|---|
|  | 4342 | SL_RETURN( &(sh.conf.path[15]), _("file_path")); | 
|---|
|  | 4343 | } | 
|---|
|  | 4344 | SL_RETURN ( preq, _("file_path")); | 
|---|
|  | 4345 | } | 
|---|
|  | 4346 | else | 
|---|
|  | 4347 | SL_RETURN( sh.conf.path, _("file_path")); | 
|---|
|  | 4348 | /* break; *//* unreachable */ | 
|---|
|  | 4349 |  | 
|---|
|  | 4350 | case 'D': | 
|---|
|  | 4351 | if (0 == sl_strncmp (sh.data.path, preq, 15)) | 
|---|
|  | 4352 | { | 
|---|
|  | 4353 | if (flag == 'R') | 
|---|
|  | 4354 | SL_RETURN( preq, _("file_path")); | 
|---|
|  | 4355 | if (flag == 'W' && sl_strlen(sh.data.path) == 15) | 
|---|
|  | 4356 | SL_RETURN (NULL, _("file_path")); | 
|---|
|  | 4357 | if (flag == 'W') | 
|---|
|  | 4358 | SL_RETURN( &(sh.data.path[15]), _("file_path")); | 
|---|
|  | 4359 | } | 
|---|
|  | 4360 | else | 
|---|
|  | 4361 | SL_RETURN( sh.data.path, _("file_path")); | 
|---|
|  | 4362 | break; | 
|---|
|  | 4363 |  | 
|---|
|  | 4364 | default: | 
|---|
|  | 4365 | SL_RETURN( NULL, _("file_path")); | 
|---|
|  | 4366 | } | 
|---|
|  | 4367 |  | 
|---|
|  | 4368 | return NULL; /* notreached */ | 
|---|
|  | 4369 | } | 
|---|
|  | 4370 | /************************************************/ | 
|---|
|  | 4371 | /****   Mlock   Utilities                    ****/ | 
|---|
|  | 4372 | /************************************************/ | 
|---|
|  | 4373 |  | 
|---|
|  | 4374 | #include <limits.h> | 
|---|
|  | 4375 |  | 
|---|
|  | 4376 | int sh_unix_pagesize() | 
|---|
|  | 4377 | { | 
|---|
|  | 4378 | int pagesize = 4096; | 
|---|
|  | 4379 | #if defined(_SC_PAGESIZE) | 
|---|
|  | 4380 | pagesize = sysconf(_SC_PAGESIZE); | 
|---|
|  | 4381 | #elif defined(_SC_PAGE_SIZE) | 
|---|
|  | 4382 | pagesize = sysconf(_SC_PAGE_SIZE); | 
|---|
|  | 4383 | #elif defined(HAVE_GETPAGESIZE) | 
|---|
|  | 4384 | pagesize = getpagesize(); | 
|---|
|  | 4385 | #elif defined(PAGESIZE) | 
|---|
|  | 4386 | pagesize = PAGESIZE; | 
|---|
|  | 4387 | #endif | 
|---|
|  | 4388 |  | 
|---|
|  | 4389 | return ((pagesize > 0) ? pagesize : 4096); | 
|---|
|  | 4390 | } | 
|---|
|  | 4391 |  | 
|---|
|  | 4392 | typedef struct sh_page_lt { | 
|---|
|  | 4393 | unsigned long  page_start; | 
|---|
|  | 4394 | int            page_refcount; | 
|---|
| [19] | 4395 | char           file[64]; | 
|---|
|  | 4396 | int            line; | 
|---|
| [1] | 4397 | struct sh_page_lt * next; | 
|---|
|  | 4398 | } sh_page_l; | 
|---|
|  | 4399 |  | 
|---|
|  | 4400 | sh_page_l * sh_page_locked = NULL; | 
|---|
|  | 4401 | volatile int page_locking = 0; | 
|---|
|  | 4402 |  | 
|---|
|  | 4403 | unsigned long sh_unix_lookup_page (void * in_addr, size_t len, int * num_pages) | 
|---|
|  | 4404 | { | 
|---|
|  | 4405 | int pagesize = sh_unix_pagesize(); | 
|---|
|  | 4406 | unsigned long  addr = (unsigned long) in_addr; | 
|---|
|  | 4407 |  | 
|---|
|  | 4408 | unsigned long pagebase; | 
|---|
|  | 4409 | unsigned long pagediff; | 
|---|
|  | 4410 | unsigned long pagenum   = addr / pagesize; | 
|---|
|  | 4411 |  | 
|---|
|  | 4412 | SL_ENTER(_("sh_unix_lookup_page")); | 
|---|
|  | 4413 | #if 0 | 
|---|
|  | 4414 | fprintf(stderr, "mlock: --> base %ld, pagenum: %ld\n", | 
|---|
|  | 4415 | addr, pagenum); | 
|---|
|  | 4416 | #endif | 
|---|
|  | 4417 |  | 
|---|
|  | 4418 | /* address of first page | 
|---|
|  | 4419 | */ | 
|---|
|  | 4420 | pagebase = pagenum * pagesize; | 
|---|
|  | 4421 |  | 
|---|
|  | 4422 | /* number of pages | 
|---|
|  | 4423 | */ | 
|---|
|  | 4424 | pagediff = (addr + len) - pagebase; | 
|---|
|  | 4425 | pagenum  = pagediff / pagesize; | 
|---|
|  | 4426 | if (pagenum * pagesize < pagediff) | 
|---|
|  | 4427 | ++pagenum; | 
|---|
|  | 4428 |  | 
|---|
|  | 4429 | #if 0 | 
|---|
|  | 4430 | fprintf(stderr, "mlock: --> pagebase %ld, pagediff %ld, (addr + len) %ld\n", | 
|---|
|  | 4431 | pagebase, pagediff, (addr + len)); | 
|---|
|  | 4432 | #endif | 
|---|
|  | 4433 |  | 
|---|
|  | 4434 | *num_pages = pagenum; | 
|---|
|  | 4435 | SL_RETURN((pagebase), _("sh_unix_lookup_page")); | 
|---|
|  | 4436 | } | 
|---|
|  | 4437 |  | 
|---|
|  | 4438 |  | 
|---|
|  | 4439 | #if defined(HAVE_MLOCK) && !defined(HAVE_BROKEN_MLOCK) | 
|---|
| [134] | 4440 |  | 
|---|
|  | 4441 | SH_MUTEX_STATIC(mutex_mlock,PTHREAD_MUTEX_INITIALIZER); | 
|---|
|  | 4442 |  | 
|---|
| [170] | 4443 | int sh_unix_mlock (const char * file, int line, void * in_addr, size_t len) | 
|---|
| [1] | 4444 | { | 
|---|
|  | 4445 | int         num_pages; | 
|---|
|  | 4446 | int         status = 0; | 
|---|
|  | 4447 | int         pagesize; | 
|---|
|  | 4448 | sh_page_l * page_list = sh_page_locked; | 
|---|
|  | 4449 | unsigned long addr; | 
|---|
|  | 4450 | #ifdef TEST_MLOCK | 
|---|
|  | 4451 | int         i = 0; | 
|---|
|  | 4452 | #endif | 
|---|
|  | 4453 |  | 
|---|
|  | 4454 | SL_ENTER(_("sh_unix_mlock")); | 
|---|
|  | 4455 |  | 
|---|
| [134] | 4456 | /* There's no cancellation point here, except if tracing is on | 
|---|
|  | 4457 | */ | 
|---|
|  | 4458 | SH_MUTEX_LOCK_UNSAFE(mutex_mlock); | 
|---|
|  | 4459 |  | 
|---|
| [1] | 4460 | if (0 != page_locking) | 
|---|
|  | 4461 | { | 
|---|
| [143] | 4462 | status = -1; | 
|---|
|  | 4463 | goto exit_mlock; | 
|---|
| [1] | 4464 | } | 
|---|
| [134] | 4465 |  | 
|---|
| [1] | 4466 | page_locking = 1; | 
|---|
|  | 4467 |  | 
|---|
|  | 4468 | pagesize = sh_unix_pagesize(); | 
|---|
|  | 4469 | addr = sh_unix_lookup_page (in_addr, len, &num_pages); | 
|---|
|  | 4470 |  | 
|---|
|  | 4471 | #ifdef TEST_MLOCK | 
|---|
|  | 4472 | fprintf(stderr, "mlock: addr %ld, base %ld, pages: %d, length %d\n", | 
|---|
|  | 4473 | (unsigned long) in_addr, addr, num_pages, len); | 
|---|
|  | 4474 | #endif | 
|---|
|  | 4475 |  | 
|---|
|  | 4476 | /* increase refcount of locked pages | 
|---|
|  | 4477 | * addr is first page; num_pages is #(consecutive pages) to lock | 
|---|
|  | 4478 | */ | 
|---|
| [134] | 4479 |  | 
|---|
| [1] | 4480 | while ((page_list != NULL) && (num_pages > 0)) | 
|---|
|  | 4481 | { | 
|---|
|  | 4482 | #ifdef TEST_MLOCK | 
|---|
|  | 4483 | fprintf(stderr, "mlock: check page %d: %ld [%d]\n", | 
|---|
|  | 4484 | i, page_list->page_start, page_list->page_refcount); | 
|---|
|  | 4485 | #endif | 
|---|
|  | 4486 | if (page_list->page_start == addr) | 
|---|
|  | 4487 | { | 
|---|
|  | 4488 | page_list->page_refcount += 1; | 
|---|
|  | 4489 | num_pages -= 1; | 
|---|
|  | 4490 | addr += pagesize; | 
|---|
|  | 4491 | #ifdef TEST_MLOCK | 
|---|
|  | 4492 | fprintf(stderr, "mlock: found page %d: %ld [%d], next page %ld\n", | 
|---|
|  | 4493 | i, page_list->page_start, page_list->page_refcount, addr); | 
|---|
|  | 4494 | #endif | 
|---|
|  | 4495 | } | 
|---|
|  | 4496 | #ifdef TEST_MLOCK | 
|---|
|  | 4497 | ++i; | 
|---|
|  | 4498 | #endif | 
|---|
|  | 4499 | page_list = page_list->next; | 
|---|
|  | 4500 | } | 
|---|
|  | 4501 |  | 
|---|
|  | 4502 | /* mlock some more pages, if needed | 
|---|
|  | 4503 | */ | 
|---|
|  | 4504 | while (num_pages > 0) | 
|---|
|  | 4505 | { | 
|---|
|  | 4506 | #ifdef TEST_MLOCK | 
|---|
|  | 4507 | fprintf(stderr, "mlock: lock  page %d: mlock %ld [num_pages %d]\n", | 
|---|
|  | 4508 | i, addr, num_pages); | 
|---|
|  | 4509 | ++i; | 
|---|
|  | 4510 | #endif | 
|---|
|  | 4511 | page_list = SH_ALLOC(sizeof(sh_page_l)); | 
|---|
|  | 4512 | page_list->page_start = addr; | 
|---|
|  | 4513 | page_list->page_refcount = 1; | 
|---|
| [19] | 4514 | sl_strlcpy(page_list->file, file, 64); | 
|---|
|  | 4515 | page_list->line = line; | 
|---|
| [1] | 4516 | status = mlock( (void *) addr, pagesize); | 
|---|
|  | 4517 | if (status != 0) | 
|---|
|  | 4518 | { | 
|---|
|  | 4519 | #ifdef TEST_MLOCK | 
|---|
| [132] | 4520 | char errbuf[SH_ERRBUF_SIZE]; | 
|---|
|  | 4521 | fprintf(stderr, "mlock: error: %s\n", | 
|---|
|  | 4522 | sh_error_message(errno, errbuf, sizeof(errbuf))); | 
|---|
| [1] | 4523 | #endif | 
|---|
|  | 4524 | SH_FREE(page_list); | 
|---|
|  | 4525 | page_locking = 0; | 
|---|
| [143] | 4526 | goto exit_mlock; | 
|---|
| [1] | 4527 | } | 
|---|
|  | 4528 | page_list->next = sh_page_locked; | 
|---|
|  | 4529 | sh_page_locked  = page_list; | 
|---|
|  | 4530 | num_pages -= 1; | 
|---|
|  | 4531 | addr += pagesize; | 
|---|
|  | 4532 | } | 
|---|
| [134] | 4533 | page_locking = 0; | 
|---|
| [143] | 4534 |  | 
|---|
|  | 4535 | exit_mlock: | 
|---|
| [134] | 4536 | SH_MUTEX_UNLOCK_UNSAFE(mutex_mlock); | 
|---|
| [1] | 4537 |  | 
|---|
|  | 4538 | SL_RETURN((status), _("sh_unix_mlock")); | 
|---|
|  | 4539 | } | 
|---|
|  | 4540 | #else | 
|---|
| [175] | 4541 | int sh_unix_mlock (const char * file, int line, void * in_addr, size_t len) | 
|---|
| [1] | 4542 | { | 
|---|
| [49] | 4543 | (void) file;    (void) line; | 
|---|
| [1] | 4544 | (void) in_addr; (void) len; | 
|---|
|  | 4545 | return -1; | 
|---|
|  | 4546 | } | 
|---|
|  | 4547 | #endif | 
|---|
|  | 4548 |  | 
|---|
|  | 4549 | #if defined(HAVE_MLOCK) && !defined(HAVE_BROKEN_MLOCK) | 
|---|
|  | 4550 | int sh_unix_munlock (void * in_addr, size_t len) | 
|---|
|  | 4551 | { | 
|---|
|  | 4552 | int         num_pages; | 
|---|
|  | 4553 | int         unlocked = 0; | 
|---|
|  | 4554 | int         status   = 0; | 
|---|
|  | 4555 | int         pagesize; | 
|---|
|  | 4556 | sh_page_l * page_list = sh_page_locked; | 
|---|
|  | 4557 | sh_page_l * page_last; | 
|---|
|  | 4558 | unsigned long addr; | 
|---|
|  | 4559 |  | 
|---|
|  | 4560 | int           test_count; | 
|---|
|  | 4561 | int           test_status; | 
|---|
|  | 4562 | int           test_pages; | 
|---|
|  | 4563 |  | 
|---|
|  | 4564 | #ifdef TEST_MLOCK | 
|---|
|  | 4565 | int         i = 0; | 
|---|
|  | 4566 | #endif | 
|---|
|  | 4567 |  | 
|---|
|  | 4568 | SL_ENTER(_("sh_unix_munlock")); | 
|---|
|  | 4569 |  | 
|---|
| [134] | 4570 | /* There's no cancellation point here, except if tracing is on | 
|---|
|  | 4571 | */ | 
|---|
|  | 4572 | SH_MUTEX_LOCK_UNSAFE(mutex_mlock); | 
|---|
|  | 4573 |  | 
|---|
| [1] | 4574 | if (0 != page_locking) | 
|---|
|  | 4575 | { | 
|---|
| [143] | 4576 | status = -1; | 
|---|
|  | 4577 | goto exit_munlock; | 
|---|
| [1] | 4578 | } | 
|---|
|  | 4579 | page_locking = 1; | 
|---|
|  | 4580 |  | 
|---|
|  | 4581 | pagesize = sh_unix_pagesize(); | 
|---|
|  | 4582 | addr     = sh_unix_lookup_page (in_addr, len, &num_pages); | 
|---|
|  | 4583 |  | 
|---|
|  | 4584 | #ifdef TEST_MLOCK | 
|---|
|  | 4585 | fprintf(stderr, "munlock: in_addr %ld, addr %ld, pages: %d, length %d\n", | 
|---|
|  | 4586 | (unsigned long) in_addr, addr, num_pages, len); | 
|---|
|  | 4587 | #endif | 
|---|
|  | 4588 |  | 
|---|
|  | 4589 | test_pages = num_pages; | 
|---|
|  | 4590 |  | 
|---|
|  | 4591 | /* reduce refcount of locked pages | 
|---|
|  | 4592 | * addr is first page; num_pages is #(consecutive pages) to lock | 
|---|
|  | 4593 | */ | 
|---|
|  | 4594 | while ((page_list != NULL) && (num_pages > 0)) | 
|---|
|  | 4595 | { | 
|---|
|  | 4596 | #ifdef TEST_MLOCK | 
|---|
|  | 4597 | fprintf(stderr, "munlock: page %d: %ld [%d]\n", | 
|---|
|  | 4598 | i, page_list->page_start, page_list->page_refcount); | 
|---|
|  | 4599 | #endif | 
|---|
|  | 4600 |  | 
|---|
|  | 4601 | test_status = 0; | 
|---|
|  | 4602 | for (test_count = 0; test_count < test_pages; ++test_count) | 
|---|
|  | 4603 | { | 
|---|
|  | 4604 | if (page_list->page_start == (addr + (test_count * pagesize))) | 
|---|
|  | 4605 | { | 
|---|
|  | 4606 | test_status = 1; | 
|---|
|  | 4607 | break; | 
|---|
|  | 4608 | } | 
|---|
|  | 4609 | } | 
|---|
|  | 4610 |  | 
|---|
|  | 4611 | if (test_status == 1) | 
|---|
|  | 4612 | { | 
|---|
|  | 4613 | page_list->page_refcount -= 1; | 
|---|
|  | 4614 | if (page_list->page_refcount == 0) | 
|---|
|  | 4615 | { | 
|---|
|  | 4616 | status = munlock ( (void *) addr, pagesize); | 
|---|
|  | 4617 | ++unlocked; | 
|---|
|  | 4618 | } | 
|---|
|  | 4619 | num_pages -= 1; | 
|---|
|  | 4620 | #ifdef TEST_MLOCK | 
|---|
|  | 4621 | fprintf(stderr, | 
|---|
|  | 4622 | "munlock: page %d: %ld [refcount %d], refcount reduced\n", | 
|---|
|  | 4623 | i, page_list->page_start, page_list->page_refcount); | 
|---|
|  | 4624 | #endif | 
|---|
|  | 4625 | } | 
|---|
|  | 4626 | #ifdef TEST_MLOCK | 
|---|
|  | 4627 | ++i; | 
|---|
|  | 4628 | #endif | 
|---|
|  | 4629 | page_list = page_list->next; | 
|---|
|  | 4630 | } | 
|---|
|  | 4631 |  | 
|---|
|  | 4632 | #ifdef TEST_MLOCK | 
|---|
|  | 4633 | i = 0; | 
|---|
|  | 4634 | #endif | 
|---|
|  | 4635 |  | 
|---|
|  | 4636 | if (unlocked > 0) | 
|---|
|  | 4637 | { | 
|---|
|  | 4638 | page_list = sh_page_locked; | 
|---|
|  | 4639 | page_last = sh_page_locked; | 
|---|
|  | 4640 |  | 
|---|
|  | 4641 | while ((page_list != NULL) && (unlocked > 0)) | 
|---|
|  | 4642 | { | 
|---|
|  | 4643 | if (page_list->page_refcount == 0) | 
|---|
|  | 4644 | { | 
|---|
|  | 4645 | #ifdef TEST_MLOCK | 
|---|
|  | 4646 | fprintf(stderr, "munlock: remove page %d: %ld [refcount %d]\n", | 
|---|
|  | 4647 | i, page_list->page_start, page_list->page_refcount); | 
|---|
|  | 4648 | #endif | 
|---|
|  | 4649 | if (page_last != page_list) | 
|---|
|  | 4650 | { | 
|---|
|  | 4651 | page_last->next = page_list->next; | 
|---|
|  | 4652 | SH_FREE(page_list); | 
|---|
|  | 4653 | page_list = page_last->next; | 
|---|
|  | 4654 | } | 
|---|
|  | 4655 | else | 
|---|
|  | 4656 | { | 
|---|
|  | 4657 | page_last = page_list->next; | 
|---|
|  | 4658 | if (page_list == sh_page_locked) | 
|---|
|  | 4659 | sh_page_locked = page_list->next; | 
|---|
|  | 4660 | SH_FREE(page_list); | 
|---|
|  | 4661 | page_list = page_last; | 
|---|
|  | 4662 | } | 
|---|
|  | 4663 | --unlocked; | 
|---|
|  | 4664 | } | 
|---|
|  | 4665 | else | 
|---|
|  | 4666 | { | 
|---|
|  | 4667 | #ifdef TEST_MLOCK | 
|---|
|  | 4668 | fprintf(stderr, "munlock: skip   page %d: %ld [refcount %d]\n", | 
|---|
|  | 4669 | i, page_list->page_start, page_list->page_refcount); | 
|---|
|  | 4670 | #endif | 
|---|
|  | 4671 |  | 
|---|
|  | 4672 | page_last = page_list; | 
|---|
|  | 4673 | page_list = page_list->next; | 
|---|
|  | 4674 | } | 
|---|
|  | 4675 | #ifdef TEST_MLOCK | 
|---|
|  | 4676 | ++i; | 
|---|
|  | 4677 | #endif | 
|---|
|  | 4678 | } | 
|---|
|  | 4679 | } | 
|---|
|  | 4680 |  | 
|---|
|  | 4681 | page_locking = 0; | 
|---|
| [143] | 4682 |  | 
|---|
|  | 4683 | exit_munlock: | 
|---|
| [134] | 4684 | SH_MUTEX_UNLOCK_UNSAFE(mutex_mlock); | 
|---|
| [1] | 4685 | SL_RETURN((status), _("sh_unix_munlock")); | 
|---|
|  | 4686 | } | 
|---|
|  | 4687 | #else | 
|---|
|  | 4688 | int sh_unix_munlock (void * in_addr, size_t len) | 
|---|
|  | 4689 | { | 
|---|
|  | 4690 | (void) in_addr; (void) len; | 
|---|
|  | 4691 | return -1; | 
|---|
|  | 4692 | } | 
|---|
|  | 4693 | #endif | 
|---|
|  | 4694 |  | 
|---|
|  | 4695 | int sh_unix_count_mlock() | 
|---|
|  | 4696 | { | 
|---|
|  | 4697 | int i = 0; | 
|---|
|  | 4698 | char str[128]; | 
|---|
|  | 4699 | sh_page_l * page_list = sh_page_locked; | 
|---|
|  | 4700 |  | 
|---|
|  | 4701 | SL_ENTER(_("sh_unix_count_mlock")); | 
|---|
|  | 4702 | while (page_list != NULL) | 
|---|
|  | 4703 | { | 
|---|
| [19] | 4704 | #ifdef WITH_TPT | 
|---|
| [25] | 4705 | sl_snprintf(str, sizeof(str), _("file: %s line: %d page: %d"), | 
|---|
| [19] | 4706 | page_list->file, page_list->line, i+1); | 
|---|
|  | 4707 | sh_error_handle(SH_ERR_INFO, FIL__, __LINE__, i, MSG_E_SUBGEN, | 
|---|
|  | 4708 | str, _("sh_unix_count_mlock")); | 
|---|
|  | 4709 | #endif | 
|---|
| [1] | 4710 | page_list = page_list->next; | 
|---|
|  | 4711 | ++i; | 
|---|
|  | 4712 | } | 
|---|
| [25] | 4713 | sl_snprintf(str, sizeof(str), _("%d pages locked"), i); | 
|---|
| [1] | 4714 | sh_error_handle(SH_ERR_INFO, FIL__, __LINE__, i, MSG_E_SUBGEN, | 
|---|
|  | 4715 | str, _("sh_unix_count_mlock")); | 
|---|
|  | 4716 | SL_RETURN((i), _("sh_unix_count_mlock")); | 
|---|
|  | 4717 | } | 
|---|
|  | 4718 |  | 
|---|
|  | 4719 | /************************************************/ | 
|---|
|  | 4720 | /************************************************/ | 
|---|
|  | 4721 | /****   Stealth Utilities                    ****/ | 
|---|
|  | 4722 | /************************************************/ | 
|---|
|  | 4723 | /************************************************/ | 
|---|
|  | 4724 | #ifdef SH_STEALTH | 
|---|
|  | 4725 |  | 
|---|
|  | 4726 | void sh_unix_xor_code (char * str, int len) | 
|---|
|  | 4727 | { | 
|---|
|  | 4728 | register int i; | 
|---|
|  | 4729 |  | 
|---|
|  | 4730 | for (i = 0; i < len; ++i) str[i] ^= (char) XOR_CODE; | 
|---|
|  | 4731 | return; | 
|---|
|  | 4732 | } | 
|---|
|  | 4733 |  | 
|---|
|  | 4734 | #if  !defined(SH_STEALTH_MICRO) | 
|---|
|  | 4735 |  | 
|---|
|  | 4736 |  | 
|---|
| [89] | 4737 | int hideout_hex_block(SL_TICKET fd, unsigned char * str, int len, | 
|---|
|  | 4738 | unsigned long * bytes_read); | 
|---|
| [1] | 4739 | unsigned long first_hex_block(SL_TICKET fd, unsigned long * max); | 
|---|
|  | 4740 |  | 
|---|
|  | 4741 | /* | 
|---|
|  | 4742 | * --- Get hidden data from a block of hex data. --- | 
|---|
|  | 4743 | */ | 
|---|
|  | 4744 | int sh_unix_getline_stealth (SL_TICKET fd, char * str, int len) | 
|---|
|  | 4745 | { | 
|---|
| [89] | 4746 | int                  add_off = 0, llen; | 
|---|
|  | 4747 | static unsigned long off_data   = 0; | 
|---|
|  | 4748 | static unsigned long max_data   = 0; | 
|---|
|  | 4749 | static unsigned long bytes_read = 0; | 
|---|
| [52] | 4750 | static int           stealth_init = BAD; | 
|---|
| [1] | 4751 |  | 
|---|
|  | 4752 | SL_ENTER(_("sh_unix_getline_stealth")); | 
|---|
|  | 4753 |  | 
|---|
| [194] | 4754 | if (str == NULL) | 
|---|
|  | 4755 | { | 
|---|
|  | 4756 | off_data   = 0; | 
|---|
|  | 4757 | max_data   = 0; | 
|---|
|  | 4758 | bytes_read = 0; | 
|---|
|  | 4759 | stealth_init = BAD; | 
|---|
|  | 4760 | SL_RETURN(0, _("sh_unix_getline_stealth")); | 
|---|
|  | 4761 | } | 
|---|
| [34] | 4762 |  | 
|---|
| [1] | 4763 | /* --- Initialize. --- | 
|---|
|  | 4764 | */ | 
|---|
|  | 4765 | if (stealth_init == BAD) | 
|---|
|  | 4766 | { | 
|---|
|  | 4767 | off_data = first_hex_block(fd, &max_data); | 
|---|
|  | 4768 | if (off_data == 0) | 
|---|
|  | 4769 | { | 
|---|
|  | 4770 | dlog(1, FIL__, __LINE__, | 
|---|
|  | 4771 | _("The stealth config file does not contain any steganographically\nhidden data. This file must be an image file in _uncompressed_\npostscript format.\nTo hide data in it, use:\n   samhain_stealth -s postscript_file orig_config_file\n   mv postscript_file /path/to/config/file\n")); | 
|---|
|  | 4772 | sh_error_handle ((-1), FIL__, __LINE__,  EIO, MSG_P_NODATA, | 
|---|
|  | 4773 | _("Stealth config file.")); | 
|---|
|  | 4774 | aud_exit (FIL__, __LINE__, EXIT_FAILURE); | 
|---|
|  | 4775 | } | 
|---|
|  | 4776 | stealth_init = GOOD; | 
|---|
| [52] | 4777 | max_data += off_data; | 
|---|
| [1] | 4778 | } | 
|---|
|  | 4779 |  | 
|---|
|  | 4780 | /* --- Seek to proper position. --- | 
|---|
|  | 4781 | */ | 
|---|
| [89] | 4782 | if (bytes_read >= max_data || add_off < 0) | 
|---|
| [52] | 4783 | { | 
|---|
|  | 4784 | dlog(1, FIL__, __LINE__, | 
|---|
|  | 4785 | _("The capacity of the container image file for the stealth config file seems to be too small. Your config file is likely truncated.\n")); | 
|---|
|  | 4786 | sh_error_handle ((-1), FIL__, __LINE__,  EIO, MSG_P_NODATA, | 
|---|
|  | 4787 | _("Stealth config file.")); | 
|---|
|  | 4788 | aud_exit (FIL__, __LINE__, EXIT_FAILURE); | 
|---|
|  | 4789 | } | 
|---|
| [1] | 4790 | sl_seek(fd, off_data); | 
|---|
|  | 4791 |  | 
|---|
|  | 4792 | /* --- Read one line. --- | 
|---|
|  | 4793 | */ | 
|---|
| [89] | 4794 | add_off   = hideout_hex_block(fd, (unsigned char *) str, len, &bytes_read); | 
|---|
| [1] | 4795 | off_data += add_off; | 
|---|
|  | 4796 |  | 
|---|
|  | 4797 | llen = sl_strlen(str); | 
|---|
|  | 4798 | SL_RETURN(llen, _("sh_unix_getline_stealth")); | 
|---|
|  | 4799 | } | 
|---|
|  | 4800 |  | 
|---|
| [89] | 4801 | int hideout_hex_block(SL_TICKET fd, unsigned char * str, int len, | 
|---|
|  | 4802 | unsigned long * bytes_read) | 
|---|
| [1] | 4803 | { | 
|---|
|  | 4804 |  | 
|---|
|  | 4805 | register int  i, j, k; | 
|---|
|  | 4806 | unsigned char c, e; | 
|---|
|  | 4807 | register int  num; | 
|---|
|  | 4808 | unsigned char mask[9] = { 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 }; | 
|---|
|  | 4809 | unsigned long here   = 0; | 
|---|
|  | 4810 | unsigned long retval = 0; | 
|---|
| [89] | 4811 | unsigned long bread  = 0; | 
|---|
| [1] | 4812 |  | 
|---|
|  | 4813 | SL_ENTER(_("hideout_hex_block")); | 
|---|
|  | 4814 |  | 
|---|
| [34] | 4815 | ASSERT_RET((len > 1), _("len > 1"), (0)); | 
|---|
|  | 4816 |  | 
|---|
|  | 4817 | --len; | 
|---|
|  | 4818 |  | 
|---|
| [1] | 4819 | i = 0; | 
|---|
|  | 4820 | while (i < len) | 
|---|
|  | 4821 | { | 
|---|
|  | 4822 | for (j = 0; j < 8; ++j) | 
|---|
|  | 4823 | { | 
|---|
|  | 4824 |  | 
|---|
|  | 4825 | /* --- Get a low byte, modify, read back. --- | 
|---|
|  | 4826 | */ | 
|---|
|  | 4827 | for (k = 0; k < 2; ++k) | 
|---|
|  | 4828 | { | 
|---|
|  | 4829 | /* -- Skip whitespace. --- | 
|---|
|  | 4830 | */ | 
|---|
|  | 4831 | c = ' '; | 
|---|
|  | 4832 | do { | 
|---|
|  | 4833 | do { | 
|---|
|  | 4834 | num = sl_read (fd, &c, 1); | 
|---|
|  | 4835 | } while (num == 0 && errno == EINTR); | 
|---|
| [89] | 4836 | if (num > 0) | 
|---|
|  | 4837 | ++here; | 
|---|
|  | 4838 | else if (num == 0) | 
|---|
| [34] | 4839 | SL_RETURN((0), _("hideout_hex_block")); | 
|---|
| [89] | 4840 | else | 
|---|
|  | 4841 | SL_RETURN((-1), _("hideout_hex_block")); | 
|---|
| [1] | 4842 | } while (c == '\n' || c == '\t' || c == '\r' || | 
|---|
|  | 4843 | c == ' '); | 
|---|
|  | 4844 | } | 
|---|
|  | 4845 |  | 
|---|
|  | 4846 |  | 
|---|
|  | 4847 | /* --- e is the value of the low byte. --- | 
|---|
|  | 4848 | */ | 
|---|
|  | 4849 | e = (unsigned char) sh_util_hexchar( c ); | 
|---|
|  | 4850 | if ((e & mask[7]) != 0)  /* bit is set     */ | 
|---|
|  | 4851 | str[i] |= mask[j]; | 
|---|
|  | 4852 | else                     /* bit is not set */ | 
|---|
|  | 4853 | str[i] &= ~mask[j]; | 
|---|
|  | 4854 |  | 
|---|
| [89] | 4855 | bread += 1; | 
|---|
| [1] | 4856 | } | 
|---|
|  | 4857 | if (str[i] == '\n') break; | 
|---|
|  | 4858 | ++i; | 
|---|
|  | 4859 | } | 
|---|
|  | 4860 |  | 
|---|
|  | 4861 | if (i != 0) | 
|---|
|  | 4862 | str[i] = '\0'; | 
|---|
|  | 4863 | else | 
|---|
| [34] | 4864 | str[i+1] = '\0'; /* keep newline and terminate */ | 
|---|
| [1] | 4865 | retval += here; | 
|---|
| [89] | 4866 | *bytes_read += (bread/8); | 
|---|
| [1] | 4867 |  | 
|---|
|  | 4868 | SL_RETURN(retval, _("hideout_hex_block")); | 
|---|
|  | 4869 | } | 
|---|
|  | 4870 |  | 
|---|
|  | 4871 | /* --- Get offset of first data block. --- | 
|---|
|  | 4872 | */ | 
|---|
|  | 4873 | unsigned long first_hex_block(SL_TICKET fd, unsigned long * max) | 
|---|
|  | 4874 | { | 
|---|
| [34] | 4875 | unsigned int  i; | 
|---|
|  | 4876 | long          num = 1; | 
|---|
|  | 4877 | unsigned long lnum; | 
|---|
| [1] | 4878 | char          c; | 
|---|
|  | 4879 | int           nothex = 0; | 
|---|
|  | 4880 | unsigned long retval = 0; | 
|---|
| [34] | 4881 | unsigned int  this_line = 0; | 
|---|
| [1] | 4882 | char          theline[SH_BUFSIZE]; | 
|---|
|  | 4883 |  | 
|---|
|  | 4884 | SL_ENTER(_("first_hex_block")); | 
|---|
|  | 4885 |  | 
|---|
|  | 4886 | *max = 0; | 
|---|
|  | 4887 |  | 
|---|
|  | 4888 | while (1) | 
|---|
|  | 4889 | { | 
|---|
|  | 4890 | theline[0] = '\0'; | 
|---|
|  | 4891 | this_line  = 0; | 
|---|
|  | 4892 | c          = '\0'; | 
|---|
| [34] | 4893 | while (c != '\n' && num > 0 && this_line < (sizeof(theline)-1)) | 
|---|
| [1] | 4894 | { | 
|---|
|  | 4895 | do { | 
|---|
|  | 4896 | num = sl_read (fd, &c, 1); | 
|---|
|  | 4897 | } while (num == 0 && errno == EINTR); | 
|---|
|  | 4898 | if (num > 0) | 
|---|
|  | 4899 | theline[this_line] = c; | 
|---|
|  | 4900 | else | 
|---|
|  | 4901 | SL_RETURN((0), _("first_hex_block")); | 
|---|
| [34] | 4902 | ++this_line; | 
|---|
| [1] | 4903 | } | 
|---|
|  | 4904 | theline[this_line] = '\0'; | 
|---|
|  | 4905 |  | 
|---|
|  | 4906 | /* not only 'newline' */ | 
|---|
|  | 4907 | if (this_line > 60) | 
|---|
|  | 4908 | { | 
|---|
|  | 4909 | nothex  = 0; | 
|---|
|  | 4910 | i       = 0; | 
|---|
|  | 4911 | while (nothex == 0 && i < (this_line-1)) | 
|---|
|  | 4912 | { | 
|---|
|  | 4913 | if (! isxdigit((int)theline[i])) nothex = 1; | 
|---|
|  | 4914 | ++i; | 
|---|
|  | 4915 | } | 
|---|
|  | 4916 | if (nothex == 1) retval += this_line; | 
|---|
|  | 4917 | } | 
|---|
|  | 4918 | else | 
|---|
|  | 4919 | { | 
|---|
|  | 4920 | nothex = 1; | 
|---|
|  | 4921 | retval += this_line; | 
|---|
|  | 4922 | } | 
|---|
|  | 4923 |  | 
|---|
|  | 4924 | if (nothex == 0) | 
|---|
|  | 4925 | { | 
|---|
|  | 4926 | *max = 0; | 
|---|
|  | 4927 | do { | 
|---|
|  | 4928 | do { | 
|---|
|  | 4929 | num = sl_read (fd, theline, SH_BUFSIZE); | 
|---|
|  | 4930 | } while (num == 0 && errno == EINTR); | 
|---|
| [34] | 4931 | if (num > 0) | 
|---|
|  | 4932 | { | 
|---|
|  | 4933 | lnum = (unsigned long) num; | 
|---|
|  | 4934 | for (i = 0; i < lnum; ++i) | 
|---|
|  | 4935 | { | 
|---|
|  | 4936 | c = theline[i]; | 
|---|
|  | 4937 | if (c == '\n' || c == '\t' || c == '\r' || c == ' ') | 
|---|
|  | 4938 | ; | 
|---|
|  | 4939 | else if (!isxdigit((int)c)) | 
|---|
|  | 4940 | break; | 
|---|
|  | 4941 | else | 
|---|
|  | 4942 | *max += 1; | 
|---|
|  | 4943 | } | 
|---|
| [1] | 4944 | } | 
|---|
|  | 4945 | } while (num > 0); | 
|---|
|  | 4946 |  | 
|---|
|  | 4947 | *max /= 16; | 
|---|
|  | 4948 | SL_RETURN((retval), _("first_hex_block")); | 
|---|
|  | 4949 | } | 
|---|
|  | 4950 |  | 
|---|
|  | 4951 | } | 
|---|
|  | 4952 | /* SL_RETURN((0), _("first_hex_block")); *//* unreachable */ | 
|---|
|  | 4953 | } | 
|---|
|  | 4954 |  | 
|---|
|  | 4955 | /* if !defined(SH_STEALTH_MICRO) */ | 
|---|
|  | 4956 | #endif | 
|---|
|  | 4957 |  | 
|---|
|  | 4958 | /* ifdef SH_STEALTH */ | 
|---|
|  | 4959 | #endif | 
|---|
|  | 4960 |  | 
|---|
|  | 4961 | /* | 
|---|
|  | 4962 | * anti-debugger code | 
|---|
|  | 4963 | */ | 
|---|
|  | 4964 | #if defined(SCREW_IT_UP) | 
|---|
|  | 4965 | volatile int sh_not_traced = 0; | 
|---|
|  | 4966 |  | 
|---|
|  | 4967 | #ifdef HAVE_GETTIMEOFDAY | 
|---|
|  | 4968 | struct timeval  save_tv; | 
|---|
|  | 4969 | #endif | 
|---|
|  | 4970 |  | 
|---|
|  | 4971 | void sh_sigtrap_handler (int signum) | 
|---|
|  | 4972 | { | 
|---|
|  | 4973 | #ifdef HAVE_GETTIMEOFDAY | 
|---|
|  | 4974 | struct timeval  tv; | 
|---|
|  | 4975 | long   difftv; | 
|---|
|  | 4976 |  | 
|---|
|  | 4977 | gettimeofday(&tv, NULL); | 
|---|
|  | 4978 | difftv = (tv.tv_sec - save_tv.tv_sec) * 1000000 + | 
|---|
|  | 4979 | (tv.tv_usec - save_tv.tv_usec); | 
|---|
|  | 4980 | if (difftv > 500000) | 
|---|
| [205] | 4981 | raise(SIGKILL); | 
|---|
| [1] | 4982 | #endif | 
|---|
|  | 4983 | sh_not_traced += signum; | 
|---|
|  | 4984 | return; | 
|---|
|  | 4985 | } | 
|---|
|  | 4986 | #endif | 
|---|