1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
|
/* login.c */
#define LOGIN_PROGRAM
#include <unistd.h>
#include <fcntl.h>
#include <time.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <termios.h>
#include "config.h"
#include "str_defs.h"
#include "pw_defs.h"
#include "utmp_defs.h"
#include "prot_defs.h"
#define SD(A,B) !str_diffn(A, B, sizeof(A))
#define SC(A,B) str_copynz(A, B, sizeof(A))
static void myexit(int n,char *s)
{ write(2,s,str_len(s)); write(2,"\n",1); _exit(n); }
int main(int argc, char **argv, char **env) {
struct passwd *pw=0;
struct spwd *spwd;
char buf[1200], lastlog[96];
char *tty, *dev_tty=0, *program, *username=0, *p;
char *arg[8] = {buf,0,0,0, 0,0,0,0};
int fd,r,OK=0,flag_auto=0;
struct termios oldtermios;
if (ioctl(0, TCGETS, &oldtermios)) _exit(100);
oldtermios.c_lflag &= ~(ECHO|ISIG);
tcsetattr(0,TCSAFLUSH,&oldtermios);
if ((dev_tty=ttyname(0)) && !str_diffn("/dev/",dev_tty,5)) tty=dev_tty+5;
else { dev_tty = 0; tty="UNKNOWN"; }
program=strip_slash(argv[0]);
argv++; (void)argc;
while ((p=argv[0]) && p[0] == '-') {
if (p[1]=='f') {
if (getuid()) goto do_it;
if (p[2]) p += 2;
else p=argv[1];
if (p && *p && *p != '-') {
flag_auto=1;
argv[0]=p;
break;
} else
goto do_it;
}
argv++;
}
if (argv[0] == 0) goto do_it;
if (flag_auto == 0)
if (read_password(buf)) goto do_it;
pw = nv_getpwnam(argv[0]);
if (pw) {
username = pw->pw_name;
if (pw->pw_passwd[0]=='*' ||
pw->pw_passwd[0]=='!') goto do_it;
}
if (!username || *username == 0) goto do_it;
if (flag_auto==1) OK=1;
else {
if ((spwd = nv_getspnam(username))==0) goto do_it;
OK = pass_check(buf, spwd->sp_pwdp);
}
do_it:
byte_zero(buf,sizeof(buf));
oldtermios.c_lflag |= ECHO;
tcsetattr(0, TCSAFLUSH, &oldtermios);
if (!username) username="UNKNOWN";
log_do(buf,OK, program,username,tty);
if (!OK) { sleep(1); myexit(100,"Sorry :-)"); }
utmp_do(username, tty, getpid());
lastlog_do(lastlog, pw->pw_uid, tty);
get_tz(0,-1);
if (dev_tty) {
struct group *gr = nv_getgrnam("tty");
chown(dev_tty, pw->pw_uid, gr ? gr->gr_gid : pw->pw_gid);
chmod(dev_tty, 0620);
}
p = 0;
if (nv_initgroups(pw->pw_name,pw->pw_gid) == -1) p = "groups";
else if (setgid(pw->pw_gid) == -1) p = "gid";
else if (setuid(pw->pw_uid) == -1) p = "uid";
if (p) {
mycat(buf, "unable to set", p);
myexit(111, buf);
}
if (chdir(pw->pw_dir)) {
r = mycat(buf,"unable to chdir: ",pw->pw_dir); buf[r++] = '\n';
write(1,buf,r);
chdir("/");
}
if ((fd=open(".hushlogin", O_RDONLY)) >=0) {
close(fd);
} else {
if ((fd=open("/etc/motd", O_RDONLY)) != -1) {
while ((r=read(fd,buf,sizeof buf)) >0) write(1,buf,r);
close(fd);
}
write(1, lastlog, str_len(lastlog));
}
p=buf; p += 1 + mycat(p,"-",strip_slash(pw->pw_shell));
arg[2]=p; p += 1 + mycat(p,"HOME=",pw->pw_dir);
arg[3]=p; p += 1 + mycat(p,"USER=",pw->pw_name);
arg[4]=p; p += 1 + mycat(p,"SHELL=",pw->pw_shell);
for (; *env; env++)
if (!str_diffn(*env,"TERM=",5)) {arg[5]=*env; break;} /* arg[7] */
oldtermios.c_lflag |= ISIG;
tcsetattr(0, TCSAFLUSH, &oldtermios);
execve(pw->pw_shell,arg,arg+2);
return(1);
}
|