source: trunk/athena/etc/xdm/xdm/verify.c @ 6705

Revision 6705, 9.3 KB checked in by cfields, 31 years ago (diff)
Fixed a path problem with verify calling xlogin's dologin().
Line 
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
38char *getenv();
39#endif
40#include <signal.h>
41#ifdef _POSIX_SOURCE
42#include <unistd.h>
43#endif
44
45struct passwd joeblow = {
46        "Nobody", "***************"
47};
48
49#ifdef USESHADOW
50struct spwd spjoeblow = {
51        "Nobody", "**************"
52};
53#endif
54
55static 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
71int attach_pid, attach_state, attachhelp_pid, attachhelp_state, quota_pid;
72static int      console = 0;
73static char     consoletty[10];
74extern char     *defaultpath;
75
76Verify (d, greet, verify)
77struct display          *d;
78struct greet_info       *greet;
79struct 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
206UnVerify(d, verify)
207struct display          *d;
208struct 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
262extern char **setEnv ();
263
264char **
265defaultEnv ()
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
279char **
280userEnv (d, useSystemPath, user, home, shell)
281struct display  *d;
282int     useSystemPath;
283char    *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
303char **
304systemEnv (d, user, home)
305struct display  *d;
306char    *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
324groupMember (name, members)
325char    *name;
326char    **members;
327{
328        while (*members) {
329                if (!strcmp (name, *members))
330                        return 1;
331                ++members;
332        }
333        return 0;
334}
335
336getGroups (name, verify, gid)
337char                    *name;
338struct verify_info      *verify;
339int                     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
371SIGVAL 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
393char *lose(msg)
394char *msg;
395{
396    fprintf(stderr, "%s\n", msg);
397    exit(1);
398}
399
400prompt_user(msg, noproc)
401char *msg;
402void (*noproc)();
403{
404    printf("%s (assuming YES)\n", msg);
405    /* (*noproc)(); */
406    return;
407}
Note: See TracBrowser for help on using the repository browser.