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 3a31d5c18..073d3be19 100644
--- a/misc.c
+++ b/misc.c
@@ -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
1127int 1128int
1129secure_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
1177int
1128tun_open(int tun, int mode, char **ifname) 1178tun_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;