void WDMRedirectStderr(int level) { int errpipe[2]; int exitstatus; if (pipe(errpipe) == -1) WDMError("cannot create pipe. " "all stderr messages will go to stderr\n"); childpid = fork(); if (childpid == -1) { WDMError("fork failed. " "all stderr messages will go to stderr\n"); close(errpipe[0]); close(errpipe[1]); } else if (childpid != 0) { /* parent, will read all messages from stderr and * redirect it to log */ Signal(SIGTERM, WDMRedirectSignals); Signal(SIGINT, WDMRedirectSignals); Signal(SIGHUP, WDMRedirectSignals); close(errpipe[1]); exitstatus = WDMRedirectFileToLog(WDM_LEVEL_ERROR, childpid, errpipe[0]); close(errpipe[0]); exit(exitstatus); } /* child, will close read end of pipe and dup2 * write end of pipe to stderr */ close(errpipe[0]); RegisterCloseOnFork(errpipe[1]); dup2(errpipe[1], 2); }
void SecureDisplay(struct display *d, Display * dpy) { WDMDebug("SecureDisplay %s\n", d->name); (void)Signal(SIGALRM, syncTimeout); if (Setjmp(syncJump)) { WDMError("WARNING: display %s could not be secured\n", d->name); SessionExit(d, RESERVER_DISPLAY, FALSE); } (void)alarm((unsigned)d->grabTimeout); WDMDebug("Before XGrabServer %s\n", d->name); XGrabServer(dpy); if (XGrabKeyboard(dpy, DefaultRootWindow(dpy), True, GrabModeAsync, GrabModeAsync, CurrentTime) != GrabSuccess) { (void)alarm(0); (void)Signal(SIGALRM, SIG_DFL); WDMError("WARNING: keyboard on display %s could not be secured\n", d->name); SessionExit(d, RESERVER_DISPLAY, FALSE); } WDMDebug("XGrabKeyboard succeeded %s\n", d->name); (void)alarm(0); (void)Signal(SIGALRM, SIG_DFL); pseudoReset(dpy); if (!d->grabServer) { XUngrabServer(dpy); XSync(dpy, 0); } WDMDebug("done secure %s\n", d->name); }
static int StartServerOnce(struct display *d) { char **f; char **argv; char arg[1024]; int pid; WDMDebug("StartServer for %s\n", d->name); receivedUsr1 = 0; (void)Signal(SIGUSR1, CatchUsr1); argv = d->argv; switch (pid = fork()) { case 0: CleanUpChild(); #ifdef XDMCP /* The chooser socket is not closed by CleanUpChild() */ DestroyWellKnownSockets(); #endif if (d->authFile) { sprintf(arg, "-auth %s", d->authFile); argv = parseArgs(argv, arg); } if (!argv) { WDMError("StartServer: no arguments\n"); sleep((unsigned)d->openDelay); exit(UNMANAGE_DISPLAY); } for (f = argv; *f; f++) WDMDebug("'%s' ", *f); WDMDebug("\n"); /* * give the server SIGUSR1 ignored, * it will notice that and send SIGUSR1 * when ready */ (void)Signal(SIGUSR1, SIG_IGN); (void)execv(argv[0], argv); WDMError("server %s cannot be executed\n", argv[0]); sleep((unsigned)d->openDelay); exit(REMANAGE_DISPLAY); case -1: WDMError("fork failed, sleeping\n"); return 0; default: break; } WDMDebug("Server Started %d\n", pid); d->serverPid = pid; if (serverPause((unsigned)d->openDelay, pid)) return FALSE; return TRUE; }
void SessionExit(struct display *d, int status, int removeAuth) { #ifdef USE_PAM pam_handle_t *pamh = thepamh(); if (pamh) { /* shutdown PAM session */ if (pam_setcred(pamh, PAM_DELETE_CRED) != PAM_SUCCESS) WDMError("pam_setcred(DELETE_CRED) failed, errno=%d", errno); pam_close_session(pamh, 0); pam_end(pamh, PAM_SUCCESS); pamh = NULL; } #endif /* make sure the server gets reset after the session is over */ if (d->serverPid >= 2 && d->resetSignal) kill(d->serverPid, d->resetSignal); else ResetServer(d); if (removeAuth) { setgid(verify.gid); setuid(verify.uid); RemoveUserAuthorization(d, &verify); } WDMDebug("Display %s exiting with status %d\n", d->name, status); exit(status); }
int WDMRedirectFileToLog(int level, pid_t pid, int fd) { fd_set set; int status; struct timeval tv; char buf[1024]; int n; WDMDebug("logger started\n"); while (waitpid(pid, &status, WNOHANG) == 0) { FD_ZERO(&set); FD_SET(fd, &set); tv.tv_sec = 1; tv.tv_usec = 0; if (select(fd + 1, &set, NULL, NULL, &tv) > 0) { n = read(fd, buf, sizeof(buf)); if (n == -1) WDMError("error reading form pipe(stderr)\n"); WDMBufferedLogMessages(level, buf, n); } } WDMBufferedLogMessages(level, "\n", 1); WDMDebug("logger stopped\n"); return WEXITSTATUS(status); }
static void AbortClient(int pid) { int sig = SIGTERM; volatile int i; int retId; for (i = 0; i < 4; i++) { if (killpg(pid, sig) == -1) { switch (errno) { case EPERM: WDMError("wdm can't kill client\n"); case EINVAL: case ESRCH: return; } } if (!Setjmp(tenaciousClient)) { (void)Signal(SIGALRM, waitAbort); (void)alarm((unsigned)10); retId = wait((waitType *) 0); (void)alarm((unsigned)0); (void)Signal(SIGALRM, SIG_DFL); if (retId == pid) break; } else (void)Signal(SIGALRM, SIG_DFL); sig = SIGKILL; } }
WDMLoginConfig * LoadConfiguration(char *configFile) { char *filename = configFile ? configFile : DEF_WDMLOGIN_CONFIG; WMPropList *db; WDMLoginConfig *config = NULL; db = WMReadPropListFromFile(filename); if(db == NULL) WDMError("Cannot open config file. Using builtin defaults\n"); if(!WDMCheckPLDictionary(db, &wdmLogin_config, &config)) WDMError("Error parsing config file. Using builtin defaults\n"); if(db) WMReleasePropList(db); return config; }
static void ScanServers(void) { char lineBuf[10240]; int len; FILE *serversFile; struct stat statb; static DisplayType acceptableTypes[] = { {Local, Permanent, FromFile}, {Foreign, Permanent, FromFile}, }; #define NumTypes (sizeof (acceptableTypes) / sizeof (acceptableTypes[0])) if (servers[0] == '/') { serversFile = fopen(servers, "r"); if (serversFile == NULL) { WDMError("cannot access servers file %s\n", servers); return; } if (ServersModTime == 0) { fstat(fileno(serversFile), &statb); ServersModTime = statb.st_mtime; } while (fgets(lineBuf, sizeof(lineBuf) - 1, serversFile)) { len = strlen(lineBuf); if (lineBuf[len - 1] == '\n') lineBuf[len - 1] = '\0'; ParseDisplay(lineBuf, acceptableTypes, NumTypes); } fclose(serversFile); } else { ParseDisplay(servers, acceptableTypes, NumTypes); } }
void BecomeOrphan(void) { Pid_t child_id; /* * fork so that the process goes into the background automatically. Also * has a nice side effect of having the child process get inherited by * init (pid 1). * Separate the child into its own process group before the parent * exits. This eliminates the possibility that the child might get * killed when the init script that's running wdm exits. */ child_id = fork(); switch (child_id) { case 0: /* child */ break; case -1: /* error */ WDMError("daemon fork failed, errno = %d\n", errno); break; default: /* parent */ exit(0); } }
void pseudoReset (Display *dpy) { Window root; int screen; if (Setjmp (resetJmp)) { WDMError("pseudoReset timeout\n"); } else { (void) Signal (SIGALRM, abortReset); (void) alarm (30); XSetErrorHandler (ignoreErrors); for (screen = 0; screen < ScreenCount (dpy); screen++) { WDMDebug("pseudoReset screen %d\n", screen); root = RootWindow (dpy, screen); killWindows (dpy, root); } WDMDebug("before XSync\n"); XSync (dpy, False); (void) alarm (0); } Signal (SIGALRM, SIG_DFL); XSetErrorHandler ((XErrorHandler)0 ); WDMDebug("pseudoReset done\n"); }
static int ErrorHandler(Display * dpy, XErrorEvent * event) { WDMError("X error\n"); if (XmuPrintDefaultErrorMessage(dpy, event, stderr) == 0) return 0; exit(UNMANAGE_DISPLAY); /*NOTREACHED*/}
static int StorePid(void) { int oldpid; if (pidFile[0] != '\0') { pidFd = open(pidFile, O_RDWR); if (pidFd == -1 && errno == ENOENT) pidFd = open(pidFile, O_RDWR | O_CREAT, 0666); if (pidFd == -1 || !(pidFilePtr = fdopen(pidFd, "r+"))) { WDMError("process-id file %s cannot be opened\n", pidFile); return -1; } if (fscanf(pidFilePtr, "%d\n", &oldpid) != 1) oldpid = -1; fseek(pidFilePtr, 0l, 0); if (lockPidFile.i) { #ifdef F_SETLK #ifndef SEEK_SET #define SEEK_SET 0 #endif struct flock lock_data; lock_data.l_type = F_WRLCK; lock_data.l_whence = SEEK_SET; lock_data.l_start = lock_data.l_len = 0; if (fcntl(pidFd, F_SETLK, &lock_data) == -1) { if (errno == EAGAIN) return oldpid; else return -1; } #else #ifdef LOCK_EX if (flock(pidFd, LOCK_EX | LOCK_NB) == -1) { if (errno == EWOULDBLOCK) return oldpid; else return -1; } #else if (lockf(pidFd, F_TLOCK, 0) == -1) { if (errno == EACCES) return oldpid; else return -1; } #endif #endif } fprintf(pidFilePtr, "%5ld\n", (long)getpid()); (void)fflush(pidFilePtr); RegisterCloseOnFork(pidFd); } return 0; }
int WaitForServer(struct display *d) { static int i; for (i = 0; i < (d->openRepeat > 0 ? d->openRepeat : 1); i++) { (void)Signal(SIGALRM, abortOpen); (void)alarm((unsigned)d->openTimeout); if (!Setjmp(openAbort)) { WDMDebug("Before XOpenDisplay(%s)\n", d->name); errno = 0; (void)XSetIOErrorHandler(openErrorHandler); dpy = XOpenDisplay(d->name); (void)alarm((unsigned)0); (void)Signal(SIGALRM, SIG_DFL); (void)XSetIOErrorHandler((int (*)(Display *))0); WDMDebug("After XOpenDisplay(%s)\n", d->name); if (dpy) { #ifdef XDMCP if (d->displayType.location == Foreign) GetRemoteAddress(d, ConnectionNumber(dpy)); #endif RegisterCloseOnFork(ConnectionNumber(dpy)); (void)fcntl(ConnectionNumber(dpy), F_SETFD, 0); return 1; } else { WDMDebug("OpenDisplay failed %d (%s) on \"%s\"\n", errno, strerror(errno), d->name); } WDMDebug("waiting for server to start %d\n", i); sleep((unsigned)d->openDelay); } else { WDMDebug("hung in open, aborting\n"); WDMError("Hung in XOpenDisplay(%s), aborting\n", d->name); (void)Signal(SIGALRM, SIG_DFL); break; } } WDMDebug("giving up on server\n"); WDMError("server open failed for %s, giving up\n", d->name); return 0; }
static void guaranteed_read(int fd, char *buf, size_t count) { int bytes_read; if (count == 0) { return; } while ((bytes_read = read(fd, buf, count)) > 0) { count -= bytes_read; buf += bytes_read; if (count == 0) { return; } } WDMError("Greet: guarenteed_read error, UNMANAGE DISPLAY\n"); WDMError("Greet: pipe read error with %s\n", wdmLogin); SessionExit(Save_d, RESERVER_DISPLAY, FALSE); /* this exits */ exit(UNMANAGE_DISPLAY); /* should not happen */ }
static int runAndWait(char **args, char **environ) { int pid; waitType result; switch (pid = fork()) { case 0: CleanUpChild(); execute(args, environ); WDMError("can't execute \"%s\" (err %d)\n", args[0], errno); exit(1); case -1: WDMDebug("fork failed\n"); WDMError("can't fork to execute \"%s\" (err %d)\n", args[0], errno); return 1; default: while (wait(&result) != pid) /* SUPPRESS 530 */ ; break; } return waitVal(result); }
static int Greet(struct display *d, struct greet_info *greet) { int code = 0, done = 0, extension_code = 0; readstring(pipe_filedes[0], name); /* username */ readstring(pipe_filedes[0], password); xsessionArg[0] = '\0'; while (!done) { extension_code = readuc(pipe_filedes[0]); switch (extension_code) { case 0: /*end of data */ done = 1; break; case 1: /*xsession parameter */ readstring(pipe_filedes[0], xsessionArg); break; case 2: /*reboot */ readstring(pipe_filedes[0], exitArg); code = 2; break; case 3: /*halt */ readstring(pipe_filedes[0], exitArg); code = 3; break; case 4: /*exit */ readstring(pipe_filedes[0], exitArg); code = 4; break; default: /*???? */ WDMError("Bad extension code from external program: %i\n", code); exit(RESERVER_DISPLAY); break; } } greet->name = name; greet->password = password; if (xsessionArg[0] == '\0') greet->string = NULL; else greet->string = xsessionArg; return code; }
static int serverPause(unsigned t, int serverPid) { int pid; serverPauseRet = 0; if (!Setjmp(pauseAbort)) { (void)Signal(SIGALRM, serverPauseAbort); (void)Signal(SIGUSR1, serverPauseUsr1); #ifdef SYSV if (receivedUsr1) (void)alarm((unsigned)1); else (void)alarm(t); #else if (!receivedUsr1) (void)alarm(t); else WDMDebug("Already received USR1\n"); #endif for (;;) { if (!receivedUsr1) pid = wait((waitType *) 0); else pid = waitpid(-1, (int *)0, WNOHANG); if (pid == serverPid || (pid == -1 && errno == ECHILD)) { WDMDebug("Server dead\n"); serverPauseRet = 1; break; } if (pid == 0) { WDMDebug("Server alive and kicking\n"); break; } } } (void)alarm((unsigned)0); (void)Signal(SIGALRM, SIG_DFL); (void)Signal(SIGUSR1, CatchUsr1); if (serverPauseRet) { WDMDebug("Server died\n"); WDMError("server unexpectedly died\n"); } return serverPauseRet; }
void WaitForChild(void) { int pid; struct display *d; waitType status; sigset_t mask, omask; sigemptyset(&mask); sigaddset(&mask, SIGCHLD); sigaddset(&mask, SIGHUP); sigprocmask(SIG_BLOCK, &mask, &omask); WDMDebug("signals blocked\n"); if (!ChildReady && !Rescan) sigsuspend(&omask); ChildReady = 0; sigprocmask(SIG_SETMASK, &omask, (sigset_t *) NULL); while ((pid = waitpid(-1, &status, WNOHANG)) > 0) { WDMDebug("Manager wait returns pid: %d sig %d core %d code %d\n", pid, waitSig(status), waitCore(status), waitCode(status)); if (autoRescan.i) RescanIfMod(); /* SUPPRESS 560 */ if ((d = FindDisplayByPid(pid))) { d->pid = -1; switch (waitVal(status)) { case UNMANAGE_DISPLAY: WDMDebug("Display exited with UNMANAGE_DISPLAY\n"); StopDisplay(d); break; case OBEYSESS_DISPLAY: d->startTries = 0; WDMDebug("Display exited with OBEYSESS_DISPLAY\n"); if (d->displayType.lifetime != Permanent || d->status == zombie) StopDisplay(d); else RestartDisplay(d, FALSE); break; default: WDMDebug("Display exited with unknown status %d\n", waitVal(status)); WDMError("Unknown session exit code %d from process %d\n", waitVal(status), pid); StopDisplay(d); break; case OPENFAILED_DISPLAY: WDMDebug("Display exited with OPENFAILED_DISPLAY, try %d of %d\n", d->startTries, d->startAttempts); WDMError("Display %s cannot be opened\n", d->name); /* * no display connection was ever made, tell the * terminal that the open attempt failed */ #ifdef XDMCP if (d->displayType.origin == FromXDMCP) SendFailed(d, "Cannot open display"); #endif if (d->displayType.origin == FromXDMCP || d->status == zombie || ++d->startTries >= d->startAttempts) { WDMError("Display %s is being disabled\n", d->name); StopDisplay(d); } else { RestartDisplay(d, TRUE); } break; case RESERVER_DISPLAY: d->startTries = 0; WDMDebug("Display exited with RESERVER_DISPLAY\n"); if (d->displayType.origin == FromXDMCP || d->status == zombie) StopDisplay(d); else RestartDisplay(d, TRUE); { Time_t Time; time(&Time); WDMDebug("time %i %i\n", (int)Time, (int)d->lastCrash); if (d->lastCrash && ((Time - d->lastCrash) < XDM_BROKEN_INTERVAL)) { WDMDebug("Server crash frequency too high:" " removing display %s\n", d->name); WDMError("Server crash rate too high:" " removing display %s\n", d->name); RemoveDisplay(d); } else d->lastCrash = Time; } break; case waitCompose(SIGTERM, 0, 0): WDMDebug("Display exited on SIGTERM, try %d of %d\n", d->startTries, d->startAttempts); if (d->displayType.origin == FromXDMCP || d->status == zombie || ++d->startTries >= d->startAttempts) { WDMError("Display %s is being disabled\n", d->name); StopDisplay(d); } else RestartDisplay(d, TRUE); break; case REMANAGE_DISPLAY: d->startTries = 0; WDMDebug("Display exited with REMANAGE_DISPLAY\n"); /* * XDMCP will restart the session if the display * requests it */ if (d->displayType.origin == FromXDMCP || d->status == zombie) StopDisplay(d); else RestartDisplay(d, FALSE); break; } } /* SUPPRESS 560 */ else if ((d = FindDisplayByServerPid(pid))) { d->serverPid = -1; switch (d->status) { case zombie: WDMDebug("Zombie server reaped, removing display %s\n", d->name); RemoveDisplay(d); break; case phoenix: WDMDebug("Phoenix server arises, restarting display %s\n", d->name); d->status = notRunning; break; case running: WDMDebug("Server for display %s terminated unexpectedly, status %d %d\n", d->name, waitVal(status), status); WDMError("Server for display %s terminated unexpectedly: %d\n", d->name, waitVal(status)); d->status = notRunning; if (d->pid != -1) { WDMDebug("Terminating session pid %d\n", d->pid); TerminateProcess(d->pid, SIGTERM); } break; case notRunning: WDMDebug("Server exited for notRunning session on display %s\n", d->name); break; } } else { WDMDebug("Unknown child termination, status %d\n", waitVal(status)); } } StartDisplays(); }
void StartDisplay(struct display *d) { int pid; WDMDebug("StartDisplay %s\n", d->name); LoadServerResources(d); if (d->displayType.location == Local) { /* don't bother pinging local displays; we'll * certainly notice when they exit */ d->pingInterval = 0; if (d->authorize) { WDMDebug("SetLocalAuthorization %s, auth %s\n", d->name, d->authNames[0]); SetLocalAuthorization(d); /* * reset the server after writing the authorization information * to make it read the file (for compatibility with old * servers which read auth file only on reset instead of * at first connection) */ if (d->serverPid != -1 && d->resetForAuth && d->resetSignal) kill(d->serverPid, d->resetSignal); } if (d->serverPid == -1 && !StartServer(d)) { WDMError("Server for display %s can't be started, session disabled\n", d->name); RemoveDisplay(d); return; } } else { /* this will only happen when using XDMCP */ if (d->authorizations) SaveServerAuthorizations(d, d->authorizations, d->authNum); } pid = fork(); switch (pid) { case 0: CleanUpChild(); LoadSessionResources(d); SetAuthorization(d); (void)Signal(SIGPIPE, SIG_IGN); (void)Signal(SIGHUP, SIG_IGN); if (!WaitForServer(d)) exit(OPENFAILED_DISPLAY); #ifdef XDMCP if (d->useChooser) RunChooser(d); else #endif ManageSession(d); exit(REMANAGE_DISPLAY); case -1: break; default: WDMDebug("pid: %d\n", pid); d->pid = pid; d->status = running; /* checking a predeclared X resource DisplayManager*wdmSequentialXServerLaunch here */ if (wdmSequentialXServerLaunch) WaitForServer(d); break; } }
static int InitGreet(struct display *d) { int pid; WDMDebug("Greet display=%s\n", d->name); pipe(pipe_filedes); pid = fork(); if (pid == -1) { /* error */ WDMError("Greet cannot fork\n"); exit(RESERVER_DISPLAY); } if (pid == 0) { /* child */ char **env = NULL; char *argv[20]; int argc = 1; /* argc = 0 is for command itself */ close(pipe_filedes[0]); fcntl(pipe_filedes[1], F_SETFD, 0); /* Reset close-on-exec (just in case) */ env = (char **)systemEnv(d, (char *)NULL, FAKEHOME); if (*wdmLocale) env = WDMSetEnv(env, "LANG", wdmLocale); if (*wdmCursorTheme) env = WDMSetEnv(env, "XCURSOR_THEME", wdmCursorTheme); if ((argv[0] = strrchr(wdmLogin, '/')) == NULL) argv[0] = wdmLogin; else argv[0]++; argv[argc++] = wstrconcat("-d", d->name); if (*wdmWm) argv[argc++] = wstrconcat("-w", wdmWm); if (*wdmLogo) argv[argc++] = wstrconcat("-l", wdmLogo); if (*wdmHelpFile) argv[argc++] = wstrconcat("-h", wdmHelpFile); if (*wdmDefaultUser) argv[argc++] = "-u"; if (*wdmBg) argv[argc++] = wstrconcat("-b", wdmBg); if (*wdmLoginConfig) argv[argc++] = wstrconcat("-c", wdmLoginConfig); if (wdmAnimations) argv[argc++] = "-a"; if (wdmXineramaHead) { argv[argc] = wmalloc(25); /* much more than length of 64bit integer converted to string, but it still a hack */ sprintf(argv[argc++], "-x%i", wdmXineramaHead); } argv[argc] = wmalloc(25); sprintf(argv[argc++], "-f%i", pipe_filedes[1]); argv[argc++] = NULL; execve(wdmLogin, argv, env); WDMError("Greet cannot exec %s\n", wdmLogin); exit(RESERVER_DISPLAY); } close(pipe_filedes[1]); RegisterCloseOnFork(pipe_filedes[0]); return pid; }
greet_user_rtn GreetUser(struct display * d, Display ** dpy, struct verify_info * verify, struct greet_info * greet) { int flag; int pid; int code; Save_d = d; /* hopefully, this is OK */ *dpy = XOpenDisplay(d->name); /* make sure we have the display */ /* * Run the setup script - note this usually will not work when * the server is grabbed, so we don't even bother trying. */ if (!d->grabServer) SetupDisplay(d); if (!*dpy) { WDMError("Cannot reopen display %s for greet window\n", d->name); exit(RESERVER_DISPLAY); } pid = InitGreet(d); /* fork and exec the external program */ for (;;) { /* * Greet user, requesting name/password */ code = Greet(d, greet); WDMDebug("Greet greet done: %s, pwlen=%i\n", name, strlen(password)); if (code != 0) { WDMDebug("Greet: exit code=%i, %s\n", code, exitArg); if (wdmVerify || wdmRoot) { flag = False; if (Verify(d, greet, verify)) flag = True; if (wdmRoot && (strcmp(greet->name, "root") != 0)) flag = False; } else flag = True; if (flag == True) { switch (code) { case 2: /* reboot */ CloseGreet(pid); WDMInfo("reboot(%s) by %s\n", exitArg, name); system(wdmReboot); SessionExit(d, UNMANAGE_DISPLAY, FALSE); break; case 3: /* halt */ CloseGreet(pid); WDMInfo("halt(%s) by %s\n", exitArg, name); system(wdmHalt); SessionExit(d, UNMANAGE_DISPLAY, FALSE); break; case 4: /* exit */ CloseGreet(pid); WDMDebug("UNMANAGE_DISPLAY\n"); WDMInfo("%s exit(%s) by %s\n", PACKAGE_NAME, exitArg, name); #if 0 SessionExit(d, UNMANAGE_DISPLAY, FALSE); #else WDMDebug("Killing parent process %d\n", getppid()); kill(getppid(), SIGINT); #endif break; } } else { kill(pid, SIGUSR1); /* Verify failed */ } } else { /* * Verify user */ if ((!*greet->name) && *wdmDefaultUser) { greet->name = wdmDefaultUser; greet->password = wdmDefaultPasswd; } if (Verify(d, greet, verify)) break; else kill(pid, SIGUSR1); /* Verify failed */ } } DeleteXloginResources(d, *dpy); CloseGreet(pid); WDMDebug("Greet loop finished\n"); /* * Run system-wide initialization file */ if (source(verify->systemEnviron, d->startup) != 0) { WDMDebug("Startup program %s exited with non-zero status\n", d->startup); SessionExit(d, OBEYSESS_DISPLAY, FALSE); } return Greet_Success; }
static int IOErrorHandler(Display * dpy) { WDMError("fatal IO error %d (%s)\n", errno, _SysErrorMsg(errno)); exit(RESERVER_DISPLAY); /*NOTREACHED*/ return 0; }
static int openErrorHandler(Display * dpy) { WDMError("IO Error in XOpenDisplay\n"); exit(OPENFAILED_DISPLAY); /*NOTREACHED*/ return (0); }
static Bool StartClient(struct verify_info *verify, struct display *d, int *pidp, char *name, char *passwd #ifdef WITH_CONSOLE_KIT , char *ck_session_cookie #endif ) { char **f; const char *home; char *failsafeArgv[2]; int pid; #ifdef HAS_SETUSERCONTEXT struct passwd *pwd; #endif #ifdef USE_PAM pam_handle_t *pamh = thepamh(); #endif if (verify->argv) { WDMDebug("StartSession %s: ", verify->argv[0]); for (f = verify->argv; *f; f++) WDMDebug("%s ", *f); WDMDebug("; "); } if (verify->userEnviron) { for (f = verify->userEnviron; *f; f++) WDMDebug("%s ", *f); WDMDebug("\n"); } /* Do system-dependent login setup here */ if (setgid(verify->gid) < 0) { WDMError("setgid %d (user \"%s\") failed, errno=%d\n", verify->gid, name, errno); return (0); } #if defined(BSD) && (BSD >= 199103) if (setlogin(name) < 0) { WDMError("setlogin for \"%s\" failed, errno=%d", name, errno); return (0); } #endif if (initgroups(name, verify->gid) < 0) { WDMError("initgroups for \"%s\" failed, errno=%d\n", name, errno); return (0); } #ifdef USE_PAM if (pamh) { if (pam_setcred(pamh, PAM_ESTABLISH_CRED) != PAM_SUCCESS) { WDMError("pam_setcred failed, errno=%d\n", errno); log_to_audit_system(0); pam_end(pamh, PAM_SUCCESS); pamh = NULL; return 0; } pam_open_session(pamh, 0); log_to_audit_system(1); /* pass in environment variables set by libpam and modules it called */ { long i; char **pam_env = pam_getenvlist(pamh); for (i = 0; pam_env && pam_env[i]; i++) { verify->userEnviron = WDMPutEnv(verify->userEnviron, pam_env[i]); } } } #endif switch (pid = fork()) { case 0: CleanUpChild(); #ifdef XDMCP /* The chooser socket is not closed by CleanUpChild() */ DestroyWellKnownSockets(); #endif if (setuid(verify->uid) < 0) { WDMError("setuid %d (user \"%s\") failed, errno=%d\n", verify->uid, name, errno); return (0); } /* * for Security Enhanced Linux, * set the default security context for this user. */ #ifdef WITH_SELINUX if (is_selinux_enabled()) { security_context_t scontext; if (get_default_context(name, NULL, &scontext)) WDMError("Failed to get default security context" " for %s.", name); WDMDebug("setting security context to %s", scontext); if (setexeccon(scontext)) { freecon(scontext); WDMError("Failed to set exec security context %s " "for %s.", scontext, name); } freecon(scontext); } #endif /* * for user-based authorization schemes, * use the password to get the user's credentials. */ bzero(passwd, strlen(passwd)); #ifdef WITH_CONSOLE_KIT if (ck_session_cookie != NULL) { verify->userEnviron = WDMSetEnv(verify->userEnviron, "XDG_SESSION_COOKIE", ck_session_cookie); } #endif SetUserAuthorization(d, verify); home = WDMGetEnv(verify->userEnviron, "HOME"); if (home) if (chdir(home) == -1) { WDMError("user \"%s\": cannot chdir to home \"%s\" (err %d), using \"/\"\n", WDMGetEnv(verify->userEnviron, "USER"), home, errno); chdir("/"); verify->userEnviron = WDMSetEnv(verify->userEnviron, "HOME", "/"); } if (verify->argv) { WDMDebug("executing session %s\n", verify->argv[0]); execute(verify->argv, verify->userEnviron); WDMError("Session \"%s\" execution failed (err %d)\n", verify->argv[0], errno); } else { WDMError("Session has no command/arguments\n"); } failsafeArgv[0] = d->failsafeClient; failsafeArgv[1] = 0; execute(failsafeArgv, verify->userEnviron); exit(1); case -1: bzero(passwd, strlen(passwd)); WDMDebug("StartSession, fork failed\n"); WDMError("can't start session on \"%s\", fork failed, errno=%d\n", d->name, errno); return 0; default: bzero(passwd, strlen(passwd)); WDMDebug("StartSession, fork succeeded %d\n", pid); *pidp = pid; return 1; } }
int main(int argc, char **argv) { int oldpid, oldumask; char cmdbuf[1024]; int debugMode = 0; /* make sure at least world write access is disabled */ if (((oldumask = umask(022)) & 002) == 002) (void)umask(oldumask); #ifndef NOXDMTITLE Title = argv[0]; TitleLen = (argv[argc - 1] + strlen(argv[argc - 1])) - Title; #endif /* * Step 1 - load configuration parameters */ InitResources(argc, argv); SetConfigFileTime(); LoadDMResources(); /* * Only allow root to run in non-debug mode to avoid problems */ debugMode = (debugLevel.i > WDM_LEVEL_WARNING); if (!debugMode && getuid() != 0) { fprintf(stderr, "Only root wants to run %s\n", argv[0]); exit(1); } if (!debugMode && daemonMode.i) { BecomeOrphan(); BecomeDaemon(); } /* SUPPRESS 560 */ if ((oldpid = StorePid())) { if (oldpid == -1) WDMError("Can't create/lock pid file %s\n", pidFile); else WDMError("Can't lock pid file %s, another wdm is running " "(pid %d)\n", pidFile, oldpid); exit(1); } WDMLogLevel(debugLevel.i); if (useSyslog.i) { WDMUseSysLog("wdm", WDMStringToFacility(syslogFacility)); } else if (errorLogFile && *errorLogFile) { int f; if ((f = open(errorLogFile, O_CREAT | O_WRONLY | O_APPEND, 0600)) == -1) WDMError("cannot open errorLogFile %s\n", errorLogFile); else WDMLogStream(fdopen(f, "w")); } /* redirect any messages for stderr into standard logging functions. */ WDMRedirectStderr(WDM_LEVEL_ERROR); /* Clean up any old Authorization files */ sprintf(cmdbuf, "/bin/rm -f %s/authdir/authfiles/A*", authDir); system(cmdbuf); #ifdef XDMCP init_session_id(); CreateWellKnownSockets(); #else WDMDebug("wdm: not compiled for XDMCP\n"); #endif parent_pid = getpid(); (void)Signal(SIGTERM, StopAll); (void)Signal(SIGINT, StopAll); /* * Step 2 - Read /etc/Xservers and set up * the socket. * * Keep a sub-daemon running * for each entry */ SetAccessFileTime(); #ifdef XDMCP ScanAccessDatabase(); #endif ScanServers(); StartDisplays(); (void)Signal(SIGHUP, RescanNotify); (void)Signal(SIGCHLD, ChildNotify); while ( #ifdef XDMCP AnyWellKnownSockets() || #endif AnyDisplaysLeft()) { if (Rescan) { RescanServers(); Rescan = 0; } WaitForSomething(); } WDMDebug("Nothing left to do, exiting\n"); exit(0); /*NOTREACHED*/}
void ManageSession(struct display *d) { static int pid = 0; Display *dpy; greet_user_rtn greet_stat; #ifdef WITH_CONSOLE_KIT char *ck_session_cookie = NULL; #endif WDMDebug("ManageSession %s\n", d->name); (void)XSetIOErrorHandler(IOErrorHandler); (void)XSetErrorHandler(ErrorHandler); #ifndef HAS_SETPROCTITLE SetTitle(d->name, (char *)0); #else setproctitle("%s", d->name); #endif /* * Load system default Resources */ LoadXloginResources(d); verify.version = 1; greet.version = 1; greet_stat = GreetUser(d, &dpy, &verify, &greet); if (greet_stat == Greet_Success) { clientPid = 0; if (!Setjmp(abortSession)) { (void)Signal(SIGTERM, catchTerm); /* * Start the clients, changing uid/groups * setting up environment and running the session */ #ifdef WITH_CONSOLE_KIT ck_session_cookie = open_ck_session(getpwnam(greet.name), d); #endif if (StartClient(&verify, d, &clientPid, greet.name, greet.password #ifdef WITH_CONSOLE_KIT , ck_session_cookie #endif )) { WDMDebug("Client Started\n"); /* * Wait for session to end, */ for (;;) { if (d->pingInterval) { if (!Setjmp(pingTime)) { (void)Signal(SIGALRM, catchAlrm); (void)alarm(d->pingInterval * 60); pid = wait((waitType *) 0); (void)alarm(0); } else { (void)alarm(0); if (!PingServer(d, (Display *) NULL)) SessionPingFailed(d); } } else { pid = wait((waitType *) 0); } if (pid == clientPid) break; } } else { WDMError("session start failed\n"); } } else { /* * when terminating the session, nuke * the child and then run the reset script */ AbortClient(clientPid); } } #ifdef WITH_CONSOLE_KIT if (ck_session_cookie != NULL) { close_ck_session(ck_session_cookie); free(ck_session_cookie); } #endif /* * run system-wide reset file */ WDMDebug("Source reset program %s\n", d->reset); source(verify.systemEnviron, d->reset); SessionExit(d, OBEYSESS_DISPLAY, TRUE); }