Mercurial > hg > toybox
comparison toys/login.c @ 642:812afb883392
Minor cleanups, mostly whitespace.
author | Rob Landley <rob@landley.net> |
---|---|
date | Tue, 24 Jul 2012 02:52:36 -0500 |
parents | 9aeea680acc7 |
children |
comparison
equal
deleted
inserted
replaced
641:94f189961631 | 642:812afb883392 |
---|---|
28 #define LOGIN_FAIL_TIMEOUT 3 | 28 #define LOGIN_FAIL_TIMEOUT 3 |
29 #define USER_NAME_MAX_SIZE 32 | 29 #define USER_NAME_MAX_SIZE 32 |
30 #define HOSTNAME_SIZE 32 | 30 #define HOSTNAME_SIZE 32 |
31 | 31 |
32 DEFINE_GLOBALS( | 32 DEFINE_GLOBALS( |
33 char * hostname; | 33 char *hostname; |
34 ) | 34 ) |
35 #define TT this.login | 35 #define TT this.login |
36 | 36 |
37 static void login_timeout_handler(int sig __attribute__((unused))) | 37 static void login_timeout_handler(int sig __attribute__((unused))) |
38 { | 38 { |
39 printf("\nLogin timed out after %d seconds.\n", LOGIN_TIMEOUT); | 39 printf("\nLogin timed out after %d seconds.\n", LOGIN_TIMEOUT); |
40 exit(0); | 40 exit(0); |
41 } | 41 } |
42 | 42 |
43 static const char *forbid[] = { | 43 static char *forbid[] = { |
44 "BASH_ENV", | 44 "BASH_ENV", |
45 "ENV", | 45 "ENV", |
46 "HOME", | 46 "HOME", |
47 "IFS", | 47 "IFS", |
48 "LD_LIBRARY_PATH", | 48 "LD_LIBRARY_PATH", |
55 "LD_KEEPDIR", | 55 "LD_KEEPDIR", |
56 "SHELL", | 56 "SHELL", |
57 NULL | 57 NULL |
58 }; | 58 }; |
59 | 59 |
60 // Unset dangerous environment variables. | |
61 void sanitize_env() | |
62 { | |
63 const char **p = forbid; | |
64 do { | |
65 unsetenv(*p); | |
66 p++; | |
67 } while (*p); | |
68 } | |
69 | |
70 int verify_password(char * pwd) | 60 int verify_password(char * pwd) |
71 { | 61 { |
72 char * pass; | 62 char *pass; |
73 | 63 |
74 if (read_password(toybuf, sizeof(toybuf), "Password: ")) | 64 if (read_password(toybuf, sizeof(toybuf), "Password: ")) return 1; |
75 return 1; | 65 if (!pwd) return 1; |
76 if (!pwd) | 66 if (pwd[0] == '!' || pwd[0] == '*') return 1; |
77 return 1; | |
78 if (pwd[0] == '!' || pwd[0] == '*') | |
79 return 1; | |
80 | 67 |
81 pass = crypt(toybuf, pwd); | 68 pass = crypt(toybuf, pwd); |
82 if (pass != NULL && strcmp(pass, pwd)==0) | 69 if (pass && !strcmp(pass, pwd)) return 0; |
83 return 0; | |
84 | 70 |
85 return 1; | 71 return 1; |
86 } | 72 } |
87 | 73 |
88 void read_user(char * buff, int size) | 74 void read_user(char * buff, int size) |
89 { | 75 { |
90 char hostname[HOSTNAME_SIZE+1]; | 76 char hostname[HOSTNAME_SIZE+1]; |
91 int i = 0; | 77 int i = 0; |
92 hostname[HOSTNAME_SIZE] = 0; | 78 hostname[HOSTNAME_SIZE] = 0; |
93 if(!gethostname(hostname, HOSTNAME_SIZE)) | 79 if(!gethostname(hostname, HOSTNAME_SIZE)) fputs(hostname, stdout); |
94 fputs(hostname, stdout); | |
95 | 80 |
96 fputs(" login: ", stdout); | 81 fputs(" login: ", stdout); |
97 fflush(stdout); | 82 fflush(stdout); |
98 | 83 |
99 do { | 84 do { |
104 | 89 |
105 if (buff[0] != '\n') | 90 if (buff[0] != '\n') |
106 if(!fgets(&buff[1], HOSTNAME_SIZE-1, stdin)) | 91 if(!fgets(&buff[1], HOSTNAME_SIZE-1, stdin)) |
107 _exit(1); | 92 _exit(1); |
108 | 93 |
109 while(i<HOSTNAME_SIZE-1 && isgraph(buff[i])) | 94 while(i<HOSTNAME_SIZE-1 && isgraph(buff[i])) i++; |
110 { | |
111 i++; | |
112 } | |
113 buff[i] = 0; | 95 buff[i] = 0; |
114 } | 96 } |
115 | 97 |
116 void handle_nologin(void) | 98 void handle_nologin(void) |
117 { | 99 { |
118 int fd = open("/etc/nologin", O_RDONLY); | 100 int fd = open("/etc/nologin", O_RDONLY); |
119 int size; | 101 int size; |
120 if (fd == -1) | 102 if (fd == -1) return; |
121 return; | |
122 | 103 |
123 size = readall(fd, toybuf,sizeof(toybuf)-1); | 104 size = readall(fd, toybuf,sizeof(toybuf)-1); |
124 toybuf[size] = 0; | 105 toybuf[size] = 0; |
125 if (!size) | 106 if (!size) puts("System closed for routine maintenance\n"); |
126 puts("System closed for routine maintenance\n"); | 107 else puts(toybuf); |
127 else | |
128 puts(toybuf); | |
129 | 108 |
130 close(fd); | 109 close(fd); |
131 fflush(stdout); | 110 fflush(stdout); |
132 exit(EXIT_FAILURE); | 111 exit(EXIT_FAILURE); |
133 } | 112 } |
134 | 113 |
135 void handle_motd(void) | 114 void handle_motd(void) |
136 { | 115 { |
137 int fd = open("/etc/motd", O_RDONLY); | 116 int fd = open("/etc/motd", O_RDONLY); |
138 int size; | 117 int size; |
139 if (fd == -1) | 118 if (fd == -1) return; |
140 return; | |
141 | 119 |
142 size = readall(fd, toybuf,sizeof(toybuf)-1); | 120 size = readall(fd, toybuf,sizeof(toybuf)-1); |
143 toybuf[size] = 0; | 121 toybuf[size] = 0; |
144 puts(toybuf); | 122 puts(toybuf); |
145 | 123 |
147 fflush(stdout); | 125 fflush(stdout); |
148 } | 126 } |
149 | 127 |
150 int change_identity(const struct passwd *pwd) | 128 int change_identity(const struct passwd *pwd) |
151 { | 129 { |
152 if (initgroups(pwd->pw_name,pwd->pw_gid)) | 130 if (initgroups(pwd->pw_name,pwd->pw_gid)) return 1; |
153 return 1; | 131 if (setgid(pwd->pw_uid)) return 1; |
154 if (setgid(pwd->pw_uid)) | 132 if (setuid(pwd->pw_uid)) return 1; |
155 return 1; | |
156 if (setuid(pwd->pw_uid)) | |
157 return 1; | |
158 | 133 |
159 return 0; | 134 return 0; |
160 } | 135 } |
161 | 136 |
162 void spawn_shell(const char *shell) | 137 void spawn_shell(const char *shell) |
163 { | 138 { |
164 const char * exec_name = strrchr(shell,'/'); | 139 const char * exec_name = strrchr(shell,'/'); |
165 if (exec_name) | 140 if (exec_name) exec_name++; |
166 exec_name++; | 141 else exec_name = shell; |
167 else | |
168 exec_name = shell; | |
169 | 142 |
170 snprintf(toybuf,sizeof(toybuf)-1, "-%s", shell); | 143 snprintf(toybuf,sizeof(toybuf)-1, "-%s", shell); |
171 execl(shell, toybuf, NULL); | 144 execl(shell, toybuf, NULL); |
172 error_exit("Failed to spawn shell"); | 145 error_exit("Failed to spawn shell"); |
173 } | 146 } |
174 | 147 |
175 void setup_environment(const struct passwd *pwd, int clear_env) | 148 void setup_environment(const struct passwd *pwd, int clear_env) |
176 { | 149 { |
177 if (chdir(pwd->pw_dir)) | 150 if (chdir(pwd->pw_dir)) printf("bad home dir: %s\n", pwd->pw_dir); |
178 printf("can't chdir to home directory: %s\n", pwd->pw_dir); | 151 |
179 | 152 if (clear_env) { |
180 if (clear_env) | |
181 { | |
182 const char * term = getenv("TERM"); | 153 const char * term = getenv("TERM"); |
183 clearenv(); | 154 clearenv(); |
184 if (term) setenv("TERM", term, 1); | 155 if (term) setenv("TERM", term, 1); |
185 } | 156 } |
186 | 157 |
187 setenv("USER", pwd->pw_name, 1); | 158 setenv("USER", pwd->pw_name, 1); |
188 setenv("LOGNAME", pwd->pw_name, 1); | 159 setenv("LOGNAME", pwd->pw_name, 1); |
189 setenv("HOME", pwd->pw_dir, 1); | 160 setenv("HOME", pwd->pw_dir, 1); |
190 setenv("SHELL", pwd->pw_shell, 1); | 161 setenv("SHELL", pwd->pw_shell, 1); |
191 } | 162 } |
192 | 163 |
193 void login_main(void) | 164 void login_main(void) |
194 { | 165 { |
195 int f_flag = (toys.optflags & 4) >> 2; | 166 int f_flag = (toys.optflags & 4) >> 2; |
196 int p_flag = (toys.optflags & 2) >> 1; | 167 int p_flag = (toys.optflags & 2) >> 1; |
197 int h_flag = toys.optflags & 1; | 168 int h_flag = toys.optflags & 1; |
198 char username[USER_NAME_MAX_SIZE+1]; | 169 char username[USER_NAME_MAX_SIZE+1], *pass = NULL, **ss; |
199 struct passwd * pwd = NULL; | 170 struct passwd * pwd = NULL; |
200 struct spwd * spwd = NULL; | 171 struct spwd * spwd = NULL; |
201 char *pass = NULL; | |
202 int auth_fail_cnt = 0; | 172 int auth_fail_cnt = 0; |
203 | 173 |
204 if (f_flag && toys.optc != 1) | 174 if (f_flag && toys.optc != 1) |
205 error_exit("-f requires username"); | 175 error_exit("-f requires username"); |
206 | 176 |
207 if (geteuid() != 0 ) | 177 if (geteuid()) error_exit("not root"); |
208 error_exit("Cannot possibly work without effective root"); | 178 |
209 | 179 if (!isatty(0) || !isatty(1) || !isatty(2)) error_exit("no tty"); |
210 if (!isatty(0) || !isatty(1) || !isatty(2)) | |
211 error_exit("Not connected to a tty"); | |
212 | 180 |
213 openlog("login", LOG_PID | LOG_CONS, LOG_AUTH); | 181 openlog("login", LOG_PID | LOG_CONS, LOG_AUTH); |
214 signal(SIGALRM, login_timeout_handler); | 182 signal(SIGALRM, login_timeout_handler); |
215 alarm(LOGIN_TIMEOUT); | 183 alarm(LOGIN_TIMEOUT); |
216 sanitize_env(); | 184 |
185 for (ss = forbid; *ss; ss++) unsetenv(*ss); | |
217 | 186 |
218 while (1) { | 187 while (1) { |
219 tcflush(0, TCIFLUSH); | 188 tcflush(0, TCIFLUSH); |
220 | 189 |
221 username[USER_NAME_MAX_SIZE] = 0; | 190 username[USER_NAME_MAX_SIZE] = 0; |
222 if (toys.optargs[0]) | 191 if (toys.optargs[0]) |
223 strncpy(username, toys.optargs[0], USER_NAME_MAX_SIZE); | 192 strncpy(username, toys.optargs[0], USER_NAME_MAX_SIZE); |
224 else { | 193 else { |
225 read_user(username, USER_NAME_MAX_SIZE+1); | 194 read_user(username, USER_NAME_MAX_SIZE+1); |
226 if (username[0] == 0) | 195 if (username[0] == 0) continue; |
227 continue; | |
228 } | 196 } |
229 | 197 |
230 pwd = getpwnam(username); | 198 pwd = getpwnam(username); |
231 if (!pwd) | 199 if (!pwd) goto query_pass; // Non-existing user |
232 goto query_pass; // Non-existing user | |
233 | 200 |
234 if (pwd->pw_passwd[0] == '!' || pwd->pw_passwd[0] == '*') | 201 if (pwd->pw_passwd[0] == '!' || pwd->pw_passwd[0] == '*') |
235 goto query_pass; // Locked account | 202 goto query_pass; // Locked account |
236 | 203 |
237 if (f_flag) | 204 if (f_flag) break; // Pre-authenticated |
238 break; // Pre-authenticated | 205 |
239 | 206 if (!pwd->pw_passwd[0]) break; // Password-less account |
240 if (pwd->pw_passwd[0] == '\0') | |
241 break; // Password-less account | |
242 | 207 |
243 pass = pwd->pw_passwd; | 208 pass = pwd->pw_passwd; |
244 if (pwd->pw_passwd[0] == 'x') { | 209 if (pwd->pw_passwd[0] == 'x') { |
245 spwd = getspnam (username); | 210 spwd = getspnam (username); |
246 if (spwd) | 211 if (spwd) pass = spwd->sp_pwdp; |
247 pass = spwd->sp_pwdp; | |
248 } | 212 } |
249 | 213 |
250 query_pass: | 214 query_pass: |
251 if (!verify_password(pass)) | 215 if (!verify_password(pass)) break; |
252 break; | |
253 | 216 |
254 f_flag = 0; | 217 f_flag = 0; |
255 syslog(LOG_WARNING, "invalid password for '%s' on %s %s %s", username, | 218 syslog(LOG_WARNING, "invalid password for '%s' on %s %s %s", username, |
256 ttyname(0), | 219 ttyname(0), (h_flag)?"from":"", (h_flag)?TT.hostname:""); |
257 (h_flag)?"from":"", | |
258 (h_flag)?TT.hostname:""); | |
259 | 220 |
260 sleep(LOGIN_FAIL_TIMEOUT); | 221 sleep(LOGIN_FAIL_TIMEOUT); |
261 puts("Login incorrect"); | 222 puts("Login incorrect"); |
262 | 223 |
263 if (++auth_fail_cnt == 3) | 224 if (++auth_fail_cnt == 3) |
264 { | |
265 error_exit("Maximum number of tries exceeded (%d)\n", auth_fail_cnt); | 225 error_exit("Maximum number of tries exceeded (%d)\n", auth_fail_cnt); |
266 } | |
267 | 226 |
268 username[0] = 0; | 227 username[0] = 0; |
269 pwd = NULL; | 228 pwd = NULL; |
270 spwd = NULL; | 229 spwd = NULL; |
271 } | 230 } |
272 | 231 |
273 alarm(0); | 232 alarm(0); |
274 | 233 |
275 if (pwd->pw_uid) | 234 if (pwd->pw_uid) handle_nologin(); |
276 handle_nologin(); | 235 |
277 | 236 if (change_identity(pwd)) error_exit("Failed to change identity"); |
278 if (change_identity(pwd)) | |
279 error_exit("Failed to change identity"); | |
280 | 237 |
281 setup_environment(pwd, !p_flag); | 238 setup_environment(pwd, !p_flag); |
282 | 239 |
283 handle_motd(); | 240 handle_motd(); |
284 | 241 |
285 syslog(LOG_INFO, "%s logged in on %s %s %s", pwd->pw_name, | 242 syslog(LOG_INFO, "%s logged in on %s %s %s", pwd->pw_name, |
286 ttyname(0), | 243 ttyname(0), (h_flag)?"from":"", (h_flag)?TT.hostname:""); |
287 (h_flag)?"from":"", | |
288 (h_flag)?TT.hostname:""); | |
289 | 244 |
290 spawn_shell(pwd->pw_shell); | 245 spawn_shell(pwd->pw_shell); |
291 } | 246 } |