void pseudoReset (Display *dpy) { Window root; int screen; if (Setjmp (resetJmp)) { LogError ("pseudoReset timeout\n"); } else { (void) Signal (SIGALRM, abortReset); (void) alarm (30); XSetErrorHandler (ignoreErrors); for (screen = 0; screen < ScreenCount (dpy); screen++) { Debug ("pseudoReset screen %d\n", screen); root = RootWindow (dpy, screen); killWindows (dpy, root); } Debug ("before XSync\n"); XSync (dpy, False); (void) alarm (0); } Signal (SIGALRM, SIG_DFL); XSetErrorHandler ((XErrorHandler)0 ); Debug ("pseudoReset done\n"); }
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: LogError ("xdm 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; } }
int LoadDisplayResources( struct display *d ) { int i, ret; char **ent; if (Setjmp( cnftalk.errjmp )) return -1; /* may memleak */ if ((ret = startConfig( GC_gDisplay, &d->cfg.dep, FALSE )) <= 0) return ret; GSendStr( d->name ); GSendStr( d->class2 ); LoadResources( &d->cfg ); /* Debug( "display(%s, %s) resources: %[*x\n", d->name, d->class2, d->cfg.numCfgEnt, ((char **)d->cfg.data) + d->cfg.numCfgEnt );*/ ret = 1; for (i = 0; i < as(dpyVal); i++) { if (!(ent = FindCfgEnt( d, dpyVal[i].id ))) ret = -1; else ApplyResource( dpyVal[i].id, ent, (char **)(((char *)d) + dpyVal[i].off) ); } if (ret < 0) LogError( "Internal error: config reader supplied incomplete data\n" ); return ret; }
int PingServer (struct display *d, Display *alternateDpy) { int (*oldError)(Display *); SIGVAL (*oldSig)(int); int oldAlarm; static Display *aDpy; aDpy = (alternateDpy != NULL ? alternateDpy : dpy); oldError = XSetIOErrorHandler (PingLostIOErr); oldAlarm = alarm (0); oldSig = Signal (SIGALRM, PingLostSig); (void) alarm (d->pingTimeout * 60); if (!Setjmp (pingTime)) { Debug ("Ping server\n"); XSync (aDpy, 0); } else { Debug ("Server dead\n"); (void) alarm (0); (void) Signal (SIGALRM, SIG_DFL); XSetIOErrorHandler (oldError); return 0; } (void) alarm (0); (void) Signal (SIGALRM, oldSig); (void) alarm (oldAlarm); Debug ("Server alive\n"); XSetIOErrorHandler (oldError); return 1; }
void SecureDisplay (struct display *d, Display *dpy) { Debug ("SecureDisplay %s\n", d->name); (void) Signal (SIGALRM, syncTimeout); if (Setjmp (syncJump)) { LogError ("WARNING: display %s could not be secured\n", d->name); SessionExit (d, RESERVER_DISPLAY, FALSE); } (void) alarm ((unsigned) d->grabTimeout); Debug ("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); LogError ("WARNING: keyboard on display %s could not be secured\n", d->name); SessionExit (d, RESERVER_DISPLAY, FALSE); } Debug ("XGrabKeyboard succeeded %s\n", d->name); (void) alarm (0); (void) Signal (SIGALRM, SIG_DFL); pseudoReset (dpy); if (!d->grabServer) { XUngrabServer (dpy); XSync (dpy, 0); } Debug ("done secure %s\n", d->name); }
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 Debug ("Already received USR1\n"); #endif for (;;) { #if defined(SYSV) && defined(X_NOT_POSIX) pid = wait ((waitType *) 0); #else if (!receivedUsr1) pid = wait ((waitType *) 0); else #ifndef X_NOT_POSIX pid = waitpid (-1, (int *) 0, WNOHANG); #else pid = wait3 ((waitType *) 0, WNOHANG, (struct rusage *) 0); #endif /* X_NOT_POSIX */ #endif /* SYSV */ if (pid == serverPid || (pid == -1 && errno == ECHILD)) { Debug ("Server dead\n"); serverPauseRet = 1; break; } #if !defined(SYSV) || !defined(X_NOT_POSIX) if (pid == 0) { Debug ("Server alive and kicking\n"); break; } #endif } } (void) alarm ((unsigned) 0); (void) Signal (SIGALRM, SIG_DFL); (void) Signal (SIGUSR1, CatchUsr1); if (serverPauseRet) { Debug ("Server died\n"); LogError ("server unexpectedly died\n"); } return serverPauseRet; }
int InitResources( char **argv ) { originalArgv = argv; cnftalk.pipe = &getter.pipe; if (Setjmp( cnftalk.errjmp )) return 0; /* may memleak */ return GetDeps(); }
static int serverPause (unsigned t, pid_t serverPid) { pid_t 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 Debug ("Already received USR1\n"); #endif for (;;) { /* * wait() is unsafe. Other Xserver or xdm processes may * exit at this time and this will remove the wait status. * This means the main loop will not restart the display. */ if (!receivedUsr1) pid = waitpid (serverPid, (int *) 0, 0); else pid = waitpid (serverPid, (int *) 0, WNOHANG); if (pid == serverPid || (pid == -1 && errno == ECHILD)) { Debug ("Server dead\n"); serverPauseRet = 1; break; } if (pid == 0) { Debug ("Server alive and kicking\n"); break; } } } (void) alarm ((unsigned) 0); (void) Signal (SIGALRM, SIG_DFL); (void) Signal (SIGUSR1, CatchUsr1); if (serverPauseRet) { Debug ("Server died\n"); LogError ("server unexpectedly died\n"); } return serverPauseRet; }
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)) { Debug ("Before XOpenDisplay(%s)\n", d->name); errno = 0; (void) XSetIOErrorHandler (openErrorHandler); dpy = XOpenDisplay (d->name); #ifdef STREAMSCONN { /* For some reason, the next XOpenDisplay we do is going to fail, so we might as well get that out of the way. There is something broken here. */ Display *bogusDpy = XOpenDisplay (d->name); Debug ("bogus XOpenDisplay %s\n", bogusDpy ? "succeeded" : "failed"); if (bogusDpy) XCloseDisplay(bogusDpy); /* just in case */ } #endif (void) alarm ((unsigned) 0); (void) Signal (SIGALRM, SIG_DFL); (void) XSetIOErrorHandler ((int (*)(Display *)) 0); Debug ("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 { Debug ("OpenDisplay failed %d (%s) on \"%s\"\n", errno, strerror (errno), d->name); } Debug ("waiting for server to start %d\n", i); sleep ((unsigned) d->openDelay); } else { Debug ("hung in open, aborting\n"); LogError ("Hung in XOpenDisplay(%s), aborting\n", d->name); (void) Signal (SIGALRM, SIG_DFL); break; } } Debug ("giving up on server\n"); LogError ("server open failed for %s, giving up\n", d->name); return 0; }
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; }
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)) { Debug ("Before XOpenDisplay(%s)\n", d->name); errno = 0; (void) XSetIOErrorHandler (openErrorHandler); d->dpy = XOpenDisplay (d->name); (void) alarm ((unsigned) 0); (void) Signal (SIGALRM, SIG_DFL); (void) XSetIOErrorHandler ((int (*)(Display *)) 0); Debug ("After XOpenDisplay(%s)\n", d->name); if (d->dpy) { #ifdef XDMCP if (d->displayType.location == Foreign) GetRemoteAddress (d, ConnectionNumber (d->dpy)); #endif RegisterCloseOnFork (ConnectionNumber (d->dpy)); (void) fcntl (ConnectionNumber (d->dpy), F_SETFD, 0); return 1; } else { Debug ("OpenDisplay failed %d (%s) on \"%s\"\n", errno, strerror (errno), d->name); } Debug ("waiting for server to start %d\n", i); sleep ((unsigned) d->openDelay); } else { Debug ("hung in open, aborting\n"); LogError ("Hung in XOpenDisplay(%s), aborting\n", d->name); (void) Signal (SIGALRM, SIG_DFL); break; } } Debug ("giving up on server\n"); LogError ("server open failed for %s, giving up\n", d->name); return 0; }
int LoadDMResources( int force ) { int i, ret; char **ent; if (Setjmp( cnftalk.errjmp )) return -1; /* may memleak, but we probably have to abort anyway */ if ((ret = startConfig( GC_gGlobal, &cfg.dep, force )) <= 0) return ret; LoadResources( &cfg ); /* Debug( "manager resources: %[*x\n", cfg.numCfgEnt, ((char **)cfg.data) + cfg.numCfgEnt );*/ ret = 1; for (i = 0; i < as(globVal); i++) { if (!(ent = FindCfgEnt( 0, globVal[i].id ))) ret = -1; else ApplyResource( globVal[i].id, ent, globVal[i].off ); } if (ret < 0) LogError( "Internal error: config reader supplied incomplete data\n" ); return ret; }
void ManageSession (struct display *d) { static int pid = 0; Display *dpy; greet_user_rtn greet_stat; static GreetUserProc greet_user_proc = NULL; #ifndef GREET_USER_STATIC void *greet_lib_handle; #endif Debug ("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); #ifdef GREET_USER_STATIC greet_user_proc = GreetUser; #else Debug("ManageSession: loading greeter library %s\n", greeterLib); greet_lib_handle = dlopen(greeterLib, RTLD_NOW); if (greet_lib_handle != NULL) greet_user_proc = (GreetUserProc)dlsym(greet_lib_handle, "GreetUser"); if (greet_user_proc == NULL) { LogError("%s while loading %s\n", dlerror(), greeterLib); exit(UNMANAGE_DISPLAY); } #endif /* tell the possibly dynamically loaded greeter function * what data structure formats to expect. * These version numbers are registered with The Open Group. */ verify.version = 1; greet.version = 1; greet_stat = (*greet_user_proc)(d, &dpy, &verify, &greet, &dlfuncs); 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 */ if (StartClient (&verify, d, &clientPid, greet.name, greet.password)) { Debug ("Client Started\n"); #ifndef GREET_USER_STATIC /* Save memory; close library */ dlclose(greet_lib_handle); #endif /* * 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 { LogError ("session start failed\n"); } } else { /* * when terminating the session, nuke * the child and then run the reset script */ AbortClient (clientPid); } } /* * run system-wide reset file */ Debug ("Source reset program %s\n", d->reset); source (verify.systemEnviron, d->reset); SessionExit (d, OBEYSESS_DISPLAY, TRUE); }
ARRAY8Ptr getLocalAddress(void) { static int haveLocalAddress; if (!haveLocalAddress) { #if defined(IPv6) && defined(AF_INET6) struct addrinfo *ai; if (getaddrinfo(localHostname(), 0, 0, &ai)) { XdmcpAllocARRAY8(&localAddress, 4); localAddress.data[0] = 127; localAddress.data[1] = 0; localAddress.data[2] = 0; localAddress.data[3] = 1; } else { if (ai->ai_family == AF_INET) { XdmcpAllocARRAY8(&localAddress, sizeof(struct in_addr)); memcpy(localAddress.data, &((struct sockaddr_in *)ai->ai_addr)->sin_addr, sizeof(struct in_addr)); } else /* if (ai->ai_family == AF_INET6) */ { XdmcpAllocARRAY8(&localAddress, sizeof(struct in6_addr)); memcpy(localAddress.data, &((struct sockaddr_in6 *)ai->ai_addr)->sin6_addr, sizeof(struct in6_addr)); } freeaddrinfo(ai); #else struct hostent *hostent; if ((hostent = gethostbyname(localHostname()))) { XdmcpAllocARRAY8(&localAddress, hostent->h_length); memmove(localAddress.data, hostent->h_addr, hostent->h_length); #endif haveLocalAddress = True; } } return &localAddress; } void scanAccessDatabase(int force) { struct _displayAddress *da; char *cptr; int nChars, i; debug("scanAccessDatabase\n"); if (Setjmp(cnftalk.errjmp)) return; /* may memleak */ if (startConfig(GC_gXaccess, &accData->dep, force) <= 0) return; free(accData->hostList); accData->nHosts = gRecvInt(); accData->nListens = gRecvInt(); accData->nAliases = gRecvInt(); accData->nAcls = gRecvInt(); nChars = gRecvInt(); if (!(accData->hostList = (HostEntry *) Malloc(accData->nHosts * sizeof(HostEntry) + accData->nListens * sizeof(ListenEntry) + accData->nAliases * sizeof(AliasEntry) + accData->nAcls * sizeof(AclEntry) + nChars))) { closeGetter(); return; } accData->listenList = (ListenEntry *)(accData->hostList + accData->nHosts); accData->aliasList = (AliasEntry *)(accData->listenList + accData->nListens); accData->acList = (AclEntry *)(accData->aliasList + accData->nAliases); cptr = (char *)(accData->acList + accData->nAcls); for (i = 0; i < accData->nHosts; i++) { switch ((accData->hostList[i].type = gRecvInt())) { case HOST_ALIAS: accData->hostList[i].entry.aliasPattern = cptr; cptr += gRecvStrBuf(cptr); break; case HOST_PATTERN: accData->hostList[i].entry.hostPattern = cptr; cptr += gRecvStrBuf(cptr); break; case HOST_ADDRESS: da = &accData->hostList[i].entry.displayAddress; da->hostAddress.data = (unsigned char *)cptr; cptr += (da->hostAddress.length = gRecvArrBuf(cptr)); switch (gRecvInt()) { #ifdef AF_INET case AF_INET: da->connectionType = FamilyInternet; break; #endif #if defined(IPv6) && defined(AF_INET6) case AF_INET6: da->connectionType = FamilyInternet6; break; #endif #ifdef AF_DECnet case AF_DECnet: da->connectionType = FamilyDECnet; break; #endif /*#ifdef AF_UNIX case AF_UNIX: #endif*/ default: da->connectionType = FamilyLocal; break; } break; case HOST_BROADCAST: break; default: logError("Received unknown host type %d from config reader\n", accData->hostList[i].type); return; } } for (i = 0; i < accData->nListens; i++) { accData->listenList[i].iface = gRecvInt(); accData->listenList[i].mcasts = gRecvInt(); accData->listenList[i].nmcasts = gRecvInt(); } for (i = 0; i < accData->nAliases; i++) { accData->aliasList[i].name = cptr; cptr += gRecvStrBuf(cptr); accData->aliasList[i].hosts = gRecvInt(); accData->aliasList[i].nhosts = gRecvInt(); } for (i = 0; i < accData->nAcls; i++) { accData->acList[i].entries = gRecvInt(); accData->acList[i].nentries = gRecvInt(); accData->acList[i].hosts = gRecvInt(); accData->acList[i].nhosts = gRecvInt(); accData->acList[i].flags = gRecvInt(); } } /* Returns True if string is matched by pattern. Does case folding. */ static int patternMatch(const char *string, const char *pattern) { int p, s; if (!string) string = ""; for (;;) { s = *string++; switch (p = *pattern++) { case '*': if (!*pattern) return True; for (string--; *string; string++) if (patternMatch(string, pattern)) return True; return False; case '?': if (s == '\0') return False; break; case '\0': return s == '\0'; case '\\': p = *pattern++; /* fall through */ default: if (tolower(p) != tolower(s)) return False; } } }
static void processDPipe(struct display *d) { char *user, *pass, *args; int cmd; GTalk dpytalk; #ifdef XDMCP int ct, len; ARRAY8 ca, cp, ha; #endif dpytalk.pipe = &d->pipe; if (Setjmp(dpytalk.errjmp)) { stopDisplay(d); return; } gSet(&dpytalk); if (!gRecvCmd(&cmd)) { /* process already exited */ unregisterInput(d->pipe.fd.r); return; } switch (cmd) { case D_User: d->userSess = gRecvInt(); d->userName = gRecvStr(); d->sessName = gRecvStr(); break; case D_UnUser: sessionDone(d); if (d->sdRec.how) { if (d->sdRec.force == SHUT_ASK && (anyUserLogins(-1) || d->allowShutdown == SHUT_ROOT)) { gSendInt(True); } else { if (!sdRec.how || sdRec.force != SHUT_FORCE || !((d->allowNuke == SHUT_NONE && sdRec.uid != d->sdRec.uid) || (d->allowNuke == SHUT_ROOT && d->sdRec.uid))) { free(sdRec.osname); sdRec = d->sdRec; } else { free(d->sdRec.osname); } d->sdRec.how = 0; d->sdRec.osname = 0; gSendInt(False); } } else { gSendInt(False); } break; case D_ReLogin: user = gRecvStr(); pass = gRecvStr(); args = gRecvStr(); setNLogin(d, user, pass, args, 1); free(args); free(pass); free(user); break; #ifdef XDMCP case D_ChooseHost: ca.data = (unsigned char *)gRecvArr(&len); ca.length = (CARD16)len; cp.data = (unsigned char *)gRecvArr(&len); cp.length = (CARD16)len; ct = gRecvInt(); ha.data = (unsigned char *)gRecvArr(&len); ha.length = (CARD16)len; registerIndirectChoice(&ca, &cp, ct, &ha); XdmcpDisposeARRAY8(&ha); XdmcpDisposeARRAY8(&cp); XdmcpDisposeARRAY8(&ca); break; case D_RemoteHost: free(d->remoteHost); d->remoteHost = gRecvStr(); break; #endif case D_XConnOk: startingServer = 0; break; default: logError("Internal error: unknown D_* command %d\n", cmd); stopDisplay(d); break; } }
int startClient( volatile int *pid ) { const char *home, *sessargs, *desksess; char **env, *xma; char **argv, *fname, *str; #ifdef USE_PAM char ** volatile pam_env; # ifndef HAVE_PAM_GETENVLIST char **saved_env; # endif int pretc; #else # ifdef _AIX char *msg; char **theenv; extern char **newenv; /* from libs.a, this is set up by setpenv */ # endif #endif #ifdef HAVE_SETUSERCONTEXT extern char **environ; #endif char *failsafeArgv[2]; char *buf, *buf2; int i; if (strCmp( dmrcuser, curuser )) { if (curdmrc) { free( curdmrc ); curdmrc = 0; } if (dmrcuser) { free( dmrcuser ); dmrcuser = 0; } } #if defined(USE_PAM) || defined(_AIX) if (!(p = getpwnam( curuser ))) { logError( "getpwnam(%s) failed.\n", curuser ); pError: displayStr( V_MSG_ERR, 0 ); return 0; } #endif #ifndef USE_PAM # ifdef _AIX msg = NULL; loginsuccess( curuser, hostname, tty, &msg ); if (msg) { debug( "loginsuccess() - %s\n", msg ); free( (void *)msg ); } # else /* _AIX */ # if defined(KERBEROS) && defined(AFS) if (krbtkfile[0] != '\0') { if (k_hasafs()) { int fail = 0; if (k_setpag() == -1) { logError( "setpag() for %s failed\n", curuser ); fail = 1; } if ((ret = k_afsklog( NULL, NULL )) != KSUCCESS) { logError( "AFS Warning: %s\n", krb_get_err_text( ret ) ); fail = 1; } if (fail) displayMsg( V_MSG_ERR, "Warning: Problems during Kerberos4/AFS setup." ); } } # endif /* KERBEROS && AFS */ # endif /* _AIX */ #endif /* !PAM */ curuid = p->pw_uid; curgid = p->pw_gid; env = baseEnv( curuser ); xma = 0; strApp( &xma, "method=", curtype, (char *)0 ); if (td_setup) strApp( &xma, ",auto", (char *)0 ); if (xma) { env = setEnv( env, "XDM_MANAGED", xma ); free( xma ); } if (td->autoLock && cursource == PWSRC_AUTOLOGIN) env = setEnv( env, "DESKTOP_LOCKED", "true" ); env = setEnv( env, "PATH", curuid ? td->userPath : td->systemPath ); env = setEnv( env, "SHELL", p->pw_shell ); env = setEnv( env, "HOME", p->pw_dir ); #if !defined(USE_PAM) && !defined(_AIX) && defined(KERBEROS) if (krbtkfile[0] != '\0') env = setEnv( env, "KRBTKFILE", krbtkfile ); #endif userEnviron = inheritEnv( env, envvars ); env = systemEnv( curuser ); systemEnviron = setEnv( env, "HOME", p->pw_dir ); debug( "user environment:\n%[|''>'\n's" "system environment:\n%[|''>'\n's" "end of environments\n", userEnviron, systemEnviron ); /* * for user-based authorization schemes, * add the user to the server's allowed "hosts" list. */ for (i = 0; i < td->authNum; i++) { #ifdef SECURE_RPC if (td->authorizations[i]->name_length == 9 && !memcmp( td->authorizations[i]->name, "SUN-DES-1", 9 )) { XHostAddress addr; char netname[MAXNETNAMELEN+1]; char domainname[MAXNETNAMELEN+1]; getdomainname( domainname, sizeof(domainname) ); user2netname( netname, curuid, domainname ); addr.family = FamilyNetname; addr.length = strlen( netname ); addr.address = netname; XAddHost( dpy, &addr ); } #endif #ifdef K5AUTH if (td->authorizations[i]->name_length == 14 && !memcmp( td->authorizations[i]->name, "MIT-KERBEROS-5", 14 )) { /* Update server's auth file with user-specific info. * Don't need to AddHost because X server will do that * automatically when it reads the cache we are about * to point it at. */ XauDisposeAuth( td->authorizations[i] ); td->authorizations[i] = krb5GetAuthFor( 14, "MIT-KERBEROS-5", td->name ); saveServerAuthorizations( td, td->authorizations, td->authNum ); } #endif } if (*dmrcDir) mergeSessionArgs( TRUE ); debug( "now starting the session\n" ); #ifdef USE_PAM # ifdef HAVE_SETUSERCONTEXT if (setusercontext( lc, p, p->pw_uid, LOGIN_SETGROUP )) { logError( "setusercontext(groups) for %s failed: %m\n", curuser ); goto pError; } # else if (!setGid( curuser, curgid )) goto pError; # endif # ifndef HAVE_PAM_GETENVLIST if (!(pam_env = initStrArr( 0 ))) { resetGids(); goto pError; } saved_env = environ; environ = pam_env; # endif removeCreds = 1; /* set it first - i don't trust PAM's rollback */ pretc = pam_setcred( pamh, 0 ); reInitErrorLog(); # ifndef HAVE_PAM_GETENVLIST pam_env = environ; environ = saved_env; # endif # ifdef HAVE_INITGROUPS /* This seems to be a strange place for it, but do it: - after the initial groups are set - after pam_setcred might have set something, even in the error case - before pam_setcred(DELETE_CRED) might need it */ if (!saveGids()) goto pError; # endif if (pretc != PAM_SUCCESS) { logError( "pam_setcred() for %s failed: %s\n", curuser, pam_strerror( pamh, pretc ) ); resetGids(); return 0; } removeSession = 1; /* set it first - same as above */ pretc = pam_open_session( pamh, 0 ); reInitErrorLog(); if (pretc != PAM_SUCCESS) { logError( "pam_open_session() for %s failed: %s\n", curuser, pam_strerror( pamh, pretc ) ); resetGids(); return 0; } /* we don't want sessreg and the startup/reset scripts run with user credentials. unfortunately, we can reset only the gids. */ resetGids(); # define D_LOGIN_SETGROUP LOGIN_SETGROUP #else /* USE_PAM */ # define D_LOGIN_SETGROUP 0 #endif /* USE_PAM */ removeAuth = 1; chownCtrl( &td->ctrl, curuid ); endpwent(); #if !defined(USE_PAM) && defined(USESHADOW) && !defined(_AIX) endspent(); #endif ctltalk.pipe = &ctlpipe; ASPrintf( &buf, "sub-daemon for display %s", td->name ); ASPrintf( &buf2, "client for display %s", td->name ); switch (gFork( &ctlpipe, buf, buf2, 0, 0, mstrtalk.pipe, pid )) { case 0: gCloseOnExec( ctltalk.pipe ); if (Setjmp( ctltalk.errjmp )) exit( 1 ); gCloseOnExec( mstrtalk.pipe ); if (Setjmp( mstrtalk.errjmp )) goto cError; #ifndef NOXDMTITLE setproctitle( "%s'", td->name ); #endif strApp( &prog, " '", (char *)0 ); reInitErrorLog(); setsid(); sessreg( td, getpid(), curuser, curuid ); /* We do this here, as we want to have the session as parent. */ switch (source( systemEnviron, td->startup, td_setup )) { case 0: break; case wcCompose( 0, 0, 127 ): goto cError; default: /* Explicit failure => message already displayed. */ logError( "Startup script returned non-zero exit code\n" ); exit( 1 ); } /* Memory leaks are ok here as we exec() soon. */ #if defined(USE_PAM) || !defined(_AIX) # ifdef USE_PAM /* pass in environment variables set by libpam and modules it called */ # ifdef HAVE_PAM_GETENVLIST pam_env = pam_getenvlist( pamh ); reInitErrorLog(); # endif if (pam_env) for (; *pam_env; pam_env++) userEnviron = putEnv( *pam_env, userEnviron ); # endif # ifdef HAVE_SETLOGIN if (setlogin( curuser ) < 0) { logError( "setlogin for %s failed: %m\n", curuser ); goto cError; } # define D_LOGIN_SETLOGIN LOGIN_SETLOGIN # else # define D_LOGIN_SETLOGIN 0 # endif # if defined(USE_PAM) && defined(HAVE_INITGROUPS) if (!restoreGids()) goto cError; # endif # ifndef HAVE_SETUSERCONTEXT # ifdef USE_PAM if (!setUid( curuser, curuid )) goto cError; # else if (!setUser( curuser, curuid, curgid )) goto cError; # endif # else /* !HAVE_SETUSERCONTEXT */ /* * Destroy environment. * We need to do this before setusercontext() because that may * set or reset some environment variables. */ if (!(environ = initStrArr( 0 ))) goto cError; /* * Set the user's credentials: uid, gid, groups, * environment variables, resource limits, and umask. */ if (setusercontext( lc, p, p->pw_uid, LOGIN_SETALL & ~(D_LOGIN_SETGROUP|D_LOGIN_SETLOGIN) ) < 0) { logError( "setusercontext for %s failed: %m\n", curuser ); goto cError; } for (i = 0; environ[i]; i++) userEnviron = putEnv( environ[i], userEnviron ); # endif /* !HAVE_SETUSERCONTEXT */ #else /* PAM || !_AIX */ /* * Set the user's credentials: uid, gid, groups, * audit classes, user limits, and umask. */ if (setpcred( curuser, NULL ) == -1) { logError( "setpcred for %s failed: %m\n", curuser ); goto cError; } /* * Set the users process environment. Store protected variables and * obtain updated user environment list. This call will initialize * global 'newenv'. */ if (setpenv( curuser, PENV_INIT | PENV_ARGV | PENV_NOEXEC, userEnviron, NULL ) != 0) { logError( "Cannot set %s's process environment\n", curuser ); goto cError; } userEnviron = newenv; #endif /* _AIX */ /* * for user-based authorization schemes, * use the password to get the user's credentials. */ #ifdef SECURE_RPC /* do like "keylogin" program */ if (!curpass[0]) logInfo( "No password for NIS provided.\n" ); else { char netname[MAXNETNAMELEN+1], secretkey[HEXKEYBYTES+1]; int nameret, keyret; int len; int key_set_ok = 0; struct key_netstarg netst; nameret = getnetname( netname ); debug( "user netname: %s\n", netname ); len = strlen( curpass ); if (len > 8) bzero( curpass + 8, len - 8 ); keyret = getsecretkey( netname, secretkey, curpass ); debug( "getsecretkey returns %d, key length %d\n", keyret, strlen( secretkey ) ); netst.st_netname = netname; memcpy( netst.st_priv_key, secretkey, HEXKEYBYTES ); memset( netst.st_pub_key, 0, HEXKEYBYTES ); if (key_setnet( &netst ) < 0) debug( "Could not set secret key.\n" ); /* is there a key, and do we have the right password? */ if (keyret == 1) { if (*secretkey) { keyret = key_setsecret( secretkey ); debug( "key_setsecret returns %d\n", keyret ); if (keyret == -1) logError( "Failed to set NIS secret key\n" ); else key_set_ok = 1; } else { /* found a key, but couldn't interpret it */ logError( "Password incorrect for NIS principal %s\n", nameret ? netname : curuser ); } } if (!key_set_ok) nukeAuth( 9, "SUN-DES-1" ); bzero( secretkey, strlen( secretkey ) ); } #endif #ifdef K5AUTH /* do like "kinit" program */ if (!curpass[0]) logInfo( "No password for Kerberos5 provided.\n" ); else if ((str = krb5Init( curuser, curpass, td->name ))) userEnviron = setEnv( userEnviron, "KRB5CCNAME", str ); else nukeAuth( 14, "MIT-KERBEROS-5" ); #endif /* K5AUTH */ if (td->autoReLogin) { gSet( &mstrtalk ); gSendInt( D_ReLogin ); gSendStr( curuser ); gSendStr( curpass ); gSendStr( newdmrc ); } if (curpass) bzero( curpass, strlen( curpass ) ); setUserAuthorization( td ); home = getEnv( userEnviron, "HOME" ); if (home && chdir( home ) < 0) { logError( "Cannot chdir to %s's home %s: %m\n", curuser, home ); sendStr( V_MSG_ERR, "Cannot enter home directory. Using /.\n" ); chdir( "/" ); userEnviron = setEnv( userEnviron, "HOME", "/" ); home = 0; } if (home || td->clientLogFile[0] == '/') { if (!createClientLog( td->clientLogFile )) { logWarn( "Session log file according to %s cannot be created: %m\n", td->clientLogFile ); goto tmperr; } } else { tmperr: if (!createClientLog( td->clientLogFallback )) logError( "Fallback session log file according to %s cannot be created: %m\n", td->clientLogFallback ); /* Could inform the user, but I guess this is only confusing. */ } if (!*dmrcDir) mergeSessionArgs( home != 0 ); if (!(desksess = iniEntry( curdmrc, "Desktop", "Session", 0 ))) desksess = "failsafe"; /* only due to OOM */ gSet( &mstrtalk ); gSendInt( D_User ); gSendInt( curuid ); gSendStr( curuser ); gSendStr( desksess ); close( mstrtalk.pipe->fd.w ); userEnviron = setEnv( userEnviron, "DESKTOP_SESSION", desksess ); for (i = 0; td->sessionsDirs[i]; i++) { fname = 0; if (strApp( &fname, td->sessionsDirs[i], "/", desksess, ".desktop", (char *)0 )) { if ((str = iniLoad( fname ))) { if (!strCmp( iniEntry( str, "Desktop Entry", "Hidden", 0 ), "true" ) || !(sessargs = iniEntry( str, "Desktop Entry", "Exec", 0 ))) sessargs = ""; free( str ); free( fname ); goto gotit; } free( fname ); } } if (!strcmp( desksess, "failsafe" ) || !strcmp( desksess, "default" ) || !strcmp( desksess, "custom" )) sessargs = desksess; else sessargs = ""; gotit: if (!(argv = parseArgs( (char **)0, td->session )) || !(argv = addStrArr( argv, sessargs, -1 ))) exit( 1 ); if (argv[0] && *argv[0]) { debug( "executing session %\"[s\n", argv ); execute( argv, userEnviron ); logError( "Session %\"s execution failed: %m\n", argv[0] ); } else logError( "Session has no command/arguments\n" ); failsafeArgv[0] = td->failsafeClient; failsafeArgv[1] = 0; execute( failsafeArgv, userEnviron ); logError( "Failsafe client %\"s execution failed: %m\n", failsafeArgv[0] ); cError: sendStr( V_MSG_ERR, 0 ); exit( 1 ); case -1: free( buf ); return 0; } debug( "StartSession, fork succeeded %d\n", *pid ); free( buf ); gSet( &ctltalk ); if (!Setjmp( ctltalk.errjmp )) while (gRecvCmd( &i )) { buf = gRecvStr(); displayStr( i, buf ); free( buf ); gSet( &ctltalk ); gSendInt( 0 ); } gClosen( ctltalk.pipe ); finishGreet(); return 1; }
static void processDPipe( struct display *d ) { char *user, *pass, *args; int cmd; GTalk dpytalk; #ifdef XDMCP int ct, len; ARRAY8 ca, ha; #endif dpytalk.pipe = &d->pipe; if (Setjmp( dpytalk.errjmp )) { StopDisplay( d ); return; } GSet( &dpytalk ); if (!GRecvCmd( &cmd )) { /* process already exited */ UnregisterInput( d->pipe.rfd ); return; } switch (cmd) { case D_User: d->userSess = GRecvInt(); d->userName = GRecvStr(); d->sessName = GRecvStr(); break; case D_ReLogin: user = GRecvStr(); pass = GRecvStr(); args = GRecvStr(); setNLogin( d, user, pass, args, 1 ); free( args ); free( pass ); free( user ); break; #ifdef XDMCP case D_ChooseHost: ca.data = (unsigned char *)GRecvArr( &len ); ca.length = (CARD16)len; ct = GRecvInt(); ha.data = (unsigned char *)GRecvArr( &len ); ha.length = (CARD16)len; RegisterIndirectChoice( &ca, ct, &ha ); XdmcpDisposeARRAY8( &ha ); XdmcpDisposeARRAY8( &ca ); break; case D_RemoteHost: if (d->remoteHost) free( d->remoteHost ); d->remoteHost = GRecvStr(); break; #endif case D_XConnOk: startingServer = 0; break; default: LogError( "Internal error: unknown D_* command %d\n", cmd ); StopDisplay( d ); break; } }
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); }