diff options
author | Michael Nottebrock <lofi@FreeBSD.org> | 2005-09-05 11:26:40 +0000 |
---|---|---|
committer | Michael Nottebrock <lofi@FreeBSD.org> | 2005-09-05 11:26:40 +0000 |
commit | 068cd2c16c400677ecf5893527613799881d8693 (patch) | |
tree | 4b05bf67bbbeab30b785afb437354da1839fa979 /x11/kde4-workspace | |
parent | 942f0a940037d6f55f524fa8e589ceff6badb0cd (diff) | |
download | ports-068cd2c16c400677ecf5893527613799881d8693.tar.gz ports-068cd2c16c400677ecf5893527613799881d8693.zip |
Fix a potential local root vulnverability in kcheckpass.
Security: CAN-2005-2494
Notes
Notes:
svn path=/head/; revision=141980
Diffstat (limited to 'x11/kde4-workspace')
-rw-r--r-- | x11/kde4-workspace/Makefile | 2 | ||||
-rw-r--r-- | x11/kde4-workspace/files/patch-post-3.4.2-kdebase-kcheckpass.diff | 156 |
2 files changed, 157 insertions, 1 deletions
diff --git a/x11/kde4-workspace/Makefile b/x11/kde4-workspace/Makefile index 9a9acf96aa95..b37100b46249 100644 --- a/x11/kde4-workspace/Makefile +++ b/x11/kde4-workspace/Makefile @@ -8,7 +8,7 @@ PORTNAME= kdebase PORTVERSION= ${KDE_VERSION} -PORTREVISION= 1 +PORTREVISION= 2 CATEGORIES= x11 kde MASTER_SITES= ${MASTER_SITE_KDE} MASTER_SITE_SUBDIR= stable/${PORTVERSION:S/.0//}/src diff --git a/x11/kde4-workspace/files/patch-post-3.4.2-kdebase-kcheckpass.diff b/x11/kde4-workspace/files/patch-post-3.4.2-kdebase-kcheckpass.diff new file mode 100644 index 000000000000..884f3e686ca8 --- /dev/null +++ b/x11/kde4-workspace/files/patch-post-3.4.2-kdebase-kcheckpass.diff @@ -0,0 +1,156 @@ +Index: kcheckpass.c +=================================================================== +--- kcheckpass/kcheckpass.c (revision 453871) ++++ kcheckpass/kcheckpass.c (working copy) +@@ -14,7 +14,7 @@ + * + * You should have received a copy of the GNU General Public + * License along with this program; if not, write to the Free +- * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ++ * Software Foundation, Inc., 51 Franklin Steet, Fifth Floor, Boston, MA 02110-1301, USA. + * + * + * kcheckpass is a simple password checker. Just invoke and +@@ -264,8 +264,13 @@ + + va_start(ap, fmt); + vfprintf(stderr, fmt, ap); ++ va_end(ap); + } + ++#ifndef O_NOFOLLOW ++# define O_NOFOLLOW 0 ++#endif ++ + static void ATTR_NORETURN + usage(int exitval) + { +@@ -286,6 +291,14 @@ + exit(exitval); + } + ++static int exclusive_lock(int fd) ++{ ++ struct flock lk; ++ lk.l_type = F_WRLCK; ++ lk.l_whence = SEEK_SET; ++ lk.l_start = lk.l_len = 0; ++ return fcntl(fd, F_SETLKW, &lk); ++} + + int + main(int argc, char **argv) +@@ -299,10 +312,13 @@ + char *p; + #endif + struct passwd *pw; +- int c, nfd, lfd, numtries; ++ int c, nfd, tfd, lfd; + uid_t uid; +- long lasttime; ++ time_t lasttime; + AuthReturn ret; ++ char tmpname[64], fname[64], fcont[64]; ++ time_t left = 3; ++ lfd = tfd = 0; + + #ifdef HAVE_OSF_C2_PASSWD + initialize_osf_security(argc, argv); +@@ -371,6 +387,41 @@ + return AuthError; + } + } ++ ++ /* see if we had already a failed attempt */ ++ if ( uid != geteuid() ) { ++ strcpy(tmpname, "/var/spool/lock/kcheckpass.tmp.XXXXXX"); ++ if ((tfd=mkstemp(tmpname)) < 0) ++ return AuthError; ++ ++ /* try locking out concurrent kcheckpass processes */ ++ exclusive_lock(tfd); ++ ++ write(tfd, fcont, sprintf(fcont, "%lu\n", time(0)+left)); ++ (void) lseek(tfd, 0, SEEK_SET); ++ ++ sprintf(fname, "/var/spool/lock/kcheckpass.%d", uid ); ++ ++ if ((lfd = open(fname, O_RDWR | O_NOFOLLOW)) >= 0) { ++ if (exclusive_lock(lfd) == 0) { ++ if ((c = read(lfd, fcont, sizeof(fcont)-1)) > 0 && ++ (fcont[c] = '\0', sscanf(fcont, "%ld", &lasttime) == 1)) ++ { ++ time_t ct = time(0); ++ ++ /* in case we were killed early, sleep the remaining time ++ * to properly enforce invocation throttling and make sure ++ * that users can't use kcheckpass for bruteforcing password ++ */ ++ if(lasttime > ct && lasttime < ct + left) ++ sleep (lasttime - ct); ++ } ++ } ++ close(lfd); ++ } ++ rename(tmpname, fname); ++ } ++ + /* Now do the fandango */ + ret = Authenticate( + #ifdef HAVE_PAM +@@ -379,35 +430,21 @@ + method, + username, + sfd < 0 ? conv_legacy : conv_server); ++ + if (ret == AuthOk || ret == AuthBad) { + /* Security: Don't undermine the shadow system. */ + if (uid != geteuid()) { +- char fname[32], fcont[32]; +- sprintf(fname, "/var/lock/kcheckpass.%d", uid); +- if ((lfd = open(fname, O_RDWR | O_CREAT)) >= 0) { +- struct flock lk; +- lk.l_type = F_WRLCK; +- lk.l_whence = SEEK_SET; +- lk.l_start = lk.l_len = 0; +- if (fcntl(lfd, F_SETLKW, &lk)) +- return AuthError; +- if ((c = read(lfd, fcont, sizeof(fcont))) > 0 && +- (fcont[c] = 0, sscanf(fcont, "%ld %d\n", &lasttime, &numtries) == 2)) +- { +- time_t left = lasttime - time(0); +- if (numtries < 20) +- numtries++; +- left += 2 << (numtries > 10 ? numtries - 10 : 0); +- if (left > 0) +- sleep(left); +- } else +- numtries = 0; +- if (ret == AuthBad) { +- lseek(lfd, 0, SEEK_SET); +- write(lfd, fcont, sprintf(fcont, "%ld %d\n", time(0), numtries)); +- } else +- unlink(fname); +- } ++ if (ret == AuthBad) { ++ write(tfd, fcont, sprintf(fcont, "%lu\n", time(0)+left)); ++ } else ++ unlink(fname); ++ ++ unlink(tmpname); ++ ++ if (ret == AuthBad) ++ sleep(left); ++ ++ close(tfd); + } + if (ret == AuthBad) { + message("Authentication failure\n"); +@@ -417,6 +454,7 @@ + } + } + } ++ + return ret; + } + |