Exemple #1
0
/* This just gets a cookie of MIT-MAGIC-COOKIE-1 type */
char *
mdmcomm_get_a_cookie (gboolean binary)
{
	FILE *fp;
	char *number;
	char *cookie = NULL;
	Xauth *xau;

	VE_IGNORE_EINTR (fp = fopen (XauFileName (), "r"));
	if (fp == NULL) {
		return NULL;
	}

	number = get_dispnum ();

	cookie = NULL;

	while ((xau = XauReadAuth (fp)) != NULL) {
		/* Just find the FIRST magic cookie, that's what mdm uses */
		if (xau->number_length != strlen (number) ||
		    strncmp (xau->number, number, xau->number_length) != 0 ||
		    /* mdm sends MIT-MAGIC-COOKIE-1 cookies of length 16,
		     * so just do those */
		    xau->data_length != 16 ||
		    xau->name_length != strlen ("MIT-MAGIC-COOKIE-1") ||
		    strncmp (xau->name, "MIT-MAGIC-COOKIE-1",
			     xau->name_length) != 0) {
			XauDisposeAuth (xau);
			continue;
		}

		if (binary) {
			cookie = g_new0 (char, 16);
			memcpy (cookie, xau->data, 16);
		} else {
			int i;
			GString *str;

			str = g_string_new (NULL);

			for (i = 0; i < xau->data_length; i++) {
				g_string_append_printf
					(str, "%02x",
					 (guint)(guchar)xau->data[i]);
			}
			cookie = g_string_free (str, FALSE);
		}

		XauDisposeAuth (xau);

		break;
	}
Exemple #2
0
void DM::GDMAuthenticate()
{
    FILE *fp;
    const char *dpy, *dnum, *dne;
    int dnl;
    Xauth *xau;

    dpy = DisplayString(QPaintDevice::x11AppDisplay());
    if(!dpy)
    {
        dpy = ::getenv("DISPLAY");
        if(!dpy)
            return;
    }
    dnum = strchr(dpy, ':') + 1;
    dne = strchr(dpy, '.');
    dnl = dne ? dne - dnum : strlen(dnum);

    /* XXX should do locking */
    if(!(fp = fopen(XauFileName(), "r")))
        return;

    while((xau = XauReadAuth(fp)))
    {
        if(xau->family == FamilyLocal && xau->number_length == dnl && !memcmp(xau->number, dnum, dnl) && xau->data_length == 16
           && xau->name_length == 18 && !memcmp(xau->name, "MIT-MAGIC-COOKIE-1", 18))
        {
            QString cmd("AUTH_LOCAL ");
            for(int i = 0; i < 16; i++)
                cmd += QString::number((uchar)xau->data[i], 16).rightJustify(2, '0');
            cmd += "\n";
            if(exec(cmd.latin1()))
            {
                XauDisposeAuth(xau);
                break;
            }
        }
        XauDisposeAuth(xau);
    }

    fclose(fp);
}
Exemple #3
0
static Xauth*
find_auth_cookie (FILE *f)
{
    Xauth *ret = NULL;
    char local_hostname[MaxHostNameLen];
    char *display_str = getenv("DISPLAY");
    char d[MaxHostNameLen + 4];
    char *colon;
    struct addrinfo *ai;
    struct addrinfo hints;
    int disp;
    int error;

    if(display_str == NULL)
	display_str = ":0";
    strlcpy(d, display_str, sizeof(d));
    display_str = d;
    colon = strchr (display_str, ':');
    if (colon == NULL)
	disp = 0;
    else {
	*colon = '\0';
	disp = atoi (colon + 1);
    }
    if (strcmp (display_str, "") == 0
	|| strncmp (display_str, "unix", 4) == 0
	|| strncmp (display_str, "localhost", 9) == 0) {
	gethostname (local_hostname, sizeof(local_hostname));
	display_str = local_hostname;
    }
    memset (&hints, 0, sizeof(hints));
    hints.ai_flags    = AI_CANONNAME;
    hints.ai_socktype = SOCK_STREAM;
    hints.ai_protocol = IPPROTO_TCP;

    error = getaddrinfo (display_str, NULL, &hints, &ai);
    if (error)
	ai = NULL;

    for (; (ret = XauReadAuth (f)) != NULL; XauDisposeAuth(ret)) {
	if (match_local_auth (ret, ai, display_str, disp) == 0) {
	    if (ai != NULL)
		freeaddrinfo (ai);
	    return ret;
	}
    }
    if (ai != NULL)
	freeaddrinfo (ai);
    return NULL;
}
Exemple #4
0
int
LoadAuthorization (void)
{
    FILE    *f;
    Xauth   *auth;
    int	    i;
    int	    count = 0;
#if !defined(WIN32) && !defined(__UNIXOS2__)
    char    *buf;
#endif

    ShouldLoadAuth = FALSE;
    if (!authorization_file)
	return 0;
#if !defined(WIN32) && !defined(__UNIXOS2__)
    buf = xalloc (strlen(authorization_file) + 5);
    if (!buf)
	return -1;
    sprintf (buf, "cat %s", authorization_file);
    f = Popen (buf, "r");
    xfree (buf);
#else
    f = fopen (authorization_file, "r");
#endif
    if (!f)
	return -1;

    while ((auth = XauReadAuth (f)) != 0) {
	for (i = 0; i < NUM_AUTHORIZATION; i++) {
	    if (protocols[i].name_length == auth->name_length &&
		memcmp (protocols[i].name, auth->name, (int) auth->name_length) == 0 &&
		protocols[i].Add)
	    {
		++count;
		(*protocols[i].Add) (auth->data_length, auth->data,
					 FakeClientID(0));
	    }
	}
	XauDisposeAuth (auth);
    }

#if !defined(WIN32) && !defined(__UNIXOS2__)
    if (Pclose (f) != 0)
	return -1;
#else
    fclose (f);
#endif
    return count;
}
static Xauth *
read_numeric(FILE *fp)
{
    Xauth *auth;

    auth = (Xauth *) malloc (sizeof (Xauth));
    if (!auth) goto bad;
    auth->family = 0;
    auth->address = NULL;
    auth->address_length = 0;
    auth->number = NULL;
    auth->number_length = 0;
    auth->name = NULL;
    auth->name_length = 0;
    auth->data = NULL;
    auth->data_length = 0;

    if (!get_short (fp, (unsigned short *) &auth->family))
      goto bad;
    if (!get_short (fp, (unsigned short *) &auth->address_length))
      goto bad;
    if (!get_bytes (fp, (unsigned int) auth->address_length, &auth->address))
      goto bad;
    if (!get_short (fp, (unsigned short *) &auth->number_length))
      goto bad;
    if (!get_bytes (fp, (unsigned int) auth->number_length, &auth->number))
      goto bad;
    if (!get_short (fp, (unsigned short *) &auth->name_length))
      goto bad;
    if (!get_bytes (fp, (unsigned int) auth->name_length, &auth->name))
      goto bad;
    if (!get_short (fp, (unsigned short *) &auth->data_length))
      goto bad;
    if (!get_bytes (fp, (unsigned int) auth->data_length, &auth->data))
      goto bad;
    
    switch (getinput (fp)) {		/* get end of line */
      case EOF:
      case '\n':
	return auth;
    }

  bad:
    if (auth) XauDisposeAuth (auth);	/* won't free null pointers */
    return NULL;
}
/* ARGSUSED */
static int 
remove_entry(char *inputfilename, int lineno, Xauth *auth, char *data)
{
    int *nremovedp = (int *) data;
    AuthList **listp = &xauth_head;
    AuthList *list;

    /*
     * unlink the auth we were asked to
     */
    while ((list = *listp)->auth != auth)
	listp = &list->next;
    *listp = list->next;
    XauDisposeAuth (list->auth);                    /* free the auth */
    free (list);				    /* free the link */
    xauth_modified = True;
    (*nremovedp)++;
    return 1;
}
Exemple #7
0
static void freeDisplay(struct display *d)
{
	char **x;
	int i;

	IfFree(d->name);
	IfFree(d->class);
	for (x = d->argv; x && *x; x++)
		IfFree(*x);
	IfFree(d->argv);
	IfFree(d->resources);
	IfFree(d->xrdb);
	IfFree(d->setup);
	IfFree(d->startup);
	IfFree(d->reset);
	IfFree(d->session);
	IfFree(d->userPath);
	IfFree(d->systemPath);
	IfFree(d->systemShell);
	IfFree(d->failsafeClient);
	IfFree(d->chooser);
	if (d->authorizations) {
		for (i = 0; i < d->authNum; i++)
			XauDisposeAuth(d->authorizations[i]);
		free(d->authorizations);
	}
	IfFree(d->clientAuthFile);
	if (d->authFile)
		(void)unlink(d->authFile);
	IfFree(d->authFile);
	IfFree(d->userAuthDir);
	for (x = d->authNames; x && *x; x++)
		IfFree(*x);
	IfFree(d->authNames);
	IfFree(d->authNameLens);
#ifdef XDMCP
	IfFree(d->peer);
	IfFree(d->from);
	XdmcpDisposeARRAY8(&d->clientAddr);
#endif
	free(d);
}
Exemple #8
0
void RemoveDisplay(struct display *old)
{
    struct display *d, **dp;
    int i;

    for(dp = &displays; (d = *dp); dp = &(*dp)->next)
    {
        if(d == old)
        {
            Debug("Removing display %s\n", d->name);
            *dp = d->next;
            IfFree(d->class2);
            IfFree(d->cfg.data);
            delStr(d->cfg.dep.name);
#ifdef XDMCP
            IfFree(d->remoteHost);
#endif
            if(d->authorizations)
            {
                for(i = 0; i < d->authNum; i++)
                    XauDisposeAuth(d->authorizations[i]);
                free((char *)d->authorizations);
            }
            if(d->authFile)
            {
                (void)unlink(d->authFile);
                free(d->authFile);
            }
            IfFree(d->authNameLens);
#ifdef XDMCP
            XdmcpDisposeARRAY8(&d->peer);
            XdmcpDisposeARRAY8(&d->from);
            XdmcpDisposeARRAY8(&d->clientAddr);
#endif
            free((char *)d);
            break;
        }
    }
}
Exemple #9
0
static int
LoadAuthorization(void)
{
    FILE *f;
    Xauth *auth;
    int i;
    int count = 0;

    ShouldLoadAuth = FALSE;
    if (!authorization_file)
        return 0;

    errno = 0;
    f = Fopen(authorization_file, "r");
    if (!f) {
        LogMessageVerb(X_ERROR, 0,
                       "Failed to open authorization file \"%s\": %s\n",
                       authorization_file,
                       errno != 0 ? strerror(errno) : "Unknown error");
        return -1;
    }

    while ((auth = XauReadAuth(f)) != 0) {
        for (i = 0; i < NUM_AUTHORIZATION; i++) {
            if (protocols[i].name_length == auth->name_length &&
                memcmp(protocols[i].name, auth->name,
                       (int) auth->name_length) == 0 && protocols[i].Add) {
                ++count;
                (*protocols[i].Add) (auth->data_length, auth->data,
                                     FakeClientID(0));
            }
        }
        XauDisposeAuth(auth);
    }

    Fclose(f);
    return count;
}
Exemple #10
0
static int 
merge_entries(AuthList **firstp, AuthList *second, int *nnewp, int *nreplp)
{
    AuthList *a, *b, *first, *tail;
    int n = 0, nnew = 0, nrepl = 0;

    if (!second) return 0;

    if (!*firstp) {			/* if nothing to merge into */
	*firstp = second;
	for (tail = *firstp, n = 1; tail->next; n++, tail = tail->next) ;
	*nnewp = n;
	*nreplp = 0;
	return n;
    }

    first = *firstp;
    /*
     * find end of first list and stick second list on it
     */
    for (tail = first; tail->next; tail = tail->next) ;
    tail->next = second;

    /*
     * run down list freeing duplicate entries; if an entry is okay, then
     * bump the tail up to include it, otherwise, cut the entry out of
     * the chain.
     */
    for (b = second; b; ) {
	AuthList *next = b->next;	/* in case we free it */

	a = first;
	for (;;) {
	    if (match_auth (a->auth, b->auth)) {  /* found a duplicate */
		AuthList tmp;		/* swap it in for old one */
		tmp = *a;
		*a = *b;
		*b = tmp;
		a->next = b->next;
		XauDisposeAuth (b->auth);
		free ((char *) b);
		b = NULL;
		tail->next = next;
		nrepl++;
		nnew--;
		break;
	    }
	    if (a == tail) break;	/* if have looked at left side */
	    a = a->next;
	}
	if (b) {			/* if we didn't remove it */
	    tail = b;			/* bump end of first list */
	}
	b = next;
	n++;
	nnew++;
    }

    *nnewp = nnew;
    *nreplp = nrepl;
    return n;

}
Exemple #11
0
Xauth *
XauGetAuthByAddr (
#if NeedWidePrototypes
    unsigned int	family,
    unsigned int	address_length,
#else
    unsigned short	family,
    unsigned short	address_length,
#endif
    _Xconst char*	address,
#if NeedWidePrototypes
    unsigned int	number_length,
#else
    unsigned short	number_length,
#endif
    _Xconst char*	number,
#if NeedWidePrototypes
    unsigned int	name_length,
#else
    unsigned short	name_length,
#endif
    _Xconst char*	name)
{
    FILE    *auth_file;
    char    *auth_name;
    Xauth   *entry;

    auth_name = XauFileName ();
    if (!auth_name)
        return NULL;
    if (access (auth_name, R_OK) != 0)		/* checks REAL id */
        return NULL;
    auth_file = fopen (auth_name, "rb");
    if (!auth_file)
        return NULL;
    for (;;) {
        entry = XauReadAuth (auth_file);
        if (!entry)
            break;
        /*
         * Match when:
         *   either family or entry->family are FamilyWild or
         *    family and entry->family are the same and
         *     address and entry->address are the same
         *  and
         *   either number or entry->number are empty or
         *    number and entry->number are the same
         *  and
         *   either name or entry->name are empty or
         *    name and entry->name are the same
         */

        if ((family == FamilyWild || entry->family == FamilyWild ||
                (entry->family == family &&
                 address_length == entry->address_length &&
                 binaryEqual (entry->address, address, address_length))) &&
                (number_length == 0 || entry->number_length == 0 ||
                 (number_length == entry->number_length &&
                  binaryEqual (entry->number, number, number_length))) &&
                (name_length == 0 || entry->name_length == 0 ||
                 (entry->name_length == name_length &&
                  binaryEqual (entry->name, name, name_length))))
            break;
        XauDisposeAuth (entry);
    }
    (void) fclose (auth_file);
    return entry;
}
Exemple #12
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;
}
Exemple #13
0
int _xcb_get_auth_info(int fd, xcb_auth_info_t *info, int display)
{
    /* code adapted from Xlib/ConnDis.c, xtrans/Xtranssocket.c,
       xtrans/Xtransutils.c */
    struct sockaddr *sockname = NULL;
    int gotsockname = 0;
    Xauth *authptr = 0;
    int ret = 1;

    /* Some systems like hpux or Hurd do not expose peer names
     * for UNIX Domain Sockets, but this is irrelevant,
     * since compute_auth() ignores the peer name in this
     * case anyway.*/
    if ((sockname = get_peer_sock_name(getpeername, fd)) == NULL)
    {
        if ((sockname = get_peer_sock_name(getsockname, fd)) == NULL)
            return 0;   /* can only authenticate sockets */
        if (sockname->sa_family != AF_UNIX)
        {
            free(sockname);
            return 0;   /* except for AF_UNIX, sockets should have peernames */
        }
        gotsockname = 1;
    }

    authptr = get_authptr(sockname, display);
    if (authptr == 0)
    {
        free(sockname);
        return 0;   /* cannot find good auth data */
    }

    info->namelen = memdup(&info->name, authptr->name, authptr->name_length);
    if (!info->namelen)
        goto no_auth;   /* out of memory */

    if (!gotsockname)
    {
        free(sockname);

        if ((sockname = get_peer_sock_name(getsockname, fd)) == NULL)
        {
            free(info->name);
            goto no_auth;   /* can only authenticate sockets */
        }
    }

    ret = compute_auth(info, authptr, sockname);
    if(!ret)
    {
        free(info->name);
        goto no_auth;   /* cannot build auth record */
    }

    free(sockname);
    sockname = NULL;

    XauDisposeAuth(authptr);
    return ret;

 no_auth:
    free(sockname);

    info->name = 0;
    info->namelen = 0;
    XauDisposeAuth(authptr);
    return 0;
}
Exemple #14
0
Xauth *
XauGetBestAuthByAddr (
#if NeedWidePrototypes
    unsigned int	family,
    unsigned int	address_length,
#else
    unsigned short	family,
    unsigned short	address_length,
#endif
    _Xconst char*	address,
#if NeedWidePrototypes
    unsigned int	number_length,
#else
    unsigned short	number_length,
#endif
    _Xconst char*	number,
    int			types_length,
    char**		types,
    _Xconst int*	type_lengths)
{
    FILE    *auth_file;
    char    *auth_name;
    Xauth   *entry;
    Xauth   *best;
    int	    best_type;
    int	    type;

    auth_name = XauFileName ();
    if (!auth_name)
	return 0;
    if (access (auth_name, R_OK) != 0)		/* checks REAL id */
	return 0;
    auth_file = fopen (auth_name, "rb");
    if (!auth_file)
	return 0;


    best = 0;
    best_type = types_length;
    for (;;) {
	entry = XauReadAuth (auth_file);
	if (!entry)
	    break;
	/*
	 * Match when:
	 *   either family or entry->family are FamilyWild or
	 *    family and entry->family are the same and
	 *     address and entry->address are the same
	 *  and
	 *   either number or entry->number are empty or
	 *    number and entry->number are the same
	 *  and
	 *   either name or entry->name are empty or
	 *    name and entry->name are the same
	 */

	if ((family == FamilyWild || entry->family == FamilyWild ||
	     (entry->family == family &&
	     ((address_length == entry->address_length &&
	      binaryEqual (entry->address, address, (int)address_length))
	    ))) &&
	    (number_length == 0 || entry->number_length == 0 ||
	     (number_length == entry->number_length &&
	      binaryEqual (entry->number, number, (int)number_length))))
	{
	    if (best_type == 0)
	    {
		best = entry;
		break;
	    }
	    for (type = 0; type < best_type; type++)
		if (type_lengths[type] == entry->name_length &&
		    !(strncmp (types[type], entry->name, entry->name_length)))
		{
		    break;
		}
	    if (type < best_type)
	    {
		if (best)
		    XauDisposeAuth (best);
		best = entry;
		best_type = type;
		if (type == 0)
		    break;
		continue;
	    }
	}
	XauDisposeAuth (entry);
    }
    (void) fclose (auth_file);
    return best;
}
Exemple #15
0
static gboolean
gdm_authenticate_connection (GdmProtocolData *data)
{
#define GDM_MIT_MAGIC_COOKIE_LEN 16

        const char *xau_path;
        FILE       *f;
        Xauth      *xau;
        char       *display_number;
        gboolean    retval;

        if (data->auth_cookie) {
                char *msg;
                char *response;

                msg = g_strdup_printf (GDM_PROTOCOL_MSG_AUTHENTICATE " %s",
                                       data->auth_cookie);
                response = gdm_send_protocol_msg (data, msg);
                g_free (msg);
 
                if (response && !strcmp (response, "OK")) {
                        g_free (response);
                        return TRUE;
                } else {
                        g_free (response);
                        g_free (data->auth_cookie);
                        data->auth_cookie = NULL;
                }
        }

        if (!(xau_path = XauFileName ()))
                return FALSE;

        if (!(f = fopen (xau_path, "r")))
                return FALSE;

        retval = FALSE;
        display_number = get_display_number ();

        while ((xau = XauReadAuth (f))) {
                char  buffer[40]; /* 2*16 == 32, so 40 is enough */
                char *msg;
                char *response;
                int   i;

                if (xau->family != FamilyLocal ||
                    strncmp (xau->number, display_number, xau->number_length) ||
                    strncmp (xau->name, "MIT-MAGIC-COOKIE-1", xau->name_length) ||
                    xau->data_length != GDM_MIT_MAGIC_COOKIE_LEN) {
                        XauDisposeAuth (xau);
                        continue;
                }
                
                for (i = 0; i < GDM_MIT_MAGIC_COOKIE_LEN; i++)
                        g_snprintf (buffer + 2*i, 3, "%02x", (guint)(guchar)xau->data[i]);
                
                XauDisposeAuth (xau);
                
                msg = g_strdup_printf (GDM_PROTOCOL_MSG_AUTHENTICATE " %s", buffer);
                response = gdm_send_protocol_msg (data, msg);
                g_free (msg);
 
                if (response && !strcmp (response, "OK")) {
			data->auth_cookie = g_strdup (buffer);
                        g_free (response);
                        retval = TRUE;
                        break;
                }

                g_free (response);
        }

        g_free (display_number);
        
        fclose (f);

        return retval;

#undef GDM_MIT_MAGIC_COOKIE_LEN
}
/* If ADD-ENTRIES is true, merge our auth entries into the existing
 Xauthority file. If ADD-ENTRIES is false, remove our entries. */
