summaryrefslogtreecommitdiff
path: root/misc.c
diff options
context:
space:
mode:
Diffstat (limited to 'misc.c')
-rw-r--r--misc.c58
1 files changed, 53 insertions, 5 deletions
diff --git a/misc.c b/misc.c
index 4623b5755..c75a795c2 100644
--- a/misc.c
+++ b/misc.c
@@ -55,8 +55,9 @@
55#include <netdb.h> 55#include <netdb.h>
56#ifdef HAVE_PATHS_H 56#ifdef HAVE_PATHS_H
57# include <paths.h> 57# include <paths.h>
58#include <pwd.h>
59#endif 58#endif
59#include <pwd.h>
60#include <grp.h>
60#ifdef SSH_TUN_OPENBSD 61#ifdef SSH_TUN_OPENBSD
61#include <net/if.h> 62#include <net/if.h>
62#endif 63#endif
@@ -1272,6 +1273,55 @@ percent_dollar_expand(const char *string, ...)
1272} 1273}
1273 1274
1274int 1275int
1276secure_permissions(struct stat *st, uid_t uid)
1277{
1278 if (!platform_sys_dir_uid(st->st_uid) && st->st_uid != uid)
1279 return 0;
1280 if ((st->st_mode & 002) != 0)
1281 return 0;
1282 if ((st->st_mode & 020) != 0) {
1283 /* If the file is group-writable, the group in question must
1284 * have exactly one member, namely the file's owner.
1285 * (Zero-member groups are typically used by setgid
1286 * binaries, and are unlikely to be suitable.)
1287 */
1288 struct passwd *pw;
1289 struct group *gr;
1290 int members = 0;
1291
1292 gr = getgrgid(st->st_gid);
1293 if (!gr)
1294 return 0;
1295
1296 /* Check primary group memberships. */
1297 while ((pw = getpwent()) != NULL) {
1298 if (pw->pw_gid == gr->gr_gid) {
1299 ++members;
1300 if (pw->pw_uid != uid)
1301 return 0;
1302 }
1303 }
1304 endpwent();
1305
1306 pw = getpwuid(st->st_uid);
1307 if (!pw)
1308 return 0;
1309
1310 /* Check supplementary group memberships. */
1311 if (gr->gr_mem[0]) {
1312 ++members;
1313 if (strcmp(pw->pw_name, gr->gr_mem[0]) ||
1314 gr->gr_mem[1])
1315 return 0;
1316 }
1317
1318 if (!members)
1319 return 0;
1320 }
1321 return 1;
1322}
1323
1324int
1275tun_open(int tun, int mode, char **ifname) 1325tun_open(int tun, int mode, char **ifname)
1276{ 1326{
1277#if defined(CUSTOM_SYS_TUN_OPEN) 1327#if defined(CUSTOM_SYS_TUN_OPEN)
@@ -2056,8 +2106,7 @@ safe_path(const char *name, struct stat *stp, const char *pw_dir,
2056 snprintf(err, errlen, "%s is not a regular file", buf); 2106 snprintf(err, errlen, "%s is not a regular file", buf);
2057 return -1; 2107 return -1;
2058 } 2108 }
2059 if ((!platform_sys_dir_uid(stp->st_uid) && stp->st_uid != uid) || 2109 if (!secure_permissions(stp, uid)) {
2060 (stp->st_mode & 022) != 0) {
2061 snprintf(err, errlen, "bad ownership or modes for file %s", 2110 snprintf(err, errlen, "bad ownership or modes for file %s",
2062 buf); 2111 buf);
2063 return -1; 2112 return -1;
@@ -2072,8 +2121,7 @@ safe_path(const char *name, struct stat *stp, const char *pw_dir,
2072 strlcpy(buf, cp, sizeof(buf)); 2121 strlcpy(buf, cp, sizeof(buf));
2073 2122
2074 if (stat(buf, &st) == -1 || 2123 if (stat(buf, &st) == -1 ||
2075 (!platform_sys_dir_uid(st.st_uid) && st.st_uid != uid) || 2124 !secure_permissions(&st, uid)) {
2076 (st.st_mode & 022) != 0) {
2077 snprintf(err, errlen, 2125 snprintf(err, errlen,
2078 "bad ownership or modes for directory %s", buf); 2126 "bad ownership or modes for directory %s", buf);
2079 return -1; 2127 return -1;