Esempio n. 1
0
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");
}
Esempio n. 2
0
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;
    }
}
Esempio n. 3
0
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;
}
Esempio n. 4
0
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;
}
Esempio n. 5
0
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);
}
Esempio n. 6
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
	    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;
}
Esempio n. 7
0
int
InitResources( char **argv )
{
	originalArgv = argv;
	cnftalk.pipe = &getter.pipe;
	if (Setjmp( cnftalk.errjmp ))
		return 0; /* may memleak */
	return GetDeps();
}
Esempio n. 8
0
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;
}
Esempio n. 9
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)) {
	    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;
}
Esempio n. 10
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;
}
Esempio n. 11
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)) {
	    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;
}
Esempio n. 12
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;
}
Esempio n. 13
0
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);
}
Esempio n. 14
0
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;
        }
    }
}
Esempio n. 15
0
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;
    }
}
Esempio n. 16
0
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;
}
Esempio n. 17
0
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;
	}
}
Esempio n. 18
0
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);
}