summaryrefslogtreecommitdiffstats
path: root/crypto/heimdal/appl/login/login.c
diff options
context:
space:
mode:
Diffstat (limited to 'crypto/heimdal/appl/login/login.c')
-rw-r--r--crypto/heimdal/appl/login/login.c269
1 files changed, 171 insertions, 98 deletions
diff --git a/crypto/heimdal/appl/login/login.c b/crypto/heimdal/appl/login/login.c
index a149449..2ada921 100644
--- a/crypto/heimdal/appl/login/login.c
+++ b/crypto/heimdal/appl/login/login.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 1998, 1999 Kungliga Tekniska Högskolan
+ * Copyright (c) 1997 - 2001 Kungliga Tekniska Högskolan
* (Royal Institute of Technology, Stockholm, Sweden).
* All rights reserved.
*
@@ -39,50 +39,9 @@
#include <sys/capability.h>
#endif
-RCSID("$Id: login.c,v 1.33 1999/12/02 17:04:55 joda Exp $");
+RCSID("$Id: login.c,v 1.46 2001/01/29 02:18:03 assar Exp $");
-/*
- * the environment we will send to execle and the shell.
- */
-
-static char **env;
-static int num_env;
-
-static void
-extend_env(char *str)
-{
- env = realloc(env, (num_env + 1) * sizeof(*env));
- if(env == NULL)
- errx(1, "Out of memory!");
- env[num_env++] = str;
-}
-
-static void
-add_env(const char *var, const char *value)
-{
- int i;
- char *str;
- asprintf(&str, "%s=%s", var, value);
- if(str == NULL)
- errx(1, "Out of memory!");
- for(i = 0; i < num_env; i++)
- if(strncmp(env[i], var, strlen(var)) == 0 &&
- env[i][strlen(var)] == '='){
- free(env[i]);
- env[i] = str;
- return;
- }
-
- extend_env(str);
-}
-
-static void
-copy_env(void)
-{
- char **p;
- for(p = environ; *p; p++)
- extend_env(*p);
-}
+static int login_timeout = 60;
static int
start_login_process(void)
@@ -118,8 +77,11 @@ start_logout_process(void)
argv0 = prog;
pid = fork();
- if(pid == 0)
+ if(pid == 0) {
+ /* avoid getting signals sent to the shell */
+ setpgid(0, getpid());
return 0;
+ }
if(pid == -1)
err(1, "fork");
/* wait for the real login process to exit */
@@ -167,7 +129,18 @@ exec_shell(const char *shell, int fallback)
err(1, "%s", shell);
}
-static enum { AUTH_KRB4, AUTH_KRB5 } 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;
@@ -179,19 +152,12 @@ krb5_verify(struct passwd *pwd, const char *password)
krb5_error_code ret;
krb5_principal princ;
- ret = krb5_init_context(&context);
- if(ret)
- return 1;
-
ret = krb5_parse_name(context, pwd->pw_name, &princ);
- if(ret){
- krb5_free_context(context);
+ if(ret)
return 1;
- }
ret = krb5_cc_gen_new(context, &krb5_mcc_ops, &id);
- if(ret){
+ if(ret) {
krb5_free_principal(context, princ);
- krb5_free_context(context);
return 1;
}
ret = krb5_verify_user_lrealm(context,
@@ -201,47 +167,39 @@ krb5_verify(struct passwd *pwd, const char *password)
1,
NULL);
krb5_free_principal(context, princ);
- if (ret)
- krb5_free_context (context);
return ret;
}
-static int
-krb5_start_session (const struct passwd *pwd)
-{
- krb5_error_code ret;
- char residual[64];
-
- /* copy credentials to file cache */
- snprintf(residual, sizeof(residual), "FILE:/tmp/krb5cc_%u",
- (unsigned)pwd->pw_uid);
- krb5_cc_resolve(context, residual, &id2);
- ret = krb5_cc_copy_cache(context, id, id2);
- if (ret == 0)
- add_env("KRB5CCNAME", residual);
- else {
- krb5_cc_destroy (context, id2);
- return ret;
- }
#ifdef KRB4
+static krb5_error_code
+krb5_to4 (krb5_ccache id)
+{
if (krb5_config_get_bool(context, NULL,
"libdefaults",
"krb4_get_tickets",
NULL)) {
CREDENTIALS c;
krb5_creds mcred, cred;
- krb5_realm realm;
char krb4tkfile[MAXPATHLEN];
+ krb5_error_code ret;
+ krb5_principal princ;
+
+ ret = krb5_cc_get_principal (context, id, &princ);
+ if (ret)
+ return ret;
- krb5_get_default_realm(context, &realm);
- krb5_make_principal(context, &mcred.server, realm,
- "krbtgt",
- realm,
- NULL);
- free (realm);
- ret = krb5_cc_retrieve_cred(context, id2, 0, &mcred, &cred);
+ ret = krb5_make_principal(context, &mcred.server,
+ princ->realm,
+ "krbtgt",
+ princ->realm,
+ NULL);
+ krb5_free_principal (context, princ);
+ if (ret)
+ return ret;
+
+ ret = krb5_cc_retrieve_cred(context, id, 0, &mcred, &cred);
if(ret == 0) {
- ret = krb524_convert_creds_kdc(context, id2, &cred, &c);
+ ret = krb524_convert_creds_kdc(context, id, &cred, &c);
if(ret == 0) {
snprintf(krb4tkfile,sizeof(krb4tkfile),"%s%d",TKT_ROOT,
getuid());
@@ -253,6 +211,29 @@ krb5_start_session (const struct passwd *pwd)
}
krb5_free_principal(context, mcred.server);
}
+ return 0;
+}
+#endif /* KRB4 */
+
+static int
+krb5_start_session (const struct passwd *pwd)
+{
+ krb5_error_code ret;
+ char residual[64];
+
+ /* copy credentials to file cache */
+ snprintf(residual, sizeof(residual), "FILE:/tmp/krb5cc_%u",
+ (unsigned)pwd->pw_uid);
+ krb5_cc_resolve(context, residual, &id2);
+ ret = krb5_cc_copy_cache(context, id, id2);
+ if (ret == 0)
+ add_env("KRB5CCNAME", residual);
+ else {
+ krb5_cc_destroy (context, id2);
+ return ret;
+ }
+#ifdef KRB4
+ krb5_to4 (id2);
#endif
krb5_cc_close(context, id2);
krb5_cc_destroy(context, id);
@@ -279,9 +260,6 @@ krb5_get_afs_tokens (const struct passwd *pwd)
if (!k_hasafs ())
return;
- ret = krb5_init_context(&context);
- if(ret)
- return;
ret = krb5_cc_default(context, &id2);
if (ret == 0) {
@@ -299,7 +277,6 @@ krb5_get_afs_tokens (const struct passwd *pwd)
pwd->pw_uid, pwd->pw_dir);
krb5_cc_close (context, id2);
}
- krb5_free_context (context);
}
#endif /* KRB4 */
@@ -365,14 +342,17 @@ krb4_get_afs_tokens (const struct passwd *pwd)
static int f_flag;
static int p_flag;
+#if 0
static int r_flag;
+#endif
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" },
@@ -450,7 +430,7 @@ do_login(const struct passwd *pwd, char *tty, char *ttyn)
else
tty_gid = pwd->pw_gid;
- if (chown (ttyn, pwd->pw_uid, pwd->pw_gid) < 0) {
+ if (chown (ttyn, pwd->pw_uid, tty_gid) < 0) {
warn("chown %s", ttyn);
if (rootlogin == 0)
exit (1);
@@ -481,7 +461,7 @@ do_login(const struct passwd *pwd, char *tty, char *ttyn)
if(rootlogin == 0)
exit(1);
}
- if(setuid(pwd->pw_uid)){
+ if(setuid(pwd->pw_uid) || (pwd->pw_uid != 0 && setuid(0) == 0)) {
warn("setuid(%u)", (unsigned)pwd->pw_uid);
if(rootlogin == 0)
exit(1);
@@ -560,17 +540,44 @@ do_login(const struct passwd *pwd, char *tty, char *ttyn)
#ifdef KRB5
if (auth == AUTH_KRB5) {
krb5_start_session (pwd);
- krb5_finish ();
}
#ifdef KRB4
+ else if (auth == 0) {
+ krb5_error_code ret;
+ krb5_ccache id;
+
+ ret = krb5_cc_default (context, &id);
+ if (ret == 0) {
+ krb5_to4 (id);
+ krb5_cc_close (context, id);
+ }
+ }
+
krb5_get_afs_tokens (pwd);
#endif /* KRB4 */
+ krb5_finish ();
#endif /* KRB5 */
#ifdef KRB4
krb4_get_afs_tokens (pwd);
#endif /* KRB4 */
+ add_env("PATH", _PATH_DEFPATH);
+
+ {
+ const char *str = login_conf_get_string("environment");
+ char buf[MAXPATHLEN];
+
+ if(str == NULL) {
+ login_read_env(_PATH_ETC_ENVIRONMENT);
+ } else {
+ while(strsep_copy(&str, ",", buf, sizeof(buf)) != -1) {
+ if(buf[0] == '\0')
+ continue;
+ login_read_env(buf);
+ }
+ }
+ }
add_env("HOME", home_dir);
add_env("USER", pwd->pw_name);
add_env("LOGNAME", pwd->pw_name);
@@ -604,6 +611,12 @@ check_password(struct passwd *pwd, const char *password)
return 0;
}
#endif
+#ifdef OTP
+ if (otp_verify (pwd, password) == 0) {
+ auth = AUTH_OTP;
+ return 0;
+ }
+#endif
return 1;
}
@@ -614,6 +627,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)
{
@@ -624,9 +648,20 @@ main(int argc, char **argv)
int optind = 0;
int ask = 1;
+ struct sigaction sa;
set_progname(argv[0]);
+#ifdef KRB5
+ {
+ krb5_error_code ret;
+
+ ret = krb5_init_context(&context);
+ if (ret)
+ errx (1, "krb5_init_context failed: %d", ret);
+ }
+#endif
+
openlog("login", LOG_ODELAY, LOG_AUTH);
if (getarg (args, sizeof(args) / sizeof(args[0]), argc, argv,
@@ -664,21 +699,41 @@ main(int argc, char **argv)
ask = 0;
}
}
+
+#if defined(DCE) && defined(AIX)
+ esetenv("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;
+ f_flag = 0;
+#if 0
+ r_flag = 0;
+#endif
ret = read_string("login: ", username, sizeof(username), 1);
if(ret == -3)
exit(0);
if(ret == -2)
- continue;
+ sig_handler(0); /* exit */
}
pwd = k_getpwnam(username);
#ifdef ALLOW_NULL_PASSWORD
@@ -687,11 +742,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");
@@ -724,6 +796,7 @@ main(int argc, char **argv)
pwd->pw_name, tty);
exit (1);
}
+ alarm(0);
do_login(pwd, tty, ttyn);
}
exit(1);
OpenPOWER on IntegriCloud