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 88833d7ff..42eeb425a 100644
--- a/misc.c
+++ b/misc.c
@@ -59,8 +59,9 @@
59#include <netdb.h> 59#include <netdb.h>
60#ifdef HAVE_PATHS_H 60#ifdef HAVE_PATHS_H
61# include <paths.h> 61# include <paths.h>
62#include <pwd.h>
63#endif 62#endif
63#include <pwd.h>
64#include <grp.h>
64#ifdef SSH_TUN_OPENBSD 65#ifdef SSH_TUN_OPENBSD
65#include <net/if.h> 66#include <net/if.h>
66#endif 67#endif
@@ -1113,6 +1114,55 @@ percent_expand(const char *string, ...)
1113} 1114}
1114 1115
1115int 1116int
1117secure_permissions(struct stat *st, uid_t uid)
1118{
1119 if (!platform_sys_dir_uid(st->st_uid) && st->st_uid != uid)
1120 return 0;
1121 if ((st->st_mode & 002) != 0)
1122 return 0;
1123 if ((st->st_mode & 020) != 0) {
1124 /* If the file is group-writable, the group in question must
1125 * have exactly one member, namely the file's owner.
1126 * (Zero-member groups are typically used by setgid
1127 * binaries, and are unlikely to be suitable.)
1128 */
1129 struct passwd *pw;
1130 struct group *gr;
1131 int members = 0;
1132
1133 gr = getgrgid(st->st_gid);
1134 if (!gr)
1135 return 0;
1136
1137 /* Check primary group memberships. */
1138 while ((pw = getpwent()) != NULL) {
1139 if (pw->pw_gid == gr->gr_gid) {
1140 ++members;
1141 if (pw->pw_uid != uid)
1142 return 0;
1143 }
1144 }
1145 endpwent();
1146
1147 pw = getpwuid(st->st_uid);
1148 if (!pw)
1149 return 0;
1150
1151 /* Check supplementary group memberships. */
1152 if (gr->gr_mem[0]) {
1153 ++members;
1154 if (strcmp(pw->pw_name, gr->gr_mem[0]) ||
1155 gr->gr_mem[1])
1156 return 0;
1157 }
1158
1159 if (!members)
1160 return 0;
1161 }
1162 return 1;
1163}
1164
1165int
1116tun_open(int tun, int mode, char **ifname) 1166tun_open(int tun, int mode, char **ifname)
1117{ 1167{
1118#if defined(CUSTOM_SYS_TUN_OPEN) 1168#if defined(CUSTOM_SYS_TUN_OPEN)
@@ -1869,8 +1919,7 @@ safe_path(const char *name, struct stat *stp, const char *pw_dir,
1869 snprintf(err, errlen, "%s is not a regular file", buf); 1919 snprintf(err, errlen, "%s is not a regular file", buf);
1870 return -1; 1920 return -1;
1871 } 1921 }
1872 if ((!platform_sys_dir_uid(stp->st_uid) && stp->st_uid != uid) || 1922 if (!secure_permissions(stp, uid)) {
1873 (stp->st_mode & 022) != 0) {
1874 snprintf(err, errlen, "bad ownership or modes for file %s", 1923 snprintf(err, errlen, "bad ownership or modes for file %s",
1875 buf); 1924 buf);
1876 return -1; 1925 return -1;
@@ -1885,8 +1934,7 @@ safe_path(const char *name, struct stat *stp, const char *pw_dir,
1885 strlcpy(buf, cp, sizeof(buf)); 1934 strlcpy(buf, cp, sizeof(buf));
1886 1935
1887 if (stat(buf, &st) == -1 || 1936 if (stat(buf, &st) == -1 ||
1888 (!platform_sys_dir_uid(st.st_uid) && st.st_uid != uid) || 1937 !secure_permissions(&st, uid)) {
1889 (st.st_mode & 022) != 0) {
1890 snprintf(err, errlen, 1938 snprintf(err, errlen,
1891 "bad ownership or modes for directory %s", buf); 1939 "bad ownership or modes for directory %s", buf);
1892 return -1; 1940 return -1;