static int
write_auth_file (int add_entries)
{
    char *home, newname[1024];
    int fd, ret;
    FILE *new_fh, *old_fh;
    addr_list *addr;
    Xauth *auth;
	
    if (auth_file == NULL)
		return FALSE;
	
    home = getenv ("HOME");
    if (home == NULL)
    {
		auth_file = NULL;
		return FALSE;
    }
	
    snprintf (newname, sizeof (newname), "%s/.XauthorityXXXXXX", home);
    mktemp (newname);
	
    if (XauLockAuth (auth_file, 1, 2, 10) != LOCK_SUCCESS)
    {
		/* FIXME: do something here? */
		
		auth_file = NULL;
		return FALSE;
    }
	
    fd = open (newname, O_WRONLY | O_CREAT | O_TRUNC, 0600);
    if (fd >= 0)
    {
		new_fh = fdopen (fd, "w");
		if (new_fh != NULL)
		{
			if (add_entries)
			{
				for (addr = addresses; addr != NULL; addr = addr->next)
				{
					XauWriteAuth (new_fh, &addr->auth);
				}
			}
			
			old_fh = fopen (auth_file, "r");
			if (old_fh != NULL)
			{
				while ((auth = XauReadAuth (old_fh)) != NULL)
				{
					if (!check_auth_item (auth))
						XauWriteAuth (new_fh, auth);
					XauDisposeAuth (auth);
				}
				fclose (old_fh);
			}
			
			fclose (new_fh);
			unlink (auth_file);
			
			ret = rename (newname, auth_file);
			
			if (ret != 0)
				auth_file = NULL;
			
			XauUnlockAuth (auth_file);
			return ret == 0;
		}
		
		close (fd);
    }
	
    XauUnlockAuth (auth_file);
    auth_file = NULL;
    return FALSE;
}
Exemple #17
0
static int
do_add(const char *inputfilename, int lineno, int argc, const char **argv)
{
    int n, nnew, nrepl;
    int len;
    const char *dpyname;
    const char *protoname;
    const char *hexkey;
    char *key;
    AuthList *list, *list_cur, *list_next;

    if (argc != 4 || !argv[1] || !argv[2] || !argv[3]) {
	prefix (inputfilename, lineno);
	badcommandline (argv[0]);
	return 1;
    }

    dpyname = argv[1];
    protoname = argv[2];
    hexkey = argv[3];

    len = strlen(hexkey);
    if (hexkey[0] == '"' && hexkey[len-1] == '"') {
	key = malloc(len-1);
	strncpy(key, hexkey+1, len-2);
	len -= 2;
    } else if (!strcmp(protoname, SECURERPC) ||
	       !strcmp(protoname, K5AUTH)) {
	key = malloc(len+1);
	strcpy(key, hexkey);
    } else {
	len = cvthexkey (hexkey, &key);
	if (len < 0) {
	    prefix (inputfilename, lineno);
	    fprintf (stderr,
		     "key contains odd number of or non-hex characters\n");
	    return 1;
	}
    }

    if (!get_displayname_auth (dpyname, &list)) {
	prefix (inputfilename, lineno);
	baddisplayname (dpyname, argv[0]);
	free (key);
	return 1;
    }

    /*
     * allow an abbreviation for common protocol names
     */
    if (strcmp (protoname, DEFAULT_PROTOCOL_ABBREV) == 0) {
	protoname = DEFAULT_PROTOCOL;
    }

    for (list_cur = list;  list_cur != NULL; list_cur = list_cur->next) {
	Xauth *auth = list_cur->auth;

	auth->name_length = strlen (protoname);
	auth->name = copystring (protoname, auth->name_length);
	if (!auth->name) {
	    prefix (inputfilename, lineno);
	    fprintf (stderr, "unable to allocate %d character protocol name\n",
		     auth->name_length);
	    for (list_cur = list; list_cur != NULL; list_cur = list_next) {
		list_next = list_cur->next;
		XauDisposeAuth(list_cur->auth);
		free(list_cur);
	    }
	    free (key);
	    return 1;
	}
	auth->data_length = len;
	auth->data = malloc(len);
	if (!auth->data) {
		prefix(inputfilename, lineno);
		fprintf(stderr, "unable to allocate %d bytes for key\n", len);
		for (list_cur = list; list_cur != NULL; list_cur = list_next) {
			list_next = list_cur->next;
			XauDisposeAuth(list_cur->auth);
			free(list_cur);
		}
		free(key);
		return 1;
	}
	memcpy(auth->data, key, len);
    }
    free(key);
    /*
     * merge it in; note that merge will deal with allocation
     */
    n = merge_entries (&xauth_head, list, &nnew, &nrepl);
    if (n <= 0) {
	prefix (inputfilename, lineno);
	fprintf (stderr, "unable to merge in added record\n");
	return 1;
    }

    xauth_modified = True;
    return 0;
}
Exemple #18
0
static int
iterdpy (const char *inputfilename, int lineno, int start,
	 int argc, const char *argv[],
	 YesNoFunc yfunc, YesNoFunc nfunc, char *data)
{
    int i;
    int status;
    int errors = 0;
    Xauth *tmp_auth;
    AuthList *proto_head, *proto;
    AuthList *l, *next;

    /*
     * iterate
     */
    for (i = start; i < argc; i++) {
	const char *displayname = argv[i];
	if (!get_displayname_auth (displayname, &proto_head)) {
	    prefix (inputfilename, lineno);
	    baddisplayname (displayname, argv[0]);
	    errors++;
	    continue;
	}
	status = 0;
	for (l = xauth_head; l; l = next) {
	    Bool matched = False;

	    /* l may be freed by remove_entry below. so save its contents */
	    next = l->next;
	    tmp_auth = copyAuth(l->auth);
	    for (proto = proto_head; proto; proto = proto->next) {
		if (match_auth_dpy (proto->auth, tmp_auth)) {
		    matched = True;
		    if (yfunc) {
			status = (*yfunc) (inputfilename, lineno,
					   tmp_auth, data);
			if (status < 0) break;
		    }
		}
	    }
	    XauDisposeAuth(tmp_auth);
	    if (matched == False) {
		if (nfunc) {
		    status = (*nfunc) (inputfilename, lineno,
				       l->auth, data);
		}
	    }
	    if (status < 0) break;
	}
	for (proto = proto_head; proto ; proto = next) {
	    next = proto->next;
	    if (proto->auth->address) free (proto->auth->address);
	    if (proto->auth->number) free (proto->auth->number);
	    free (proto->auth);
	    free (proto);
	}
	if (status < 0) {
	    errors -= status;		/* since status is negative */
	    break;
	}
    }

    return errors;
}
Exemple #19
0
Xauth *
XauGetBestAuthByAddr (
#if NeedWidePrototypes
    unsigned int	family,
    unsigned int	address_length,
#else
    unsigned short	family,
    unsigned short	address_length,
#endif
    _Xconst char*	address,
#if NeedWidePrototypes
    unsigned int	number_length,
#else
    unsigned short	number_length,
#endif
    _Xconst char*	number,
    int			types_length,
    char**		types,
    _Xconst int*	type_lengths)
{
    FILE    *auth_file;
    char    *auth_name;
    Xauth   *entry;
    Xauth   *best;
    int	    best_type;
    int	    type;
#ifdef hpux
    char		*fully_qual_address;
    unsigned short	fully_qual_address_length;
#endif

    auth_name = XauFileName ();
    if (!auth_name)
	return NULL;
    if (access (auth_name, R_OK) != 0)		/* checks REAL id */
	return NULL;
    auth_file = fopen (auth_name, "rb");
    if (!auth_file)
	return NULL;

#ifdef hpux
    if (family == FamilyLocal) {
#ifdef XTHREADS_NEEDS_BYNAMEPARAMS
	_Xgethostbynameparams hparams;
#endif
	struct hostent *hostp;

	/* make sure we try fully-qualified hostname */
	if ((hostp = _XGethostbyname(address,hparams)) != NULL) {
	    fully_qual_address = hostp->h_name;
	    fully_qual_address_length = strlen(fully_qual_address);
	}
	else
	{
	    fully_qual_address = NULL;
	    fully_qual_address_length = 0;
	}
    }
#endif /* hpux */

    best = NULL;
    best_type = types_length;
    for (;;) {
	entry = XauReadAuth (auth_file);
	if (!entry)
	    break;
	/*
	 * Match when:
	 *   either family or entry->family are FamilyWild or
	 *    family and entry->family are the same and
	 *     address and entry->address are the same
	 *  and
	 *   either number or entry->number are empty or
	 *    number and entry->number are the same
	 *  and
	 *   either name or entry->name are empty or
	 *    name and entry->name are the same
	 */

	if ((family == FamilyWild || entry->family == FamilyWild ||
	     (entry->family == family &&
	     ((address_length == entry->address_length &&
	      binaryEqual (entry->address, address, (int)address_length))
#ifdef hpux
	     || (family == FamilyLocal &&
		fully_qual_address_length == entry->address_length &&
	     	binaryEqual (entry->address, fully_qual_address,
		    (int) fully_qual_address_length))
#endif
	    ))) &&
	    (number_length == 0 || entry->number_length == 0 ||
	     (number_length == entry->number_length &&
	      binaryEqual (entry->number, number, (int)number_length))))
	{
	    if (best_type == 0)
	    {
		best = entry;
		break;
	    }
	    for (type = 0; type < best_type; type++)
		if (type_lengths[type] == entry->name_length &&
		    !(strncmp (types[type], entry->name, entry->name_length)))
		{
		    break;
		}
	    if (type < best_type)
	    {
		if (best)
		    XauDisposeAuth (best);
		best = entry;
		best_type = type;
		if (type == 0)
		    break;
		continue;
	    }
	}
	XauDisposeAuth (entry);
    }
    (void) fclose (auth_file);
    return best;
}
Exemple #20
0
/********************************************************************
 *
 * fork/exec a child pdm after setting up a message pipe. 
 */
