summaryrefslogtreecommitdiffstats
path: root/term-utils/agetty.c
diff options
context:
space:
mode:
authorWerner Fink2011-05-09 15:52:39 +0200
committerKarel Zak2011-05-17 11:13:06 +0200
commiteb8e1f9f0cfb8ebb44ca50962e0623257c4d6436 (patch)
treef8a90572d9269056d38aa7555163fdf714a25fe0 /term-utils/agetty.c
parentagetty: better support of virtual console (diff)
downloadkernel-qcow2-util-linux-eb8e1f9f0cfb8ebb44ca50962e0623257c4d6436.tar.gz
kernel-qcow2-util-linux-eb8e1f9f0cfb8ebb44ca50962e0623257c4d6436.tar.xz
kernel-qcow2-util-linux-eb8e1f9f0cfb8ebb44ca50962e0623257c4d6436.zip
agetty: add an autologin feature
Add an autologin feature to agetty, that is that a user can be automatically logged in. For this the options of for the login program has to used. Make it possible to pass-through options to the login program which requires a security check. Signed-off-by: Werner Fink <werner@suse.de>
Diffstat (limited to 'term-utils/agetty.c')
-rw-r--r--term-utils/agetty.c219
1 files changed, 193 insertions, 26 deletions
diff --git a/term-utils/agetty.c b/term-utils/agetty.c
index 5f2df0837..64b2fd1ff 100644
--- a/term-utils/agetty.c
+++ b/term-utils/agetty.c
@@ -93,7 +93,8 @@
#endif
/* Login prompt. */
-#define LOGIN " login: "
+#define LOGIN " login: "
+#define ARRAY_SIZE_MAX 16 /* Numbers of args for login beside "-- \\u" */
/* Some shorthands for control characters. */
#define CTL(x) (x ^ 0100) /* Assumes ASCII dialect */
@@ -131,7 +132,9 @@
struct options {
int flags; /* toggle switches, see below */
int timeout; /* time-out period */
+ char *autolog; /* login the user automatically */
char *login; /* login program */
+ char *logopt; /* options for login program */
char *tty; /* name of tty */
char *vcline; /* line of virtual console */
char *term; /* terminal type */
@@ -156,6 +159,7 @@ struct options {
#define F_VCONSOLE (1<<12) /* This is a virtual console */
#define F_HANGUP (1<<13) /* Do call vhangup(2) */
#define F_UTF8 (1<<14) /* We can do UTF8 */
+#define F_LOGINPAUSE (1<<15) /* Wait for any key before dropping login prompt */
#define serial_tty_option(opt, flag) \
(((opt)->flags & (F_VCONSOLE|(flag))) == (flag))
@@ -241,6 +245,9 @@ static speed_t bcode(char *s);
static void usage(FILE * out) __attribute__((__noreturn__));
static void log_err(const char *, ...) __attribute__((__noreturn__)) __attribute__((__format__(printf, 1, 2)));
static void log_warn (const char *, ...) __attribute__((__format__(printf, 1, 2)));
+static void checkname (const char* nm);
+static void replacename (char** arr, const char* nm);
+static void mkarray (char** arr, char* str);
/* Fake hostname for ut_host specified on command line. */
static char *fakehost;
@@ -254,20 +261,18 @@ FILE *dbf;
int main(int argc, char **argv)
{
- char *logname = NULL; /* login name, given to /bin/login */
- struct chardata chardata; /* will be set by get_logname() */
- struct termios termios; /* terminal mode bits */
+ char *logname = NULL; /* login name, given to /bin/login */
+ char logcmd[NAME_MAX+1];
+ char *logarr[ARRAY_SIZE_MAX + 2]; /* arguments plus "-- \\u" */
+ struct chardata chardata; /* will be set by get_logname() */
+ struct termios termios; /* terminal mode bits */
static struct options options = {
- F_ISSUE, /* show /etc/issue (SYSV_STYLE) */
- 0, /* no timeout */
- _PATH_LOGIN, /* default login program */
- "tty1", /* default tty line */
- 0, /* line of virtual console */
- DEFAULT_VCTERM, /* terminal type */
- "", /* modem init string */
- ISSUE, /* default issue file */
- 0, /* no baud rates known yet */
- { 0 }
+ .flags = F_ISSUE, /* show /etc/issue (SYSV_STYLE) */
+ .login = _PATH_LOGIN, /* default login program */
+ .logopt = "-- \\u", /* escape for user name */
+ .tty = "tty1", /* default tty line */
+ .term = DEFAULT_VCTERM, /* terminal type */
+ .issue = ISSUE /* default issue file */
};
struct sigaction sa, sa_hup, sa_quit, sa_int;
sigset_t set;
@@ -315,7 +320,8 @@ int main(int argc, char **argv)
termio_init(&options, &termios);
/* Write the modem init string and DO NOT flush the buffers. */
- if (serial_tty_option(&options, F_INITSTRING)) {
+ if (serial_tty_option(&options, F_INITSTRING) &&
+ options.initstring && *options.initstring != '\0') {
debug("writing init string\n");
write_all(STDOUT_FILENO, options.initstring,
strlen(options.initstring));
@@ -353,12 +359,21 @@ int main(int argc, char **argv)
chardata = init_chardata;
if ((options.flags & F_NOPROMPT) == 0) {
- /* Read the login name. */
- debug("reading login name\n");
- while ((logname =
- get_logname(&options, &termios, &chardata)) == 0)
- if ((options.flags & F_VCONSOLE) == 0)
- next_speed(&options, &termios);
+ if (options.autolog) {
+ /* Do the auto login */
+ debug("doing auto login\n");
+ do_prompt(&options, &termios);
+ printf ("%s%s (automatic login)\n", LOGIN, options.autolog);
+ logname = options.autolog;
+ options.logopt = "-f \\u";
+ } else {
+ /* Read the login name. */
+ debug("reading login name\n");
+ while ((logname =
+ get_logname(&options, &termios, &chardata)) == 0)
+ if ((options.flags & F_VCONSOLE) == 0)
+ next_speed(&options, &termios);
+ }
}
/* Disable timer. */
@@ -376,8 +391,16 @@ int main(int argc, char **argv)
sigaction (SIGQUIT, &sa_quit, NULL);
sigaction (SIGINT, &sa_int, NULL);
+ strncpy(logcmd, options.login, NAME_MAX);
+ strncat(logcmd, " ", NAME_MAX - strlen(logcmd));
+ strncat(logcmd, options.logopt, NAME_MAX - strlen(logcmd));
+
+ checkname(logname);
+ mkarray(logarr, logcmd);
+ replacename(logarr, logname);
+
/* Let the login program take care of password validation. */
- execl(options.login, options.login, "--", logname, NULL);
+ execv(options.login, logarr);
log_err(_("%s: can't exec %s: %m"), options.tty, options.login);
}
@@ -394,6 +417,7 @@ static void parse_args(int argc, char **argv, struct options *op)
};
const struct option longopts[] = {
{ "8bits", no_argument, 0, '8' },
+ { "autologin", required_argument, 0, 'a' },
{ "noreset", no_argument, 0, 'c' },
{ "issue-file", required_argument, 0, 'f' },
{ "flow-control", no_argument, 0, 'h' },
@@ -404,6 +428,10 @@ static void parse_args(int argc, char **argv, struct options *op)
{ "local-line", no_argument, 0, 'L' },
{ "extract-baud", no_argument, 0, 'm' },
{ "skip-login", no_argument, 0, 'n' },
+ { "login-options", required_argument, 0, 'o' },
+ { "loginopts", required_argument, 0, 'o' }, /* compat option */
+ { "logopts", required_argument, 0, 'o' }, /* compat option */
+ { "loginpause", no_argument, 0, 'p' },
{ "hangup", no_argument, 0, 'R' },
{ "keep-baud", no_argument, 0, 's' },
{ "timeout", required_argument, 0, 't' },
@@ -414,12 +442,15 @@ static void parse_args(int argc, char **argv, struct options *op)
{ NULL, 0, 0, 0 }
};
- while ((c = getopt_long(argc, argv, "8cf:hH:iI:l:LmnsRt:Uw", longopts,
+ while ((c = getopt_long(argc, argv, "8a:cf:hH:iI:l:Lmno:pRst:Uw", longopts,
NULL)) != -1) {
switch (c) {
case '8':
op->flags |= F_EIGHTBITS;
break;
+ case 'a':
+ op->autolog = optarg;
+ break;
case 'c':
op->flags |= F_KEEPCFLAGS;
break;
@@ -452,6 +483,12 @@ static void parse_args(int argc, char **argv, struct options *op)
case 'n':
op->flags |= F_NOPROMPT;
break;
+ case 'o':
+ op->logopt = optarg;
+ break;
+ case 'p':
+ op->flags |= F_LOGINPAUSE;
+ break;
case 'R':
op->flags |= F_HANGUP;
break;
@@ -1066,14 +1103,73 @@ static void do_prompt(struct options *op, struct termios *tp)
}
fclose(fd);
}
-#endif /* ISSUE */
+#endif /* ISSUE */
+ if (op->flags & F_LOGINPAUSE) {
+ puts("[press ENTER to login]");
+ getc(stdin);
+ }
+#ifdef KDGKBLED
+ if (op->autolog == (char*)0 && (op->flags & F_VCONSOLE)) {
+ int kb = 0, nl = 0;
+ struct stat st;
+ if (stat("/var/run/numlock-on", &st) == 0)
+ nl = 1;
+ if (ioctl(STDIN_FILENO, KDGKBLED, &kb) == 0) {
+ const char *hint = _("Hint: ");
+ char warn[256];
+ off_t space = sizeof(warn) - 1, off = 0;
+
+ if (nl && (kb & 0x02) == 0) {
+ const char *msg = _("Num Lock off");
+ const size_t len = strlen(msg);
+ strncpy(&warn[0], msg, space);
+ space -= len;
+ off += len;
+ } else if (nl == 0 && (kb & 2) && (kb & 0x20) == 0) {
+ const char *msg = _("Num Lock on");
+ const size_t len = strlen(msg);
+ strncpy(&warn[0], msg, space);
+ space -= len;
+ off += len;
+ }
+ if ((kb & 0x04) && (kb & 0x40) == 0) {
+ const char *msg = _("Caps Lock on");
+ const size_t len = strlen(msg);
+ if (off) {
+ strncpy(&warn[off], ", ", space);
+ space -= 2;
+ off += 2;
+ }
+ strncpy(&warn[off], msg, space);
+ space -= len;
+ off += len;
+ }
+ if ((kb & 0x01) && (kb & 0x10) == 0) {
+ const char *msg = _("Scroll Lock on");
+ const size_t len = strlen(msg);
+ if (off) {
+ strncpy(&warn[off], ", ", space);
+ space -= 2;
+ off += 2;
+ }
+ strncpy(&warn[off], msg, space);
+ space -= len;
+ off += len;
+ }
+ if (off)
+ printf ("%s%s\n\n", hint, warn);
+ }
+ }
+#endif /* KDGKBLED */
{
char hn[MAXHOSTNAMELEN + 1];
if (gethostname(hn, sizeof(hn)) == 0)
write_all(STDOUT_FILENO, hn, strlen(hn));
}
- /* Always show login prompt. */
- write_all(STDOUT_FILENO, LOGIN, sizeof(LOGIN) - 1);
+ if (op->autolog == (char*)0) {
+ /* Always show login prompt. */
+ write_all(STDOUT_FILENO, LOGIN, sizeof(LOGIN) - 1);
+ }
}
/* Select next baud rate. */
@@ -1360,6 +1456,7 @@ static void __attribute__ ((__noreturn__)) usage(FILE * out)
fprintf(out, _("\nOptions:\n"
" -8, --8bits assume 8-bit tty\n"
+ " -a, --autologin USER login the specified user automatically\n"
" -c, --noreset do not reset control mode\n"
" -f, --issue-file FILE display issue file\n"
" -h, --flow-control enable hardware flow control\n"
@@ -1370,6 +1467,8 @@ static void __attribute__ ((__noreturn__)) usage(FILE * out)
" -L, --local-line force local line\n"
" -m, --extract-baud extract baud rate during connect\n"
" -n, --skip-login do not prompt for login\n"
+ " -o, --login-options OPTS options that are passed to login\n"
+ " -p, --loginpause wait for any key before the login\n"
" -R, --hangup do virtually hangup on the tty\n"
" -s, --keep-baud try to keep baud rate after break\n"
" -t, --timeout NUMBER login process timeout\n"
@@ -1603,3 +1702,71 @@ static void init_special_char(char* arg, struct options *op)
}
*q = '\0';
}
+
+/*
+ * Do not allow the user to pass an option as a user name
+ * To be more safe: Use `--' to make sure the rest is
+ * interpreted as non-options by the program, if it supports it.
+ */
+static void checkname(const char* nm)
+{
+ const char *p = nm;
+ if (!nm)
+ goto err;
+ if (strlen (nm) > 42)
+ goto err;
+ while (isspace (*p))
+ p++;
+ if (*p == '-')
+ goto err;
+ return;
+err:
+ errno = EPERM;
+ log_err ("checkname: %m");
+}
+
+static void replacename(char** arr, const char* nm)
+{
+ const char *p;
+ char *tmp;
+ while ((p = *arr)) {
+ const char *p1 = p;
+ while (*p1) {
+ if (memcmp (p1, "\\u", 2) == 0) {
+ tmp = malloc (strlen (p) + strlen (nm));
+ if (!tmp)
+ log_err ("replacename: %m");
+ if (p1 != p)
+ memcpy (tmp, p, (p1-p));
+ *(tmp + (p1-p)) = 0;
+ strcat (tmp, nm);
+ strcat (tmp, p1+2);
+ *arr = tmp;
+ }
+ p1++;
+ }
+ arr++;
+}
+}
+
+static void mkarray(char** arr, char* str)
+{
+ char* p = str;
+ char* start = p;
+ int i = 0;
+
+ while (*p && i < (ARRAY_SIZE_MAX)) {
+ if (isspace (*p)) {
+ *p = 0;
+ while (isspace (*++p))
+ ;
+ if (*p) {
+ arr[i++] = start;
+ start = p;
+ }
+ } else
+ p++;
+ }
+ arr[i++] = start;
+ arr[i++] = (char*)0;
+}