summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormillert <millert@openbsd.org>2001-12-07 05:15:58 +0000
committermillert <millert@openbsd.org>2001-12-07 05:15:58 +0000
commitf14e630af81779cd913f9c8be5feed5fcedd93b8 (patch)
tree879fbf04dbd9d0ed2eaa92cd56b9c5df01e75f16
parentethernet -> dc (Netra X1 finds its root dev correctly now) (diff)
downloadwireguard-openbsd-f14e630af81779cd913f9c8be5feed5fcedd93b8.tar.xz
wireguard-openbsd-f14e630af81779cd913f9c8be5feed5fcedd93b8.zip
Catch SIGINT, SIGQUIT and SIGTSTP but ignore during the database
update. We have to be careful and drop our lock if we are suspended and then regain the lock on resume. This is necessary because the user must not be allowed to keep a record locked for a long period of time to avoid a DoS. We must be sure to re-lock when we resume because otherwise an attacker could suspend us until a user starts to login and then resume and then race the user for login using the challenge response from the user.
-rw-r--r--libexec/login_skey/login_skey.c62
1 files changed, 57 insertions, 5 deletions
diff --git a/libexec/login_skey/login_skey.c b/libexec/login_skey/login_skey.c
index e3a1d7142bb..7645a70b702 100644
--- a/libexec/login_skey/login_skey.c
+++ b/libexec/login_skey/login_skey.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: login_skey.c,v 1.5 2001/12/06 05:37:04 millert Exp $ */
+/* $OpenBSD: login_skey.c,v 1.6 2001/12/07 05:15:58 millert Exp $ */
/*-
* Copyright (c) 1995 Berkeley Software Design, Inc. All rights reserved.
@@ -40,10 +40,12 @@
#include <sys/resource.h>
#include <ctype.h>
+#include <errno.h>
#include <fcntl.h>
#include <paths.h>
#include <pwd.h>
#include <readpassphrase.h>
+#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -55,7 +57,11 @@
#include <sha1.h>
#include <skey.h>
-void timedout __P((int));
+void quit __P((int));
+void suspend __P((int));
+
+volatile sig_atomic_t resumed;
+struct skey skey;
int
main(argc, argv)
@@ -65,7 +71,6 @@ main(argc, argv)
FILE *back = NULL;
char *class = 0;
char *username = 0;
- struct skey skey;
char skeyprompt[SKEY_MAX_CHALLENGE+17];
char passbuf[SKEY_MAX_PW_LEN+1];
int c, haskey;
@@ -73,7 +78,10 @@ main(argc, argv)
skeyprompt[0] = '\0';
- (void)signal(SIGALRM, timedout);
+ (void)signal(SIGINT, quit);
+ (void)signal(SIGQUIT, quit);
+ (void)signal(SIGALRM, quit);
+ (void)signal(SIGTSTP, suspend);
(void)setpriority(PRIO_PROCESS, 0, 0);
openlog(NULL, LOG_ODELAY, LOG_AUTH);
@@ -175,13 +183,30 @@ main(argc, argv)
/* Time out getting passphrase after 2 minutes to avoid a DoS */
if (haskey)
alarm(120);
+ resumed = 0;
readpassphrase(skeyprompt, passbuf, sizeof(passbuf), 0);
if (passbuf[0] == '\0')
readpassphrase("S/Key Password [echo on]: ",
passbuf, sizeof(passbuf), RPP_ECHO_ON);
alarm(0);
+ if (resumed) {
+ /*
+ * We were suspended by the user. Our lock is
+ * no longer valid so we must regain it so
+ * an attacker cannot do a partial guess of
+ * an S/Key response already in progress.
+ */
+ haskey = (skeylookup(&skey, username) == 0);
+ }
}
+ /*
+ * Ignore keyboard interupt/suspend during database update.
+ */
+ signal(SIGINT, SIG_IGN);
+ signal(SIGQUIT, SIG_IGN);
+ signal(SIGTSTP, SIG_IGN);
+
if (haskey && skeyverify(&skey, passbuf) == 0) {
if (mode == 0) {
if (skey.n <= 1)
@@ -199,9 +224,36 @@ main(argc, argv)
}
void
-timedout(signo)
+quit(signo)
int signo;
{
_exit(1);
}
+
+void
+suspend(signo)
+ int signo;
+{
+ sigset_t nset;
+ int save_errno = errno;
+
+ /*
+ * Unlock the skey record so we don't sleep holding the lock.
+ * Unblock SIGTSTP, set it to the default action and then
+ * resend it so we are suspended properly.
+ * When we resume, reblock SIGTSTP, reset the signal handler,
+ * set a flag and restore errno.
+ */
+ alarm(0);
+ skey_unlock(&skey);
+ (void)signal(signo, SIG_DFL);
+ (void)sigemptyset(&nset);
+ (void)sigaddset(&nset, signo);
+ (void)sigprocmask(SIG_UNBLOCK, &nset, NULL);
+ (void)kill(getpid(), signo);
+ (void)sigprocmask(SIG_BLOCK, &nset, NULL);
+ (void)signal(signo, suspend);
+ resumed = 1;
+ errno = save_errno;
+}