1 | /* |
---|
2 | * xdm - display manager daemon |
---|
3 | * |
---|
4 | * $XConsortium: verify.c,v 1.24 91/07/18 22:22:45 rws Exp $ |
---|
5 | * $Header: /afs/dev.mit.edu/source/repository/athena/etc/xdm/xdm/verify.c,v 1.2 1993-06-30 17:14:36 cfields Exp $ |
---|
6 | * |
---|
7 | * Copyright 1988 Massachusetts Institute of Technology |
---|
8 | * |
---|
9 | * Permission to use, copy, modify, and distribute this software and its |
---|
10 | * documentation for any purpose and without fee is hereby granted, provided |
---|
11 | * that the above copyright notice appear in all copies and that both that |
---|
12 | * copyright notice and this permission notice appear in supporting |
---|
13 | * documentation, and that the name of M.I.T. not be used in advertising or |
---|
14 | * publicity pertaining to distribution of the software without specific, |
---|
15 | * written prior permission. M.I.T. makes no representations about the |
---|
16 | * suitability of this software for any purpose. It is provided "as is" |
---|
17 | * without express or implied warranty. |
---|
18 | * |
---|
19 | * Author: Keith Packard, MIT X Consortium |
---|
20 | */ |
---|
21 | |
---|
22 | /* |
---|
23 | * verify.c |
---|
24 | * |
---|
25 | * typical unix verification routine. |
---|
26 | */ |
---|
27 | |
---|
28 | # include "dm.h" |
---|
29 | # include <pwd.h> |
---|
30 | # include <utmp.h> |
---|
31 | # ifdef NGROUPS_MAX |
---|
32 | # include <grp.h> |
---|
33 | # endif |
---|
34 | #ifdef USESHADOW |
---|
35 | # include <shadow.h> |
---|
36 | #endif |
---|
37 | #ifdef X_NOT_STDC_ENV |
---|
38 | char *getenv(); |
---|
39 | #endif |
---|
40 | #include <signal.h> |
---|
41 | #ifdef _POSIX_SOURCE |
---|
42 | #include <unistd.h> |
---|
43 | #endif |
---|
44 | |
---|
45 | struct passwd joeblow = { |
---|
46 | "Nobody", "***************" |
---|
47 | }; |
---|
48 | |
---|
49 | #ifdef USESHADOW |
---|
50 | struct spwd spjoeblow = { |
---|
51 | "Nobody", "**************" |
---|
52 | }; |
---|
53 | #endif |
---|
54 | |
---|
55 | static char *envvars[] = { |
---|
56 | #if defined(sony) && !defined(SYSTYPE_SYSV) |
---|
57 | "bootdev", |
---|
58 | "boothowto", |
---|
59 | "cputype", |
---|
60 | "ioptype", |
---|
61 | "machine", |
---|
62 | "model", |
---|
63 | "CONSDEVTYPE", |
---|
64 | "SYS_LANGUAGE", |
---|
65 | "SYS_CODE", |
---|
66 | "TZ", |
---|
67 | #endif |
---|
68 | NULL |
---|
69 | }; |
---|
70 | |
---|
71 | int attach_pid, attach_state, attachhelp_pid, attachhelp_state, quota_pid; |
---|
72 | static int console = 0; |
---|
73 | static char consoletty[10]; |
---|
74 | extern char *defaultpath; |
---|
75 | |
---|
76 | Verify (d, greet, verify) |
---|
77 | struct display *d; |
---|
78 | struct greet_info *greet; |
---|
79 | struct verify_info *verify; |
---|
80 | { |
---|
81 | struct passwd *p; |
---|
82 | #ifdef USESHADOW |
---|
83 | struct spwd *sp; |
---|
84 | #endif |
---|
85 | char *crypt (); |
---|
86 | char **userEnv (), **systemEnv (), **parseArgs (); |
---|
87 | char *shell, *home; |
---|
88 | char **argv; |
---|
89 | char *msg, *dologin(), c; |
---|
90 | SIGVAL (*oldsig)(), CatchChild(); |
---|
91 | int i; |
---|
92 | |
---|
93 | Debug ("Verify %s ...\n", greet->name); |
---|
94 | |
---|
95 | /* Get a console running displaying stdout & stderr |
---|
96 | * through a pty. |
---|
97 | */ |
---|
98 | if (console == 0) { |
---|
99 | #ifndef _AIX |
---|
100 | /* choose a pty */ |
---|
101 | strcpy(consoletty, "/dev/ptyp0"); |
---|
102 | for (c = 'p'; c <= 's'; c++) { |
---|
103 | consoletty[8] = c; |
---|
104 | for (i = 0; i < 16; i++) { |
---|
105 | consoletty[9] = "0123456789abcdef"[i]; |
---|
106 | console = open(consoletty, O_RDONLY, 0); |
---|
107 | if (console >= 0) break; |
---|
108 | } |
---|
109 | if (console >= 0) break; |
---|
110 | } |
---|
111 | consoletty[5] = 't'; |
---|
112 | #else /* _AIX */ |
---|
113 | console = open("/dev/ptc", O_RDONLY, 0); |
---|
114 | strcpy(consoletty, ttyname(console)); |
---|
115 | #endif /* _AIX */ |
---|
116 | dup2(console, 0); |
---|
117 | if (fork() == 0) { |
---|
118 | execlp("/etc/athena/console", "console", "-f", |
---|
119 | "/etc/athena/login/Console", "-display", |
---|
120 | d->name, NULL); |
---|
121 | exit(0); |
---|
122 | } |
---|
123 | console = open(consoletty, O_RDWR, 0); |
---|
124 | Debug ("got console %d\n", console); |
---|
125 | dup2(console, 1); |
---|
126 | dup2(console, 2); |
---|
127 | } |
---|
128 | Debug ("Console started\n"); |
---|
129 | oldsig = signal(SIGCHLD, CatchChild); |
---|
130 | |
---|
131 | if (!greet->string || (i = atoi(greet->string)) == 0) |
---|
132 | i = 1; |
---|
133 | |
---|
134 | setenv("PATH", defaultpath, 1); |
---|
135 | msg = dologin(greet->name, greet->password, i, |
---|
136 | "/etc/athena/login/Xsession", &consoletty[5], |
---|
137 | "/etc/athena/login/Xsession", d->name, verify); |
---|
138 | signal(SIGCHLD, oldsig); |
---|
139 | if (msg) { |
---|
140 | printf("%s\n", msg); |
---|
141 | Debug ("dologin returned %s\n", msg); |
---|
142 | return(0); |
---|
143 | } else { |
---|
144 | static char home[256]; |
---|
145 | sprintf(home, "/mit/%s", greet->name); |
---|
146 | Debug ("dologin was successful\n"); |
---|
147 | verify->systemEnviron = systemEnv (d, greet->name, home); |
---|
148 | Debug ("user environment:\n"); |
---|
149 | printEnv (verify->userEnviron); |
---|
150 | Debug ("system environment:\n"); |
---|
151 | printEnv (verify->systemEnviron); |
---|
152 | Debug ("end of environments\n"); |
---|
153 | return(1); |
---|
154 | } |
---|
155 | /* NOTREACHED */ |
---|
156 | p = getpwnam (greet->name); |
---|
157 | if (!p || strlen (greet->name) == 0) |
---|
158 | p = &joeblow; |
---|
159 | #ifdef USESHADOW |
---|
160 | sp = getspnam(greet->name); |
---|
161 | if (sp == NULL) { |
---|
162 | sp = &spjoeblow; |
---|
163 | Debug ("getspnam() failed. Are you root?\n"); |
---|
164 | } |
---|
165 | endspent(); |
---|
166 | |
---|
167 | if (strcmp (crypt (greet->password, sp->sp_pwdp), sp->sp_pwdp)) |
---|
168 | #else |
---|
169 | if (strcmp (crypt (greet->password, p->pw_passwd), p->pw_passwd)) |
---|
170 | #endif |
---|
171 | { |
---|
172 | Debug ("verify failed\n"); |
---|
173 | bzero(greet->password, strlen(greet->password)); |
---|
174 | return 0; |
---|
175 | } |
---|
176 | Debug ("verify succeeded\n"); |
---|
177 | /* bzero(greet->password, strlen(greet->password)); */ |
---|
178 | verify->uid = p->pw_uid; |
---|
179 | #ifdef NGROUPS_MAX |
---|
180 | getGroups (greet->name, verify, p->pw_gid); |
---|
181 | #else |
---|
182 | verify->gid = p->pw_gid; |
---|
183 | #endif |
---|
184 | home = p->pw_dir; |
---|
185 | shell = p->pw_shell; |
---|
186 | argv = 0; |
---|
187 | if (d->session) |
---|
188 | argv = parseArgs (argv, d->session); |
---|
189 | if (greet->string) |
---|
190 | argv = parseArgs (argv, greet->string); |
---|
191 | if (!argv) |
---|
192 | argv = parseArgs (argv, "xsession"); |
---|
193 | verify->argv = argv; |
---|
194 | verify->userEnviron = userEnv (d, p->pw_uid == 0, |
---|
195 | greet->name, home, shell); |
---|
196 | Debug ("user environment:\n"); |
---|
197 | printEnv (verify->userEnviron); |
---|
198 | verify->systemEnviron = systemEnv (d, greet->name, home); |
---|
199 | Debug ("system environment:\n"); |
---|
200 | printEnv (verify->systemEnviron); |
---|
201 | Debug ("end of environments\n"); |
---|
202 | return 1; |
---|
203 | } |
---|
204 | |
---|
205 | |
---|
206 | UnVerify(d, verify) |
---|
207 | struct display *d; |
---|
208 | struct verify_info *verify; |
---|
209 | { |
---|
210 | int found, file; |
---|
211 | char login[9]; |
---|
212 | struct utmp utmp; |
---|
213 | |
---|
214 | Debug ("Cleaning up on logout\n"); |
---|
215 | |
---|
216 | found = 0; |
---|
217 | if ((file = open("/etc/utmp", O_RDWR, 0)) > 0) { |
---|
218 | while (read(file, (char *)&utmp, sizeof(utmp)) > 0) { |
---|
219 | if (!strncmp(utmp.ut_line, &consoletty[5], sizeof(utmp.ut_line)) |
---|
220 | #ifdef _AIX |
---|
221 | && (utmp.ut_type == USER_PROCESS) |
---|
222 | #endif |
---|
223 | ) { |
---|
224 | strncpy(login, utmp.ut_name, 8); |
---|
225 | login[8] = 0; |
---|
226 | if (utmp.ut_name[0] != '\0') { |
---|
227 | strncpy(utmp.ut_name, "", sizeof(utmp.ut_name)); |
---|
228 | #ifdef _AIX |
---|
229 | utmp.ut_type = EMPTY; |
---|
230 | #endif |
---|
231 | lseek(file, (long) -sizeof(utmp), L_INCR); |
---|
232 | write(file, (char *) &utmp, sizeof(utmp)); |
---|
233 | found = 1; |
---|
234 | } |
---|
235 | break; |
---|
236 | } |
---|
237 | } |
---|
238 | close(file); |
---|
239 | } |
---|
240 | if (found) { |
---|
241 | if ((file = open("/usr/adm/wtmp", O_WRONLY|O_APPEND, 0644)) >= 0) { |
---|
242 | strncpy(utmp.ut_line, &consoletty[5], sizeof(utmp.ut_line)); |
---|
243 | strncpy(utmp.ut_name, "", sizeof(utmp.ut_name)); |
---|
244 | strncpy(utmp.ut_host, "", sizeof(utmp.ut_host)); |
---|
245 | time(&utmp.ut_time); |
---|
246 | write(file, (char *) &utmp, sizeof(utmp)); |
---|
247 | close(file); |
---|
248 | } |
---|
249 | } |
---|
250 | #ifdef DEBUG |
---|
251 | if (found) |
---|
252 | syslog(3, "Unverify called and entry removed from utmp, tty %s", |
---|
253 | &consoletty[5]); |
---|
254 | else |
---|
255 | syslog(3, "Unverify called and entry NOT removed from utmp, tty %s", |
---|
256 | &consoletty[5]); |
---|
257 | #endif |
---|
258 | cleanup(NULL); |
---|
259 | } |
---|
260 | |
---|
261 | |
---|
262 | extern char **setEnv (); |
---|
263 | |
---|
264 | char ** |
---|
265 | defaultEnv () |
---|
266 | { |
---|
267 | char **env, **exp, *value; |
---|
268 | |
---|
269 | env = 0; |
---|
270 | for (exp = exportList; exp && *exp; ++exp) |
---|
271 | { |
---|
272 | value = getenv (*exp); |
---|
273 | if (value) |
---|
274 | env = setEnv (env, *exp, value); |
---|
275 | } |
---|
276 | return env; |
---|
277 | } |
---|
278 | |
---|
279 | char ** |
---|
280 | userEnv (d, useSystemPath, user, home, shell) |
---|
281 | struct display *d; |
---|
282 | int useSystemPath; |
---|
283 | char *user, *home, *shell; |
---|
284 | { |
---|
285 | char **env; |
---|
286 | char **envvar; |
---|
287 | char *str; |
---|
288 | |
---|
289 | env = defaultEnv (); |
---|
290 | env = setEnv (env, "DISPLAY", d->name); |
---|
291 | env = setEnv (env, "HOME", home); |
---|
292 | env = setEnv (env, "USER", user); |
---|
293 | env = setEnv (env, "PATH", useSystemPath ? d->systemPath : d->userPath); |
---|
294 | env = setEnv (env, "SHELL", shell); |
---|
295 | for (envvar = envvars; *envvar; envvar++) |
---|
296 | { |
---|
297 | if (str = getenv(*envvar)) |
---|
298 | env = setEnv (env, *envvar, str); |
---|
299 | } |
---|
300 | return env; |
---|
301 | } |
---|
302 | |
---|
303 | char ** |
---|
304 | systemEnv (d, user, home) |
---|
305 | struct display *d; |
---|
306 | char *user, *home; |
---|
307 | { |
---|
308 | char **env; |
---|
309 | |
---|
310 | env = defaultEnv (); |
---|
311 | env = setEnv (env, "DISPLAY", d->name); |
---|
312 | if (home) |
---|
313 | env = setEnv (env, "HOME", home); |
---|
314 | if (user) |
---|
315 | env = setEnv (env, "USER", user); |
---|
316 | env = setEnv (env, "PATH", d->systemPath); |
---|
317 | env = setEnv (env, "SHELL", d->systemShell); |
---|
318 | if (d->authFile) |
---|
319 | env = setEnv (env, "XAUTHORITY", d->authFile); |
---|
320 | return env; |
---|
321 | } |
---|
322 | |
---|
323 | #ifdef NGROUPS_MAX |
---|
324 | groupMember (name, members) |
---|
325 | char *name; |
---|
326 | char **members; |
---|
327 | { |
---|
328 | while (*members) { |
---|
329 | if (!strcmp (name, *members)) |
---|
330 | return 1; |
---|
331 | ++members; |
---|
332 | } |
---|
333 | return 0; |
---|
334 | } |
---|
335 | |
---|
336 | getGroups (name, verify, gid) |
---|
337 | char *name; |
---|
338 | struct verify_info *verify; |
---|
339 | int gid; |
---|
340 | { |
---|
341 | int ngroups; |
---|
342 | struct group *g; |
---|
343 | int i; |
---|
344 | |
---|
345 | ngroups = 0; |
---|
346 | verify->groups[ngroups++] = gid; |
---|
347 | setgrent (); |
---|
348 | /* SUPPRESS 560 */ |
---|
349 | while (g = getgrent()) { |
---|
350 | /* |
---|
351 | * make the list unique |
---|
352 | */ |
---|
353 | for (i = 0; i < ngroups; i++) |
---|
354 | if (verify->groups[i] == g->gr_gid) |
---|
355 | break; |
---|
356 | if (i != ngroups) |
---|
357 | continue; |
---|
358 | if (groupMember (name, g->gr_mem)) { |
---|
359 | if (ngroups >= NGROUPS_MAX) |
---|
360 | LogError ("%s belongs to more than %d groups, %s ignored\n", |
---|
361 | name, NGROUPS_MAX, g->gr_name); |
---|
362 | else |
---|
363 | verify->groups[ngroups++] = g->gr_gid; |
---|
364 | } |
---|
365 | } |
---|
366 | verify->ngroups = ngroups; |
---|
367 | endgrent (); |
---|
368 | } |
---|
369 | #endif |
---|
370 | |
---|
371 | SIGVAL CatchChild() |
---|
372 | { |
---|
373 | int pid; |
---|
374 | waitType status; |
---|
375 | char *number(); |
---|
376 | |
---|
377 | /* Necessary on the rios- it sets the signal handler to SIG_DFL */ |
---|
378 | /* during the execution of a signal handler */ |
---|
379 | signal(SIGCHLD,CatchChild); |
---|
380 | pid = wait3(&status, WNOHANG, 0); |
---|
381 | |
---|
382 | if (pid == attach_pid) { |
---|
383 | attach_state = waitCode(status); |
---|
384 | } else if (pid == attachhelp_pid) { |
---|
385 | attachhelp_state = waitCode(status); |
---|
386 | } else if (pid == quota_pid) { |
---|
387 | /* don't need to do anything here */ |
---|
388 | } else |
---|
389 | fprintf(stderr, "XLogin: child %d exited with status %d\n", |
---|
390 | pid, waitCode(status)); |
---|
391 | } |
---|
392 | |
---|
393 | char *lose(msg) |
---|
394 | char *msg; |
---|
395 | { |
---|
396 | fprintf(stderr, "%s\n", msg); |
---|
397 | exit(1); |
---|
398 | } |
---|
399 | |
---|
400 | prompt_user(msg, noproc) |
---|
401 | char *msg; |
---|
402 | void (*noproc)(); |
---|
403 | { |
---|
404 | printf("%s (assuming YES)\n", msg); |
---|
405 | /* (*noproc)(); */ |
---|
406 | return; |
---|
407 | } |
---|