diff options
Diffstat (limited to 'misc.c')
-rw-r--r-- | misc.c | 58 |
1 files changed, 53 insertions, 5 deletions
@@ -61,8 +61,9 @@ | |||
61 | #include <netdb.h> | 61 | #include <netdb.h> |
62 | #ifdef HAVE_PATHS_H | 62 | #ifdef HAVE_PATHS_H |
63 | # include <paths.h> | 63 | # include <paths.h> |
64 | #include <pwd.h> | ||
65 | #endif | 64 | #endif |
65 | #include <pwd.h> | ||
66 | #include <grp.h> | ||
66 | #ifdef SSH_TUN_OPENBSD | 67 | #ifdef SSH_TUN_OPENBSD |
67 | #include <net/if.h> | 68 | #include <net/if.h> |
68 | #endif | 69 | #endif |
@@ -1125,6 +1126,55 @@ percent_expand(const char *string, ...) | |||
1125 | } | 1126 | } |
1126 | 1127 | ||
1127 | int | 1128 | int |
1129 | secure_permissions(struct stat *st, uid_t uid) | ||
1130 | { | ||
1131 | if (!platform_sys_dir_uid(st->st_uid) && st->st_uid != uid) | ||
1132 | return 0; | ||
1133 | if ((st->st_mode & 002) != 0) | ||
1134 | return 0; | ||
1135 | if ((st->st_mode & 020) != 0) { | ||
1136 | /* If the file is group-writable, the group in question must | ||
1137 | * have exactly one member, namely the file's owner. | ||
1138 | * (Zero-member groups are typically used by setgid | ||
1139 | * binaries, and are unlikely to be suitable.) | ||
1140 | */ | ||
1141 | struct passwd *pw; | ||
1142 | struct group *gr; | ||
1143 | int members = 0; | ||
1144 | |||
1145 | gr = getgrgid(st->st_gid); | ||
1146 | if (!gr) | ||
1147 | return 0; | ||
1148 | |||
1149 | /* Check primary group memberships. */ | ||
1150 | while ((pw = getpwent()) != NULL) { | ||
1151 | if (pw->pw_gid == gr->gr_gid) { | ||
1152 | ++members; | ||
1153 | if (pw->pw_uid != uid) | ||
1154 | return 0; | ||
1155 | } | ||
1156 | } | ||
1157 | endpwent(); | ||
1158 | |||
1159 | pw = getpwuid(st->st_uid); | ||
1160 | if (!pw) | ||
1161 | return 0; | ||
1162 | |||
1163 | /* Check supplementary group memberships. */ | ||
1164 | if (gr->gr_mem[0]) { | ||
1165 | ++members; | ||
1166 | if (strcmp(pw->pw_name, gr->gr_mem[0]) || | ||
1167 | gr->gr_mem[1]) | ||
1168 | return 0; | ||
1169 | } | ||
1170 | |||
1171 | if (!members) | ||
1172 | return 0; | ||
1173 | } | ||
1174 | return 1; | ||
1175 | } | ||
1176 | |||
1177 | int | ||
1128 | tun_open(int tun, int mode, char **ifname) | 1178 | tun_open(int tun, int mode, char **ifname) |
1129 | { | 1179 | { |
1130 | #if defined(CUSTOM_SYS_TUN_OPEN) | 1180 | #if defined(CUSTOM_SYS_TUN_OPEN) |
@@ -1909,8 +1959,7 @@ safe_path(const char *name, struct stat *stp, const char *pw_dir, | |||
1909 | snprintf(err, errlen, "%s is not a regular file", buf); | 1959 | snprintf(err, errlen, "%s is not a regular file", buf); |
1910 | return -1; | 1960 | return -1; |
1911 | } | 1961 | } |
1912 | if ((!platform_sys_dir_uid(stp->st_uid) && stp->st_uid != uid) || | 1962 | if (!secure_permissions(stp, uid)) { |
1913 | (stp->st_mode & 022) != 0) { | ||
1914 | snprintf(err, errlen, "bad ownership or modes for file %s", | 1963 | snprintf(err, errlen, "bad ownership or modes for file %s", |
1915 | buf); | 1964 | buf); |
1916 | return -1; | 1965 | return -1; |
@@ -1925,8 +1974,7 @@ safe_path(const char *name, struct stat *stp, const char *pw_dir, | |||
1925 | strlcpy(buf, cp, sizeof(buf)); | 1974 | strlcpy(buf, cp, sizeof(buf)); |
1926 | 1975 | ||
1927 | if (stat(buf, &st) == -1 || | 1976 | if (stat(buf, &st) == -1 || |
1928 | (!platform_sys_dir_uid(st.st_uid) && st.st_uid != uid) || | 1977 | !secure_permissions(&st, uid)) { |
1929 | (st.st_mode & 022) != 0) { | ||
1930 | snprintf(err, errlen, | 1978 | snprintf(err, errlen, |
1931 | "bad ownership or modes for directory %s", buf); | 1979 | "bad ownership or modes for directory %s", buf); |
1932 | return -1; | 1980 | return -1; |