From 5170144facb83bdd026593d75885ce6aee08c245 Mon Sep 17 00:00:00 2001 From: lukem Date: Wed, 25 Jun 1997 00:15:04 +0000 Subject: [PATCH] Apply [bin/3270] from Simon J. Gerraty , with fixes by me: * if the user has an s/key, provide a reminder in the password prompt * if '-s' is given once, force a user that has an s/key to use it * if '-s' is given more than once, only permit s/key logins --- usr.bin/login/login.1 | 19 +++++++--- usr.bin/login/login.c | 83 +++++++++++++++++++++++++++++++++++++------ 2 files changed, 87 insertions(+), 15 deletions(-) diff --git a/usr.bin/login/login.1 b/usr.bin/login/login.1 index cdda926be653..f69eed52ae74 100644 --- a/usr.bin/login/login.1 +++ b/usr.bin/login/login.1 @@ -1,4 +1,4 @@ -.\" $NetBSD: login.1,v 1.8 1997/03/08 14:17:35 mouse Exp $ +.\" $NetBSD: login.1,v 1.9 1997/06/25 00:15:04 lukem Exp $ .\" .\" Copyright (c) 1980, 1990, 1993 .\" The Regents of the University of California. All rights reserved. @@ -41,7 +41,7 @@ .Nd log into the computer .Sh SYNOPSIS .Nm login -.Op Fl fp +.Op Fl fps .Op Fl h Ar hostname .Op Ar user .Sh DESCRIPTION @@ -54,9 +54,14 @@ of the user fails, .Nm login prompts for a user name. Authentication of users is done via passwords. +If the user can be authenticated via S/Key, then the S/Key challenge is +incorporated in the password prompt. The user then has the option of +entering their normal password or the S/Key response, neither will be +echoed. Alternatively, the user can enter the password "s/key", in which case -S/Key authentication of users is performed, as descibed in -.Xr skey 1 . +S/Key authentication is performed, as described in +.Xr skey 1 , +and the response will be echoed. S/Key is a Trademark of Bellcore. .Pp The options are as follows: @@ -83,6 +88,12 @@ discards any previous environment. The .Fl p option disables this behavior. +.It Fl s +If the user can be authenticated via S/Key, then require it. +If the +.Fl s +option is given more than once, user's may only log in if they can be +authenticated via S/Key. .El .Pp If the file diff --git a/usr.bin/login/login.c b/usr.bin/login/login.c index 3ea9159bebc0..44b78c0a2ddc 100644 --- a/usr.bin/login/login.c +++ b/usr.bin/login/login.c @@ -1,4 +1,4 @@ -/* $NetBSD: login.c,v 1.19 1997/06/23 11:19:10 veego Exp $ */ +/* $NetBSD: login.c,v 1.20 1997/06/25 00:15:06 lukem Exp $ */ /*- * Copyright (c) 1980, 1987, 1988, 1991, 1993, 1994 @@ -43,7 +43,7 @@ static char copyright[] = #if 0 static char sccsid[] = "@(#)login.c 8.4 (Berkeley) 4/2/94"; #endif -static char rcsid[] = "$NetBSD: login.c,v 1.19 1997/06/23 11:19:10 veego Exp $"; +static char rcsid[] = "$NetBSD: login.c,v 1.20 1997/06/25 00:15:06 lukem Exp $"; #endif /* not lint */ /* @@ -114,6 +114,11 @@ int authok; struct passwd *pwd; int failures; char term[64], *envinit[1], *hostname, *username, *tty; +#ifdef SKEY +int used_skey = 0; +int require_skey = 0; +char skeypw[] = "s/key"; +#endif int main(argc, argv) @@ -127,10 +132,14 @@ main(argc, argv) struct utmp utmp; int ask, ch, cnt, fflag, hflag, pflag, quietlog, rootlogin, rval; uid_t uid; - char *domain, *p, *salt, *ttyn; + char *domain, *p, *salt, *ttyn, *pwprompt; char tbuf[MAXPATHLEN + 2], tname[sizeof(_PATH_TTY) + 10]; char localhost[MAXHOSTNAMELEN]; + tbuf[0] = '\0'; + rval = 0; + pwprompt = NULL; + (void)signal(SIGALRM, timedout); (void)alarm(timeout); (void)signal(SIGQUIT, SIG_IGN); @@ -144,6 +153,7 @@ main(argc, argv) * -f is used to skip a second login authentication * -h is used by other servers to pass the name of the remote * host to login so that it may be placed in utmp and wtmp + * -s is used to force use of S/Key or equivalent. */ domain = NULL; if (gethostname(localhost, sizeof(localhost)) < 0) @@ -153,7 +163,7 @@ main(argc, argv) fflag = hflag = pflag = 0; uid = getuid(); - while ((ch = getopt(argc, argv, "fh:p")) != EOF) + while ((ch = getopt(argc, argv, "fh:ps")) != EOF) switch (ch) { case 'f': fflag = 1; @@ -170,6 +180,15 @@ main(argc, argv) case 'p': pflag = 1; break; + case 's': +#ifdef SKEY + /* + * If -s given twice, use S/Key or no login + * otherwise just insist on S/Key if user has one. + */ + require_skey++; +#endif + break; case '?': default: if (!uid) @@ -201,6 +220,9 @@ main(argc, argv) tty = ttyn; for (cnt = 0;; ask = 1) { +#ifdef SKEY + used_skey = 0; +#endif #if defined(KERBEROS) || defined(KERBEROS5) kdestroy(); #endif @@ -269,7 +291,28 @@ main(argc, argv) (void)setpriority(PRIO_PROCESS, 0, -4); - p = getpass("Password:"); +#ifdef SKEY + p = NULL; + pwprompt = "Password:"; + + if (require_skey > 1) /* -s -s */ + p = skeypw; + else if (skey_haskey(username) == 0) { + if (require_skey > 0) /* -s */ + p = skeypw; + else { + extern char *skey_keyinfo(); + static char skprompt[80]; + char *skinfo = skey_keyinfo(username); + + (void)snprintf(skprompt, sizeof(skprompt)-1, + "Password [%s]:", skinfo); + pwprompt = skprompt; + } + } + if (p == NULL) +#endif + p = getpass(pwprompt); if (pwd) { #if defined(KERBEROS) || defined(KERBEROS5) @@ -287,7 +330,10 @@ main(argc, argv) rval = pwcheck(username, p, salt, pwd->pw_passwd); #endif } - memset(p, 0, strlen(p)); +#ifdef SKEY + if (used_skey == 0 && p != skeypw) +#endif + memset(p, 0, strlen(p)); (void)setpriority(PRIO_PROCESS, 0, 0); @@ -471,14 +517,29 @@ int pwcheck(user, p, salt, passwd) char *user, *p, *salt, *passwd; { + int sts = strcmp(crypt(p, salt), passwd); + #ifdef SKEY - if (strcasecmp(p, "s/key") == 0) - if (skey_haskey(user)) + if (sts) { /* wasn't passwd */ + if (skey_haskey(user)) { + if (strcasecmp(p, skeypw) == 0) { + (void) fprintf(stderr, "You have no s/key. "); return 1; - else - return skey_authenticate(user); + } + } else { + if (strcasecmp(p, skeypw) == 0) { + sts = skey_authenticate(user); + } else { + if ((sts = skey_passcheck(user, p)) != -1) { + sts = 0; /* ok */ + } + } + } + if (sts == 0) + used_skey = 1; + } #endif - return strcmp(crypt(p, salt), passwd); + return sts; } #if defined(KERBEROS) || defined(KERBEROS5)