summaryrefslogtreecommitdiffstats
path: root/login-utils/login.c
diff options
context:
space:
mode:
authorKarel Zak2006-12-07 00:25:33 +0100
committerKarel Zak2006-12-07 00:25:33 +0100
commit726f69e29ca9d4842f3acb20fffd2466fda62c09 (patch)
treeabbc1b6e9bfb0dfe32e81a83648e261ccb2d5a5f /login-utils/login.c
parentImported from util-linux-2.2 tarball. (diff)
downloadkernel-qcow2-util-linux-726f69e29ca9d4842f3acb20fffd2466fda62c09.tar.gz
kernel-qcow2-util-linux-726f69e29ca9d4842f3acb20fffd2466fda62c09.tar.xz
kernel-qcow2-util-linux-726f69e29ca9d4842f3acb20fffd2466fda62c09.zip
Imported from util-linux-2.5 tarball.
Diffstat (limited to 'login-utils/login.c')
-rw-r--r--login-utils/login.c185
1 files changed, 88 insertions, 97 deletions
diff --git a/login-utils/login.c b/login-utils/login.c
index f0130f8ed..33a0b03e7 100644
--- a/login-utils/login.c
+++ b/login-utils/login.c
@@ -130,8 +130,11 @@ static char sccsid[] = "@(#)login.c 5.40 (Berkeley) 5/9/89";
#ifndef linux
#include <tzfile.h>
+#endif
#include <lastlog.h>
-#else
+
+#if 0
+/* from before we had a lastlog.h file in linux */
struct lastlog
{ long ll_time;
char ll_line[12];
@@ -152,7 +155,7 @@ void checknologin P_((void));
void dolastlog P_((int quiet));
void badlogin P_((char *name));
char *stypeof P_((char *ttyid));
-void checktty P_((char *user, char *tty));
+void checktty P_((char *user, char *tty, struct passwd *pwd));
void getstr P_((char *buf, int cnt, char *err));
void sleepexit P_((int eval));
#undef P_
@@ -164,13 +167,11 @@ char realm[REALM_SZ];
int kerror = KSUCCESS, notickets = 1;
#endif
-#ifndef linux
#define TTYGRPNAME "tty" /* name of group to own ttys */
-#else
-# define TTYGRPNAME "other"
-# ifndef MAXPATHLEN
-# define MAXPATHLEN 1024
-# endif
+/**# define TTYGRPNAME "other" **/
+
+#ifndef MAXPATHLEN
+# define MAXPATHLEN 1024
#endif
/*
@@ -184,9 +185,9 @@ int timeout = 60;
#endif
struct passwd *pwd;
-int failures;
+int failures = 1;
char term[64], *hostname, *username, *tty;
-
+struct hostent hostaddress;
char thishost[100];
#ifndef linux
@@ -265,6 +266,7 @@ main(argc, argv)
(void)strncpy(thishost, tbuf, sizeof(thishost)-1);
domain = index(tbuf, '.');
+ hostname = NULL;
fflag = hflag = pflag = 0;
passwd_req = 1;
while ((ch = getopt(argc, argv, "fh:p")) != EOF)
@@ -284,6 +286,14 @@ main(argc, argv)
strcasecmp(p, domain) == 0)
*p = 0;
hostname = optarg;
+ {
+ struct hostent *he = gethostbyname(hostname);
+ if (he) {
+ memcpy(&hostaddress, he, sizeof(hostaddress));
+ } else {
+ memset(&hostaddress, 0, sizeof(hostaddress));
+ }
+ }
break;
case 'p':
@@ -357,7 +367,7 @@ main(argc, argv)
tcsetattr(0,TCSAFLUSH,&tt);
}
- if (tty = rindex(ttyn, '/'))
+ if ((tty = rindex(ttyn, '/')))
++tty;
else
tty = ttyn;
@@ -375,14 +385,27 @@ main(argc, argv)
getloginname();
}
- checktty(username, tty);
+ /* Dirty patch to fix a gigantic security hole when using
+ yellow pages. This problem should be solved by the
+ libraries, and not by programs, but this must be fixed
+ urgently! If the first char of the username is '+', we
+ avoid login success.
+ Feb 95 <alvaro@etsit.upm.es> */
+
+ if (username[0] == '+') {
+ puts("Illegal username");
+ badlogin(username);
+ sleepexit(1);
+ }
(void)strcpy(tbuf, username);
- if (pwd = getpwnam(username))
+ if ((pwd = getpwnam(username)))
salt = pwd->pw_passwd;
else
salt = "xx";
+ checktty(username, tty, pwd); /* in checktty.c */
+
/* if user not super-user, check for disabled logins */
if (pwd == NULL || pwd->pw_uid)
checknologin();
@@ -566,30 +589,38 @@ main(argc, argv)
/* for linux, write entries in utmp and wtmp */
{
struct utmp ut;
- char *ttyabbrev;
int wtmp;
-
- memset((char *)&ut, 0, sizeof(ut));
- ut.ut_type = USER_PROCESS;
- ut.ut_pid = getpid();
- strncpy(ut.ut_line, ttyn + sizeof("/dev/")-1, sizeof(ut.ut_line));
- ttyabbrev = ttyn + sizeof("/dev/tty") - 1;
- strncpy(ut.ut_id, ttyabbrev, sizeof(ut.ut_id));
- (void)time(&ut.ut_time);
+ struct utmp *utp;
+ pid_t mypid = getpid();
+
+ utmpname(_PATH_UTMP);
+ setutent();
+ while ((utp = getutent())
+ && !(utp->ut_pid == mypid)) /* nothing */;
+
+ if (utp) {
+ memcpy(&ut, utp, sizeof(ut));
+ } else {
+ /* some gettys/telnetds don't initialize utmp... */
+ memset(&ut, 0, sizeof(ut));
+ }
+ endutent();
+
+ if (ut.ut_id[0] == 0)
+ strncpy(ut.ut_id, ttyn + 8, sizeof(ut.ut_id));
+
strncpy(ut.ut_user, username, sizeof(ut.ut_user));
-
- /* fill in host and ip-addr fields when we get networking */
+ strncpy(ut.ut_line, ttyn + 5, sizeof(ut.ut_line));
+ time(&ut.ut_time);
+ ut.ut_type = USER_PROCESS;
+ ut.ut_pid = mypid;
if (hostname) {
- struct hostent *he;
-
strncpy(ut.ut_host, hostname, sizeof(ut.ut_host));
- if ((he = gethostbyname(hostname)))
- memcpy(&ut.ut_addr, he->h_addr_list[0],
+ if (hostaddress.h_addr_list)
+ memcpy(&ut.ut_addr, hostaddress.h_addr_list[0],
sizeof(ut.ut_addr));
}
-
- utmpname(_PATH_UTMP);
- setutent();
+
pututline(&ut);
endutent();
@@ -600,7 +631,6 @@ main(argc, argv)
close(wtmp);
}
}
- /* fix_utmp_type_and_user(username, ttyn, LOGIN_PROCESS); */
#endif
dolastlog(quietlog);
@@ -615,9 +645,13 @@ main(argc, argv)
(void)chown(ttyn, pwd->pw_uid,
(gr = getgrnam(TTYGRPNAME)) ? gr->gr_gid : pwd->pw_gid);
- (void)chmod(ttyn, 0622);
- (void)setgid(pwd->pw_gid);
+#ifdef USE_TTY_GROUP
+ chmod(ttyn, 0620);
+#else
+ chmod(ttyn, 0600);
+#endif
+ setgid(pwd->pw_gid);
initgroups(username, pwd->pw_gid);
#ifdef HAVE_QUOTA
@@ -676,10 +710,9 @@ main(argc, argv)
(void)setenv("LOGNAME", pwd->pw_name, 1);
#endif
-#ifndef linux
- if (tty[sizeof("tty")-1] == 'd')
+ if (tty[sizeof("tty")-1] == 'S')
syslog(LOG_INFO, "DIALUP %s, %s", tty, pwd->pw_name);
-#endif
+
if (pwd->pw_uid == 0)
if (hostname)
syslog(LOG_NOTICE, "ROOT LOGIN ON %s FROM %s",
@@ -748,16 +781,26 @@ getloginname()
register int ch;
register char *p;
static char nbuf[UT_NAMESIZE + 1];
+ int cnt, cnt2;
+ cnt2 = 0;
for (;;) {
+ cnt = 0;
(void)printf("\n%s login: ", thishost); fflush(stdout);
for (p = nbuf; (ch = getchar()) != '\n'; ) {
if (ch == EOF) {
- badlogin(username);
+ badlogin("EOF");
exit(0);
}
if (p < nbuf + UT_NAMESIZE)
*p++ = ch;
+
+ cnt++;
+ if (cnt > UT_NAMESIZE + 20) {
+ fprintf(stderr, "login name much too long.\n");
+ badlogin("NAME too long");
+ exit(0);
+ }
}
if (p > nbuf)
if (nbuf[0] == '-')
@@ -768,6 +811,13 @@ getloginname()
username = nbuf;
break;
}
+
+ cnt2++;
+ if (cnt2 > 50) {
+ fprintf(stderr, "too many bare linefeeds.\n");
+ badlogin("EXCESSIVE linefeeds");
+ exit(0);
+ }
}
}
@@ -898,9 +948,6 @@ void
badlogin(name)
char *name;
{
- if (failures == 0)
- return;
-
if (hostname)
syslog(LOG_NOTICE, "%d LOGIN FAILURE%s FROM %s, %s",
failures, failures > 1 ? "S" : "", hostname, name);
@@ -924,62 +971,6 @@ stypeof(ttyid)
#endif
void
-checktty(user, tty)
- char *user;
- char *tty;
-{
- FILE *f;
- char buf[256];
- char *ptr;
- char devname[50];
- struct stat stb;
-
- /* no /etc/usertty, default to allow access */
- if(!(f = fopen(_PATH_USERTTY, "r"))) return;
-
- while(fgets(buf, 255, f)) {
-
- /* strip comments */
- for(ptr = buf; ptr < buf + 256; ptr++)
- if(*ptr == '#') *ptr = 0;
-
- strtok(buf, " \t");
- if(strncmp(user, buf, 8) == 0) {
- while((ptr = strtok(NULL, "\t\n "))) {
- if(strncmp(tty, ptr, 10) == 0) {
- fclose(f);
- return;
- }
- if(strcmp("PTY", ptr) == 0) {
-#ifdef linux
- sprintf(devname, "/dev/%s", ptr);
- /* VERY linux dependent, recognize PTY as alias
- for all pseudo tty's */
- if((stat(devname, &stb) >= 0)
- && major(stb.st_rdev) == 4
- && minor(stb.st_rdev) >= 192) {
- fclose(f);
- return;
- }
-#endif
- }
- }
- /* if we get here, /etc/usertty exists, there's a line
- beginning with our username, but it doesn't contain the
- name of the tty where the user is trying to log in.
- So deny access! */
- fclose(f);
- printf("Login on %s denied.\n", tty);
- badlogin(user);
- sleepexit(1);
- }
- }
- fclose(f);
- /* users not mentioned in /etc/usertty are by default allowed access
- on all tty's */
-}
-
-void
getstr(buf, cnt, err)
char *buf, *err;
int cnt;