void mgr_launch_pdm( XpPdmServiceRec *rec )
{
    int       i;
    struct sigaction svec;
    char      buf[1024];
    int       original_umask;
    char      *existing_name;
    FILE      *existing_file;
    Xauth     *entry;
    char      *envstr;


    /*
     * Setup message pipe.
     */
    if ( pipe(rec->message_pipe) == -1 ) {
	rec->pdm_exec_errorcode = g.pdm_start_error;
	sprintf( buf, PDMD_MSG_8, g.prog_name );
	rec->pdm_exec_errormessage = xpstrdup( buf );
	return;
    }

    rec->message_xtid = XtAppAddInput( g.context, rec->message_pipe[0],
			  (XtPointer) XtInputReadMask,
			  message_pipe_handler, (XtPointer) NULL );

    /*
     * See if a cookie file is needed.
     */
    if (rec->cookie_cnt) {
	/*
	 * Create new .Xauthority file.
	 */
	original_umask = umask (0077);      /* disallow non-owner access */
	tmpnam( rec->auth_filename );
	rec->auth_file = fopen( rec->auth_filename, "w" );

	if (rec->auth_file) {
	    /*
	     * Copy existing .Xauthority entries.
	     */
	    existing_name = XauFileName ();

	    if (existing_name) {
		if (access (existing_name, R_OK) == 0) {     /* checks REAL id */
		    existing_file = fopen (existing_name, "r");
		    if (existing_file) {
			for (;;) {
			    entry = XauReadAuth (existing_file);
			    if (!entry)
				break;

			    XauWriteAuth( rec->auth_file, entry );
			    XauDisposeAuth (entry);
			}
			fclose (existing_file);
		    }
		}
	    }

	    /*
	     * Merge in cookies recently sent.
	     */
	    for ( i = 0; i < rec->cookie_cnt; i++ ) {
		XauWriteAuth( rec->auth_file, rec->cookies[i] );
	    }

	    fclose( rec->auth_file );
	}
	original_umask = umask (original_umask);
    }


    rec->pid = fork();

    if ( rec->pid < 0 ) {
	rec->pdm_exec_errorcode = g.pdm_start_error;
	sprintf( buf, PDMD_MSG_9, g.prog_name );
	rec->pdm_exec_errormessage = xpstrdup( buf );
	return;
    }
    else if ( rec->pid == 0) {
	/*
	 * Child process.
	 */

	/*
	 * Hook stderr back to parent via message pipe.
	 */
	dup2(rec->message_pipe[1], 2);
	close(rec->message_pipe[0]);

	/*
	 * The child should have default behavior for all signals.
	 */
	sigemptyset(&svec.sa_mask);
	svec.sa_flags   = 0;
	svec.sa_handler = SIG_DFL;
	(void) sigaction(SIGCHLD, &svec, (struct sigaction *) NULL);

	for (i=3; i < FOPEN_MAX; i++) {
	    if ((i != rec->message_pipe[1]) && 
		(rec->auth_file && (i != fileno(rec->auth_file))))
	    {
		(void) fcntl (i, F_SETFD, 1);
	    }
	}

	/*
	 * Set the new locale for the child.
	 *
	 * note: the locale hint will be of the form:
	 *
	 *    name_spec[;registry_spec[;ver_spec[;encoding_spec]]]
	 *
	 * for now, just pull out the name_spec (e.g. 'C')
	 * and use it.   With a little work, a more complex
	 * syntax could be understood and the appropriate
	 * actions taken here rather than just wedging
	 * name_spec into setlocale() and hoping.
	 */
	if ( !(rec->locale_hint) ) {
	    /*
	     * Leave current locale alone.
	     */
	}
	else if ( strcmp( rec->locale_hint, "" ) ) {
	    /*
	     * Leave current locale alone.  Note that "" into
	     * setlocale says to go with default vs leave it alone.
	     */
	}
	else {
	    char *tptr1, *tptr2;

	    tptr1 = xpstrdup( rec->locale_hint );
            tptr2 = strchr( tptr1, ';' );
	    if (tptr2) *tptr2 = '\0';
	
	    setlocale( LC_ALL, tptr1 );
	    XFree( tptr1 );
	}

	/*
	 * Set XAUTHORITY env var if needed.
	 */
	if ((rec->cookie_cnt) && (rec->auth_filename) && (rec->auth_file)) {
	    envstr = Xmalloc( strlen(rec->auth_filename) + 12 );
	    sprintf( envstr, "XAUTHORITY=%s", rec->auth_filename );
	    putenv( envstr );
	}

	/*
	 * Start the child for real.
	 */
	(void) execvp(rec->pdm_exec_argvs[0], rec->pdm_exec_argvs);

	(void) fprintf (stderr, PDMD_MSG_10, g.prog_name, rec->pdm_exec_argvs[0]);

	/*
	 * tomg - need to deal with failed child start.
	 */
	exit(PDM_EXIT_ERROR);
    }
    else {
	/*
	 * Parent process.
	 */

	/*
	 * Close the write end of the pipe - only the child needs it.
	 */
	close(rec->message_pipe[1]);
	rec->message_pipe[1] = -1;
    }
}