The attached patch should solve the following problem: ssh-agent creates a temporary directory under /tmp with '600' permissions. The actual socket file is created in that dir using the default umask. That's no problem in U*X systems since nobody but the owner of the directory can read the socket file. Unfortunately, Windows has a user privilege called "Bypass traverse checking", granted to everybody by default(!), which allows reading a file even if the user has not the appropriate rights on the parent directory. Sigh. The following patch solves that problem by modifying the umask prior to calling `bind' and resetting it afterwards. Thanks to Egor Duda <deo at logos-m.ru> for that patch. Corinna Index: ssh-agent.c ==================================================================RCS file: /cvs/openssh_cvs/ssh-agent.c,v retrieving revision 1.54 diff -u -p -r1.54 ssh-agent.c --- ssh-agent.c 2001/04/04 01:53:21 1.54 +++ ssh-agent.c 2001/05/03 12:19:50 @@ -714,6 +714,9 @@ main(int ac, char **av) #ifdef HAVE_SETRLIMIT struct rlimit rlim; #endif +#ifdef HAVE_CYGWIN + int prev_mask; +#endif pid_t pid; char *shell, *format, *pidstr, pidstrbuf[1 + 3 * sizeof pid]; extern int optind; @@ -805,10 +808,19 @@ main(int ac, char **av) memset(&sunaddr, 0, sizeof(sunaddr)); sunaddr.sun_family = AF_UNIX; strlcpy(sunaddr.sun_path, socket_name, sizeof(sunaddr.sun_path)); +#ifdef HAVE_CYGWIN + prev_mask = umask(0177); +#endif if (bind(sock, (struct sockaddr *) & sunaddr, sizeof(sunaddr)) < 0) { perror("bind"); +#ifdef HAVE_CYGWIN + umask(prev_mask); +#endif cleanup_exit(1); } +#ifdef HAVE_CYGWIN + umask(prev_mask); +#endif if (listen(sock, 5) < 0) { perror("listen"); cleanup_exit(1); -- Corinna Vinschen Cygwin Developer Red Hat, Inc. mailto:vinschen at redhat.com
mouring at etoh.eviladmin.org
2001-May-03 22:48 UTC
[PATCH]: Workaround a security leak on Windows
Applied, I assume that you wanted Egor Duda to have the credit. - Ben On Thu, 3 May 2001, Corinna Vinschen wrote:> The attached patch should solve the following problem: > > ssh-agent creates a temporary directory under /tmp with '600' > permissions. The actual socket file is created in that dir using > the default umask. That's no problem in U*X systems since nobody > but the owner of the directory can read the socket file. > > Unfortunately, Windows has a user privilege called "Bypass traverse > checking", granted to everybody by default(!), which allows reading > a file even if the user has not the appropriate rights on the parent > directory. Sigh. > > The following patch solves that problem by modifying the umask > prior to calling `bind' and resetting it afterwards. > > Thanks to Egor Duda <deo at logos-m.ru> for that patch. > > Corinna > > Index: ssh-agent.c > ==================================================================> RCS file: /cvs/openssh_cvs/ssh-agent.c,v > retrieving revision 1.54 > diff -u -p -r1.54 ssh-agent.c > --- ssh-agent.c 2001/04/04 01:53:21 1.54 > +++ ssh-agent.c 2001/05/03 12:19:50 > @@ -714,6 +714,9 @@ main(int ac, char **av) > #ifdef HAVE_SETRLIMIT > struct rlimit rlim; > #endif > +#ifdef HAVE_CYGWIN > + int prev_mask; > +#endif > pid_t pid; > char *shell, *format, *pidstr, pidstrbuf[1 + 3 * sizeof pid]; > extern int optind; > @@ -805,10 +808,19 @@ main(int ac, char **av) > memset(&sunaddr, 0, sizeof(sunaddr)); > sunaddr.sun_family = AF_UNIX; > strlcpy(sunaddr.sun_path, socket_name, sizeof(sunaddr.sun_path)); > +#ifdef HAVE_CYGWIN > + prev_mask = umask(0177); > +#endif > if (bind(sock, (struct sockaddr *) & sunaddr, sizeof(sunaddr)) < 0) { > perror("bind"); > +#ifdef HAVE_CYGWIN > + umask(prev_mask); > +#endif > cleanup_exit(1); > } > +#ifdef HAVE_CYGWIN > + umask(prev_mask); > +#endif > if (listen(sock, 5) < 0) { > perror("listen"); > cleanup_exit(1); > > -- > Corinna Vinschen > Cygwin Developer > Red Hat, Inc. > mailto:vinschen at redhat.com >