diff --git a/appl/login/login.c b/appl/login/login.c index 68c750f77..c8ffbc5f8 100644 --- a/appl/login/login.c +++ b/appl/login/login.c @@ -48,6 +48,8 @@ RCSID("$Id$"); static char **env; static int num_env; +static int login_timeout = 60; + static void extend_env(char *str) { @@ -167,7 +169,18 @@ exec_shell(const char *shell, int fallback) err(1, "%s", shell); } -static enum { NONE = 0, AUTH_KRB4 = 1, AUTH_KRB5 = 2 } auth; +static enum { NONE = 0, AUTH_KRB4 = 1, AUTH_KRB5 = 2, AUTH_OTP = 3 } auth; + +#ifdef OTP +static OtpContext otp_ctx; + +static int +otp_verify(struct passwd *pwd, const char *password) +{ + return (otp_verify_user (&otp_ctx, password)); +} +#endif /* OTP */ + #ifdef KRB5 static krb5_context context; @@ -379,10 +392,11 @@ static int r_flag; static int version_flag; static int help_flag; static char *remote_host; +static char *auth_level = NULL; struct getargs args[] = { + { NULL, 'a', arg_string, &auth_level, "authentication mode" }, #if 0 - { NULL, 'a' }, { NULL, 'd' }, #endif { NULL, 'f', arg_flag, &f_flag, "pre-authenticated" }, @@ -592,6 +606,21 @@ do_login(const struct passwd *pwd, char *tty, char *ttyn) krb4_get_afs_tokens (pwd); #endif /* KRB4 */ + { + char **newenv; + char *p; + int i, j; + + newenv = NULL; + i = read_environment(_PATH_ETC_ENVIRONMENT, &newenv); + for (j = 0; j < i; j++) { + p = strchr(newenv[j], '='); + *p++ = 0; + add_env(newenv[j], p); + *--p = '='; + free(newenv[j]); + } + } add_env("HOME", home_dir); add_env("USER", pwd->pw_name); add_env("LOGNAME", pwd->pw_name); @@ -624,6 +653,12 @@ check_password(struct passwd *pwd, const char *password) auth = AUTH_KRB4; return 0; } +#endif +#ifdef OTP + if (otp_verify (pwd, password) == 0) { + auth = AUTH_OTP; + return 0; + } #endif return 1; } @@ -635,6 +670,17 @@ usage(int status) exit(status); } +static RETSIGTYPE +sig_handler(int sig) +{ + if (sig == SIGALRM) + fprintf(stderr, "Login timed out after %d seconds\n", + login_timeout); + else + fprintf(stderr, "Login received signal, exiting\n"); + exit(0); +} + int main(int argc, char **argv) { @@ -645,6 +691,7 @@ main(int argc, char **argv) int optind = 0; int ask = 1; + struct sigaction sa; set_progname(argv[0]); @@ -689,13 +736,30 @@ main(int argc, char **argv) ask = 0; } } + +#if defined(DCE) && defined(AIX) + setenv("AUTHSTATE", "DCE", 1); +#endif + /* XXX should we care about environment on the command line? */ + + memset(&sa, 0, sizeof(sa)); + sa.sa_handler = sig_handler; + sigemptyset(&sa.sa_mask); + sa.sa_flags = 0; + sigaction(SIGALRM, &sa, NULL); + alarm(login_timeout); + for(try = 0; try < max_tries; try++){ struct passwd *pwd; char password[128]; int ret; char ttname[32]; char *tty, *ttyn; + char prompt[128]; +#ifdef OTP + char otp_str[256]; +#endif if(ask){ f_flag = r_flag = 0; @@ -703,7 +767,7 @@ main(int argc, char **argv) if(ret == -3) exit(0); if(ret == -2) - continue; + sig_handler(0); /* exit */ } pwd = k_getpwnam(username); #ifdef ALLOW_NULL_PASSWORD @@ -712,11 +776,28 @@ main(int argc, char **argv) } else #endif - if(f_flag == 0) { - ret = read_string("Password: ", password, sizeof(password), 0); - if(ret == -3 || ret == -2) - continue; - } + + { +#ifdef OTP + if(auth_level && strcmp(auth_level, "otp") == 0 && + otp_challenge(&otp_ctx, username, + otp_str, sizeof(otp_str)) == 0) + snprintf (prompt, sizeof(prompt), "%s's %s Password: ", + username, otp_str); + else +#endif + strncpy(prompt, "Password: ", sizeof(prompt)); + + if (f_flag == 0) { + ret = read_string(prompt, password, sizeof(password), 0); + if (ret == -3) { + ask = 1; + continue; + } + if (ret == -2) + sig_handler(0); + } + } if(pwd == NULL){ fprintf(stderr, "Login incorrect.\n"); @@ -749,6 +830,7 @@ main(int argc, char **argv) pwd->pw_name, tty); exit (1); } + alarm(0); do_login(pwd, tty, ttyn); } exit(1);