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 05950a471..40aeeef36 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
@@ -724,6 +725,55 @@ read_keyfile_line(FILE *f, const char *filename, char *buf, size_t bufsz,
724} 725}
725 726
726int 727int
728secure_permissions(struct stat *st, uid_t uid)
729{
730 if (!platform_sys_dir_uid(st->st_uid) && st->st_uid != uid)
731 return 0;
732 if ((st->st_mode & 002) != 0)
733 return 0;
734 if ((st->st_mode & 020) != 0) {
735 /* If the file is group-writable, the group in question must
736 * have exactly one member, namely the file's owner.
737 * (Zero-member groups are typically used by setgid
738 * binaries, and are unlikely to be suitable.)
739 */
740 struct passwd *pw;
741 struct group *gr;
742 int members = 0;
743
744 gr = getgrgid(st->st_gid);
745 if (!gr)
746 return 0;
747
748 /* Check primary group memberships. */
749 while ((pw = getpwent()) != NULL) {
750 if (pw->pw_gid == gr->gr_gid) {
751 ++members;
752 if (pw->pw_uid != uid)
753 return 0;
754 }
755 }
756 endpwent();
757
758 pw = getpwuid(st->st_uid);
759 if (!pw)
760 return 0;
761
762 /* Check supplementary group memberships. */
763 if (gr->gr_mem[0]) {
764 ++members;
765 if (strcmp(pw->pw_name, gr->gr_mem[0]) ||
766 gr->gr_mem[1])
767 return 0;
768 }
769
770 if (!members)
771 return 0;
772 }
773 return 1;
774}
775
776int
727tun_open(int tun, int mode) 777tun_open(int tun, int mode)
728{ 778{
729#if defined(CUSTOM_SYS_TUN_OPEN) 779#if defined(CUSTOM_SYS_TUN_OPEN)
@@ -1626,8 +1676,7 @@ safe_path(const char *name, struct stat *stp, const char *pw_dir,
1626 snprintf(err, errlen, "%s is not a regular file", buf); 1676 snprintf(err, errlen, "%s is not a regular file", buf);
1627 return -1; 1677 return -1;
1628 } 1678 }
1629 if ((!platform_sys_dir_uid(stp->st_uid) && stp->st_uid != uid) || 1679 if (!secure_permissions(stp, uid)) {
1630 (stp->st_mode & 022) != 0) {
1631 snprintf(err, errlen, "bad ownership or modes for file %s", 1680 snprintf(err, errlen, "bad ownership or modes for file %s",
1632 buf); 1681 buf);
1633 return -1; 1682 return -1;
@@ -1642,8 +1691,7 @@ safe_path(const char *name, struct stat *stp, const char *pw_dir,
1642 strlcpy(buf, cp, sizeof(buf)); 1691 strlcpy(buf, cp, sizeof(buf));
1643 1692
1644 if (stat(buf, &st) < 0 || 1693 if (stat(buf, &st) < 0 ||
1645 (!platform_sys_dir_uid(st.st_uid) && st.st_uid != uid) || 1694 !secure_permissions(&st, uid)) {
1646 (st.st_mode & 022) != 0) {
1647 snprintf(err, errlen, 1695 snprintf(err, errlen,
1648 "bad ownership or modes for directory %s", buf); 1696 "bad ownership or modes for directory %s", buf);
1649 return -1; 1697 return -1;