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 ae4d29b84..2f3dbda0c 100644
--- a/misc.c
+++ b/misc.c
@@ -57,8 +57,9 @@
57#include <netdb.h> 57#include <netdb.h>
58#ifdef HAVE_PATHS_H 58#ifdef HAVE_PATHS_H
59# include <paths.h> 59# include <paths.h>
60#include <pwd.h>
61#endif 60#endif
61#include <pwd.h>
62#include <grp.h>
62#ifdef SSH_TUN_OPENBSD 63#ifdef SSH_TUN_OPENBSD
63#include <net/if.h> 64#include <net/if.h>
64#endif 65#endif
@@ -1025,6 +1026,55 @@ percent_expand(const char *string, ...)
1025} 1026}
1026 1027
1027int 1028int
1029secure_permissions(struct stat *st, uid_t uid)
1030{
1031 if (!platform_sys_dir_uid(st->st_uid) && st->st_uid != uid)
1032 return 0;
1033 if ((st->st_mode & 002) != 0)
1034 return 0;
1035 if ((st->st_mode & 020) != 0) {
1036 /* If the file is group-writable, the group in question must
1037 * have exactly one member, namely the file's owner.
1038 * (Zero-member groups are typically used by setgid
1039 * binaries, and are unlikely to be suitable.)
1040 */
1041 struct passwd *pw;
1042 struct group *gr;
1043 int members = 0;
1044
1045 gr = getgrgid(st->st_gid);
1046 if (!gr)
1047 return 0;
1048
1049 /* Check primary group memberships. */
1050 while ((pw = getpwent()) != NULL) {
1051 if (pw->pw_gid == gr->gr_gid) {
1052 ++members;
1053 if (pw->pw_uid != uid)
1054 return 0;
1055 }
1056 }
1057 endpwent();
1058
1059 pw = getpwuid(st->st_uid);
1060 if (!pw)
1061 return 0;
1062
1063 /* Check supplementary group memberships. */
1064 if (gr->gr_mem[0]) {
1065 ++members;
1066 if (strcmp(pw->pw_name, gr->gr_mem[0]) ||
1067 gr->gr_mem[1])
1068 return 0;
1069 }
1070
1071 if (!members)
1072 return 0;
1073 }
1074 return 1;
1075}
1076
1077int
1028tun_open(int tun, int mode, char **ifname) 1078tun_open(int tun, int mode, char **ifname)
1029{ 1079{
1030#if defined(CUSTOM_SYS_TUN_OPEN) 1080#if defined(CUSTOM_SYS_TUN_OPEN)
@@ -1782,8 +1832,7 @@ safe_path(const char *name, struct stat *stp, const char *pw_dir,
1782 snprintf(err, errlen, "%s is not a regular file", buf); 1832 snprintf(err, errlen, "%s is not a regular file", buf);
1783 return -1; 1833 return -1;
1784 } 1834 }
1785 if ((!platform_sys_dir_uid(stp->st_uid) && stp->st_uid != uid) || 1835 if (!secure_permissions(stp, uid)) {
1786 (stp->st_mode & 022) != 0) {
1787 snprintf(err, errlen, "bad ownership or modes for file %s", 1836 snprintf(err, errlen, "bad ownership or modes for file %s",
1788 buf); 1837 buf);
1789 return -1; 1838 return -1;
@@ -1798,8 +1847,7 @@ safe_path(const char *name, struct stat *stp, const char *pw_dir,
1798 strlcpy(buf, cp, sizeof(buf)); 1847 strlcpy(buf, cp, sizeof(buf));
1799 1848
1800 if (stat(buf, &st) < 0 || 1849 if (stat(buf, &st) < 0 ||
1801 (!platform_sys_dir_uid(st.st_uid) && st.st_uid != uid) || 1850 !secure_permissions(&st, uid)) {
1802 (st.st_mode & 022) != 0) {
1803 snprintf(err, errlen, 1851 snprintf(err, errlen,
1804 "bad ownership or modes for directory %s", buf); 1852 "bad ownership or modes for directory %s", buf);
1805 return -1; 1853 return -1;