| /* vi: set sw=4 ts=4: */ |
| /* |
| * Licensed under GPLv2 or later, see file LICENSE in this source tree. |
| */ |
| #include "libbb.h" |
| #include "bb_archive.h" |
| |
| int FAST_FUNC unsafe_symlink_target(const char *target) |
| { |
| const char *dot; |
| |
| if (target[0] == '/') { |
| const char *var; |
| unsafe: |
| var = getenv("EXTRACT_UNSAFE_SYMLINKS"); |
| if (var) { |
| if (LONE_CHAR(var, '1')) |
| return 0; /* pretend it's safe */ |
| return 1; /* "UNSAFE!" */ |
| } |
| bb_error_msg("skipping unsafe symlink to '%s' in archive," |
| " set %s=1 to extract", |
| target, |
| "EXTRACT_UNSAFE_SYMLINKS" |
| ); |
| /* Prevent further messages */ |
| setenv("EXTRACT_UNSAFE_SYMLINKS", "0", 0); |
| return 1; /* "UNSAFE!" */ |
| } |
| |
| dot = target; |
| for (;;) { |
| dot = strchr(dot, '.'); |
| if (!dot) |
| return 0; /* safe target */ |
| |
| /* Is it a path component starting with ".."? */ |
| if ((dot[1] == '.') |
| && (dot == target || dot[-1] == '/') |
| /* Is it exactly ".."? */ |
| && (dot[2] == '/' || dot[2] == '\0') |
| ) { |
| goto unsafe; |
| } |
| /* NB: it can even be trailing ".", should only add 1 */ |
| dot += 1; |
| } |
| } |