Fix a potential local root vulnverability in kcheckpass.
Security: CAN-2005-2494
This commit is contained in:
parent
942f0a9400
commit
068cd2c16c
Notes:
svn2git
2021-03-31 03:12:20 +00:00
svn path=/head/; revision=141980
14 changed files with 1099 additions and 7 deletions
|
@ -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
|
||||
|
|
156
x11/kde4-baseapps/files/patch-post-3.4.2-kdebase-kcheckpass.diff
Normal file
156
x11/kde4-baseapps/files/patch-post-3.4.2-kdebase-kcheckpass.diff
Normal file
|
@ -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;
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
156
x11/kde4-runtime/files/patch-post-3.4.2-kdebase-kcheckpass.diff
Normal file
156
x11/kde4-runtime/files/patch-post-3.4.2-kdebase-kcheckpass.diff
Normal file
|
@ -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;
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
156
x11/kdebase3/files/patch-post-3.4.2-kdebase-kcheckpass.diff
Normal file
156
x11/kdebase3/files/patch-post-3.4.2-kdebase-kcheckpass.diff
Normal file
|
@ -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;
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
156
x11/kdebase4/files/patch-post-3.4.2-kdebase-kcheckpass.diff
Normal file
156
x11/kdebase4/files/patch-post-3.4.2-kdebase-kcheckpass.diff
Normal file
|
@ -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;
|
||||
}
|
||||
|
Loading…
Reference in a new issue