Sophie

Sophie

distrib > * > 2008.0 > x86_64 > by-pkgid > 31e1296274b13d07b478531793fc3fda > files > 36

kdebase-3.5.9-4mdv2008.0.src.rpm

diff -r -N -u kdebase-3.5.8.orig/kdm/backend/client.c kdebase-3.5.8/kdm/backend/client.c
--- kdebase-3.5.8.orig/kdm/backend/client.c	2008-01-25 08:37:10.000000000 -0200
+++ kdebase-3.5.8/kdm/backend/client.c	2008-01-25 08:38:42.000000000 -0200
@@ -83,6 +83,10 @@
 # include <time.h>
 #endif /* USE_PAM || _AIX */
 
+#ifdef WITH_CONSOLE_KIT
+#include "consolekit.h"
+#endif
+
 /*
  * Session data, mostly what struct verify_info was for
  */
@@ -1100,8 +1104,13 @@
 static int removeCreds;
 #endif
 
+#ifdef WITH_CONSOLE_KIT
+int
+StartClient( const char *ck_session_cookie )
+#else
 int
 StartClient()
+#endif
 {
 	const char *home, *sessargs, *desksess;
 	char **env, *xma;
@@ -1197,6 +1206,11 @@
 	if (krbtkfile[0] != '\0')
 		env = setEnv( env, "KRBTKFILE", krbtkfile );
 #endif
+#ifdef WITH_CONSOLE_KIT
+	if (ck_session_cookie != NULL) {
+		env = setEnv ( env, "XDG_SESSION_COOKIE", ck_session_cookie );
+	}
+#endif
 	userEnviron = inheritEnv( env, envvars );
 	env = systemEnv( curuser );
 	systemEnviron = setEnv( env, "HOME", p->pw_dir );
diff -r -N -u kdebase-3.5.8.orig/kdm/backend/client.c.orig kdebase-3.5.8/kdm/backend/client.c.orig
--- kdebase-3.5.8.orig/kdm/backend/client.c.orig	1969-12-31 21:00:00.000000000 -0300
+++ kdebase-3.5.8/kdm/backend/client.c.orig	2008-01-25 08:37:10.000000000 -0200
@@ -0,0 +1,1736 @@
+/*
+
+Copyright 1988, 1998  The Open Group
+Copyright 2000-2004 Oswald Buddenhagen <ossi@kde.org>
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation.
+
+The above copyright notice and this permission notice shall be included
+in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of a copyright holder shall
+not be used in advertising or otherwise to promote the sale, use or
+other dealings in this Software without prior written authorization
+from the copyright holder.
+
+*/
+
+/*
+ * xdm - display manager daemon
+ * Author: Keith Packard, MIT X Consortium
+ *
+ * user verification and session initiation.
+ */
+
+#include "dm.h"
+#include "dm_auth.h"
+#include "dm_error.h"
+
+#include <sys/stat.h>
+#include <pwd.h>
+#include <grp.h>
+#ifdef SECURE_RPC
+# include <rpc/rpc.h>
+# include <rpc/key_prot.h>
+extern int key_setnet( struct key_netstarg *arg );
+#endif
+#ifdef K5AUTH
+# include <krb5/krb5.h>
+#endif
+#ifdef HAVE_SETUSERCONTEXT
+# include <login_cap.h>
+# define USE_LOGIN_CAP 1
+#endif
+#ifdef USE_PAM
+# ifdef HAVE_PAM_PAM_APPL_H
+#  include <pam/pam_appl.h>
+# else
+#  include <security/pam_appl.h>
+# endif
+#elif defined(_AIX) /* USE_PAM */
+# include <login.h>
+# include <usersec.h>
+extern int loginrestrictions( const char *Name, const int Mode, const char *Tty, char **Msg );
+extern int loginfailed( const char *User, const char *Host, const char *Tty );
+extern int loginsuccess( const char *User, const char *Host, const char *Tty, char **Msg );
+#else /* USE_PAM || _AIX */
+# ifdef USESHADOW
+#  include <shadow.h>
+# endif
+# ifdef KERBEROS
+#  include <sys/param.h>
+#  include <krb.h>
+#  ifndef NO_AFS
+#   include <kafs.h>
+#  endif
+# endif
+/* for nologin */
+# include <sys/types.h>
+# include <unistd.h>
+/* for expiration */
+# include <time.h>
+#endif /* USE_PAM || _AIX */
+
+/*
+ * Session data, mostly what struct verify_info was for
+ */
+char *curuser;
+char *curpass;
+char *curtype;
+char *newpass;
+char **userEnviron;
+char **systemEnviron;
+static int curuid;
+static int curgid;
+int cursource;
+
+char *dmrcuser;
+char *curdmrc;
+char *newdmrc;
+
+static struct passwd *p;
+#ifdef USE_PAM
+static pam_handle_t *pamh;
+#elif defined(_AIX)
+static char tty[16], hostname[100];
+#else
+# ifdef USESHADOW
+static struct spwd *sp;
+# endif
+# ifdef KERBEROS
+static char krbtkfile[MAXPATHLEN];
+# endif
+#endif
+
+#define V_RET_AUTH \
+		do { \
+			PrepErrorGreet (); \
+			GSendInt (V_AUTH); \
+			return 0; \
+		} while(0)
+
+#define V_RET_FAIL(m) \
+		do { \
+			PrepErrorGreet (); \
+			GSendInt (V_MSG_ERR); \
+			GSendStr (m); \
+			GSendInt (V_FAIL); \
+			return 0; \
+		} while(0)
+
+#ifdef USE_PAM
+
+# ifdef PAM_MESSAGE_NONCONST
+typedef struct pam_message pam_message_type;
+typedef void *pam_gi_type;
+# else
+typedef const struct pam_message pam_message_type;
+typedef const void *pam_gi_type;
+# endif
+
+struct pam_data {
+	GConvFunc gconv;
+	int usecur;
+	int abort;
+};
+
+static int
+PAM_conv( int num_msg,
+          pam_message_type **msg,
+          struct pam_response **resp,
+          void *appdata_ptr )
+{
+	int count;
+	struct pam_response *reply;
+	struct pam_data *pd = (struct pam_data *)appdata_ptr;
+
+	if (!(reply = Calloc( num_msg, sizeof(*reply) )))
+		return PAM_CONV_ERR;
+
+	ReInitErrorLog();
+	Debug( "PAM_conv\n" );
+	for (count = 0; count < num_msg; count++)
+		switch (msg[count]->msg_style) {
+		case PAM_TEXT_INFO:
+			Debug( " PAM_TEXT_INFO: %s\n", msg[count]->msg );
+			PrepErrorGreet();
+			GSendInt( V_MSG_INFO );
+			GSendStr( msg[count]->msg );
+			continue;
+		case PAM_ERROR_MSG:
+			Debug( " PAM_ERROR_MSG: %s\n", msg[count]->msg );
+			PrepErrorGreet();
+			GSendInt( V_MSG_ERR );
+			GSendStr( msg[count]->msg );
+			continue;
+		default:
+			/* could do better error handling here, but see below ... */
+			if (pd->usecur) {
+				switch (msg[count]->msg_style) {
+				/* case PAM_PROMPT_ECHO_ON: cannot happen */
+				case PAM_PROMPT_ECHO_OFF:
+					Debug( " PAM_PROMPT_ECHO_OFF (usecur): %s\n", msg[count]->msg );
+					if (!curpass)
+						pd->gconv( GCONV_PASS, 0 );
+					StrDup( &reply[count].resp, curpass );
+					break;
+				default:
+					LogError( "Unknown PAM message style <%d>\n", msg[count]->msg_style );
+					goto conv_err;
+				}
+			} else {
+				switch (msg[count]->msg_style) {
+				case PAM_PROMPT_ECHO_ON:
+					Debug( " PAM_PROMPT_ECHO_ON: %s\n", msg[count]->msg );
+					reply[count].resp = pd->gconv( GCONV_NORMAL, msg[count]->msg );
+					break;
+				case PAM_PROMPT_ECHO_OFF:
+					Debug( " PAM_PROMPT_ECHO_OFF: %s\n", msg[count]->msg );
+					reply[count].resp = pd->gconv( GCONV_HIDDEN, msg[count]->msg );
+					break;
+#ifdef PAM_BINARY_PROMPT
+				case PAM_BINARY_PROMPT:
+					Debug( " PAM_BINARY_PROMPT\n" );
+					reply[count].resp = pd->gconv( GCONV_BINARY, msg[count]->msg );
+					break;
+#endif
+				default:
+					LogError( "Unknown PAM message style <%d>\n", msg[count]->msg_style );
+					goto conv_err;
+				}
+			}
+			if (!reply[count].resp) {
+				Debug( "  PAM_conv aborted\n" );
+				pd->abort = TRUE;
+				goto conv_err;
+			}
+			reply[count].resp_retcode = PAM_SUCCESS; /* unused in linux-pam */
+		}
+	Debug( " PAM_conv success\n" );
+	*resp = reply;
+	return PAM_SUCCESS;
+
+  conv_err:
+	for (; count >= 0; count--)
+		if (reply[count].resp)
+			switch (msg[count]->msg_style) {
+			case PAM_PROMPT_ECHO_ON:
+			case PAM_PROMPT_ECHO_OFF: /* could wipe ... */
+#ifdef PAM_BINARY_PROMPT
+			case PAM_BINARY_PROMPT: /* ... that too ... */
+#endif
+				free( reply[count].resp );
+				break;
+			}
+	free( reply );
+	return PAM_CONV_ERR;
+}
+
+static int
+PAM_conv_null( int num_msg,
+               pam_message_type **msg,
+               struct pam_response **resp,
+               void *appdata_ptr ATTR_UNUSED )
+{
+	int count;
+	struct pam_response *reply;
+
+	if (!(reply = Calloc( num_msg, sizeof(*reply) )))
+		return PAM_CONV_ERR;
+
+	ReInitErrorLog();
+	Debug( "PAM_conv_null\n" );
+	for (count = 0; count < num_msg; count++) {
+		switch (msg[count]->msg_style) {
+		case PAM_TEXT_INFO:
+			Debug( " PAM_TEXT_INFO: %s\n", msg[count]->msg );
+			continue;
+		case PAM_ERROR_MSG:
+			LogError( "PAM error message: %s\n", msg[count]->msg );
+			continue;
+		default:
+			/* unknown */
+			Debug( " PAM_<%d>\n", msg[count]->msg_style );
+			free( reply );
+			return PAM_CONV_ERR;
+		}
+		reply[count].resp_retcode = PAM_SUCCESS; /* unused in linux-pam */
+	}
+	Debug( " PAM_conv_null success\n" );
+	*resp = reply;
+	return PAM_SUCCESS;
+}
+
+# ifdef PAM_FAIL_DELAY
+static void
+fail_delay( int retval ATTR_UNUSED, unsigned usec_delay ATTR_UNUSED,
+            void *appdata_ptr ATTR_UNUSED )
+{}
+# endif
+
+static int
+doPAMAuth( const char *psrv, struct pam_data *pdata )
+{
+	pam_gi_type pitem;
+	struct pam_conv pconv;
+	int pretc;
+
+	pdata->abort = FALSE;
+	pconv.conv = PAM_conv;
+	pconv.appdata_ptr = (void *)pdata;
+	Debug( " PAM service %s\n", psrv );
+	if ((pretc = pam_start( psrv, curuser, &pconv, &pamh )) != PAM_SUCCESS)
+		goto pam_bail2;
+	if ((pretc = pam_set_item( pamh, PAM_TTY, td->name )) != PAM_SUCCESS) {
+	  pam_bail:
+		pam_end( pamh, pretc );
+		pamh = 0;
+	  pam_bail2:
+		ReInitErrorLog();
+		LogError( "PAM error: %s\n", pam_strerror( 0, pretc ) );
+		V_RET_FAIL( 0 );
+	}
+	if ((td->displayType & d_location) == dForeign) {
+		char *cp = strchr( td->name, ':' );
+		*cp = 0;
+		pretc = pam_set_item( pamh, PAM_RHOST, td->name );
+		*cp = ':';
+		if (pretc != PAM_SUCCESS)
+			goto pam_bail;
+	}
+# ifdef PAM_FAIL_DELAY
+	pam_set_item( pamh, PAM_FAIL_DELAY, (void *)fail_delay );
+# endif
+	ReInitErrorLog();
+
+	Debug( " pam_authenticate() ...\n" );
+	pretc = pam_authenticate( pamh,
+	                          td->allowNullPasswd ? 0 : PAM_DISALLOW_NULL_AUTHTOK );
+	ReInitErrorLog();
+	Debug( " pam_authenticate() returned: %s\n", pam_strerror( pamh, pretc ) );
+	if (pdata->abort) {
+		pam_end( pamh, PAM_SUCCESS );
+		pamh = 0;
+		return 0;
+	}
+	if (!curuser) {
+		Debug( " asking PAM for user ...\n" );
+		pam_get_item( pamh, PAM_USER, &pitem );
+		ReInitErrorLog();
+		StrDup( &curuser, (const char *)pitem );
+		GSendInt( V_PUT_USER );
+		GSendStr( curuser );
+	}
+	if (pretc != PAM_SUCCESS) {
+		switch (pretc) {
+		case PAM_USER_UNKNOWN:
+		case PAM_AUTH_ERR:
+		case PAM_MAXTRIES: /* should handle this better ... */
+		case PAM_AUTHINFO_UNAVAIL: /* returned for unknown users ... bogus */
+			pam_end( pamh, pretc );
+			pamh = 0;
+			V_RET_AUTH;
+		default:
+			pam_end( pamh, pretc );
+			pamh = 0;
+			V_RET_FAIL( 0 );
+		}
+	}
+	return 1;
+}
+
+#endif /* USE_PAM */
+
+static int
+#if defined(USE_PAM) || defined(_AIX)
+AccNoPass( const char *un )
+{
+	struct passwd *pw = 0;
+#else
+AccNoPass( const char *un, struct passwd *pw )
+{
+#endif
+	struct group *gr;
+	char **fp;
+	int hg;
+
+	if (!*un)
+		return 0;
+
+	if (cursource != PWSRC_MANUAL)
+		return 1;
+
+	for (hg = 0, fp = td->noPassUsers; *fp; fp++)
+		if (**fp == '@')
+			hg = 1;
+		else if (!strcmp( un, *fp ))
+			return 1;
+		else if (!strcmp( "*", *fp )) {
+#if defined(USE_PAM) || defined(_AIX)
+			if (!(pw = getpwnam( un )))
+				return 0;
+#endif
+			if (pw->pw_uid)
+				return 1;
+		}
+
+#if defined(USE_PAM) || defined(_AIX)
+	if (hg && (pw || (pw = getpwnam( un )))) {
+#else
+	if (hg) {
+#endif
+		for (setgrent(); (gr = getgrent()); )
+			for (fp = td->noPassUsers; *fp; fp++)
+				if (**fp == '@' && !strcmp( gr->gr_name, *fp + 1 )) {
+					if (pw->pw_gid == gr->gr_gid) {
+						endgrent();
+						return 1;
+					}
+					for (; *gr->gr_mem; gr->gr_mem++)
+						if (!strcmp( un, *gr->gr_mem )) {
+							endgrent();
+							return 1;
+						}
+				}
+		endgrent();
+	}
+
+	return 0;
+}
+
+#if !defined(USE_PAM) && !defined(_AIX) && defined(USE_LOGIN_CAP)
+# define LC_RET0 do { login_close(lc); return 0; } while(0)
+#else
+# define LC_RET0 return 0
+#endif
+
+int
+Verify( GConvFunc gconv, int rootok )
+{
+#ifdef USE_PAM
+	const char *psrv;
+	struct pam_data pdata;
+	int pretc, pnopass;
+	char psrvb[64];
+#elif defined(_AIX)
+	char *msg, *curret;
+	int i, reenter;
+#else
+	struct stat st;
+	const char *nolg;
+	char *buf;
+	int fd;
+# ifdef HAVE_GETUSERSHELL
+	char *s;
+# endif
+# if defined(HAVE_STRUCT_PASSWD_PW_EXPIRE) || defined(USESHADOW)
+	int tim, expir, warntime, quietlog;
+# endif
+# ifdef USE_LOGIN_CAP
+#  ifdef HAVE_LOGIN_GETCLASS
+	login_cap_t *lc;
+#  else
+	struct login_cap *lc;
+#  endif
+# endif
+#endif
+
+	Debug( "Verify ...\n" );
+
+#ifdef USE_PAM
+
+	pnopass = FALSE;
+	if (!strcmp( curtype, "classic" )) {
+		if (!gconv( GCONV_USER, 0 ))
+			return 0;
+		if (AccNoPass( curuser )) {
+			gconv( GCONV_PASS_ND, 0 );
+			if (!*curpass) {
+				pnopass = TRUE;
+				sprintf( psrvb, "%.31s-np", PAMService );
+				psrv = psrvb;
+			} else
+				psrv = PAMService;
+		} else
+			psrv = PAMService;
+		pdata.usecur = TRUE;
+	} else {
+		sprintf( psrvb, "%.31s-%.31s", PAMService, curtype );
+		psrv = psrvb;
+		pdata.usecur = FALSE;
+	}
+	pdata.gconv = gconv;
+	if (!doPAMAuth( psrv, &pdata ))
+		return 0;
+
+#elif defined(_AIX)
+
+	if ((td->displayType & d_location) == dForeign) {
+		char *tmpch;
+		strncpy( hostname, td->name, sizeof(hostname) - 1 );
+		hostname[sizeof(hostname)-1] = '\0';
+		if ((tmpch = strchr( hostname, ':' )))
+			*tmpch = '\0';
+	} else
+		hostname[0] = '\0';
+
+	/* tty names should only be 15 characters long */
+# if 0
+	for (i = 0; i < 15 && td->name[i]; i++) {
+		if (td->name[i] == ':' || td->name[i] == '.')
+			tty[i] = '_';
+		else
+			tty[i] = td->name[i];
+	}
+	tty[i] = '\0';
+# else
+	memcpy( tty, "/dev/xdm/", 9 );
+	for (i = 0; i < 6 && td->name[i]; i++) {
+		if (td->name[i] == ':' || td->name[i] == '.')
+			tty[9 + i] = '_';
+		else
+			tty[9 + i] = td->name[i];
+	}
+	tty[9 + i] = '\0';
+# endif
+
+	if (!strcmp( curtype, "classic" )) {
+		if (!gconv( GCONV_USER, 0 ))
+			return 0;
+		if (AccNoPass( curuser )) {
+			gconv( GCONV_PASS_ND, 0 );
+			if (!*curpass) {
+				Debug( "accepting despite empty password\n" );
+				goto done;
+			}
+		} else
+			if (!gconv( GCONV_PASS, 0 ))
+				return 0;
+		enduserdb();
+		msg = NULL;
+		if ((i = authenticate( curuser, curpass, &reenter, &msg ))) {
+			Debug( "authenticate() failed: %s\n", msg );
+			if (msg)
+				free( msg );
+			loginfailed( curuser, hostname, tty );
+			if (i == ENOENT || i == ESAD)
+				V_RET_AUTH;
+			else
+				V_RET_FAIL( 0 );
+		}
+		if (reenter) {
+			LogError( "authenticate() requests more data: %s\n", msg );
+			free( msg );
+			V_RET_FAIL( 0 );
+		}
+	} else if (!strcmp( curtype, "generic" )) {
+		if (!gconv( GCONV_USER, 0 ))
+			return 0;
+		for (curret = 0;;) {
+			msg = NULL;
+			if ((i = authenticate( curuser, curret, &reenter, &msg ))) {
+				Debug( "authenticate() failed: %s\n", msg );
+				if (msg)
+					free( msg );
+				loginfailed( curuser, hostname, tty );
+				if (i == ENOENT || i == ESAD)
+					V_RET_AUTH;
+				else
+					V_RET_FAIL( 0 );
+			}
+			if (curret)
+				free( curret );
+			if (!reenter)
+				break;
+			if (!(curret = gconv( GCONV_HIDDEN, msg )))
+				return 0;
+			free( msg );
+		}
+	} else {
+		LogError( "Unsupported authentication type %\"s requested\n", curtype );
+		V_RET_FAIL( 0 );
+	}
+	if (msg) {
+		PrepErrorGreet();
+		GSendInt( V_MSG_INFO );
+		GSendStr( msg );
+		free( msg );
+	}
+
+  done:
+
+#else
+
+	if (strcmp( curtype, "classic" )) {
+		LogError( "Unsupported authentication type %\"s requested\n", curtype );
+		V_RET_FAIL( 0 );
+	}
+
+	if (!gconv( GCONV_USER, 0 ))
+		return 0;
+
+	if (!(p = getpwnam( curuser ))) {
+		Debug( "getpwnam() failed.\n" );
+		V_RET_AUTH;
+	}
+# ifdef __linux__ /* only Linux? */
+	if (p->pw_passwd[0] == '!' || p->pw_passwd[0] == '*') {
+		Debug( "account is locked\n" );
+		V_RET_AUTH;
+	}
+# endif
+
+# ifdef USESHADOW
+	if ((sp = getspnam( curuser )))
+		p->pw_passwd = sp->sp_pwdp;
+	else
+		Debug( "getspnam() failed: %m. Are you root?\n" );
+# endif
+
+	if (!*p->pw_passwd) {
+		if (!td->allowNullPasswd) {
+			Debug( "denying user with empty password\n" );
+			V_RET_AUTH;
+		}
+		goto nplogin;
+	}
+
+	if (AccNoPass( curuser, p )) {
+	  nplogin:
+		gconv( GCONV_PASS_ND, 0 );
+		if (!*curpass) {
+			Debug( "accepting password-less login\n" );
+			goto done;
+		}
+	} else
+		if (!gconv( GCONV_PASS, 0 ))
+			return 0;
+
+# ifdef KERBEROS
+	if (p->pw_uid) {
+		int ret;
+		char realm[REALM_SZ];
+
+		if (krb_get_lrealm( realm, 1 )) {
+			LogError( "Can't get KerberosIV realm.\n" );
+			V_RET_FAIL( 0 );
+		}
+
+		sprintf( krbtkfile, "%s.%.*s", TKT_ROOT, MAXPATHLEN - strlen( TKT_ROOT ) - 2, td->name );
+		krb_set_tkt_string( krbtkfile );
+		unlink( krbtkfile );
+
+		ret = krb_verify_user( curuser, "", realm, curpass, 1, "rcmd" );
+		if (ret == KSUCCESS) {
+			chown( krbtkfile, p->pw_uid, p->pw_gid );
+			Debug( "KerberosIV verify succeeded\n" );
+			goto done;
+		} else if (ret != KDC_PR_UNKNOWN && ret != SKDC_CANT) {
+			LogError( "KerberosIV verification failure %\"s for %s\n",
+			          krb_get_err_text( ret ), curuser );
+			krbtkfile[0] = '\0';
+			V_RET_FAIL( 0 );
+		}
+		Debug( "KerberosIV verify failed: %s\n", krb_get_err_text( ret ) );
+	}
+	krbtkfile[0] = '\0';
+# endif	 /* KERBEROS */
+
+# if defined(ultrix) || defined(__ultrix__)
+	if (authenticate_user( p, curpass, NULL ) < 0)
+# elif defined(HAVE_CRYPT)
+	if (strcmp( crypt( curpass, p->pw_passwd ), p->pw_passwd ))
+# else
+	if (strcmp( curpass, p->pw_passwd ))
+# endif
+	{
+		Debug( "password verify failed\n" );
+		V_RET_AUTH;
+	}
+
+  done:
+
+#endif /* !defined(USE_PAM) && !defined(_AIX) */
+
+	Debug( "restrict %s ...\n", curuser );
+
+#if defined(USE_PAM) || defined(_AIX)
+	if (!(p = getpwnam( curuser ))) {
+		LogError( "getpwnam(%s) failed.\n", curuser );
+		V_RET_FAIL( 0 );
+	}
+#endif
+	if (!p->pw_uid) {
+		if (!rootok && !td->allowRootLogin)
+			V_RET_FAIL( "Root logins are not allowed" );
+		return 1; /* don't deny root to log in */
+	}
+
+#ifdef USE_PAM
+
+	Debug( " pam_acct_mgmt() ...\n" );
+	pretc = pam_acct_mgmt( pamh, 0 );
+	ReInitErrorLog();
+	Debug( " pam_acct_mgmt() returned: %s\n", pam_strerror( pamh, pretc ) );
+	if (pretc == PAM_NEW_AUTHTOK_REQD) {
+		pdata.usecur = FALSE;
+		pdata.gconv = conv_interact;
+		/* pam will have output a message already, so no PrepErrorGreet () */
+		if (gconv != conv_interact || pnopass) {
+			pam_end( pamh, PAM_SUCCESS );
+			pamh = 0;
+			GSendInt( V_CHTOK_AUTH );
+			/* this cannot auth the wrong user, as only classic auths get here */
+			while (!doPAMAuth( PAMService, &pdata ))
+				if (pdata.abort)
+					return 0;
+			GSendInt( V_PRE_OK );
+		} else
+			GSendInt( V_CHTOK );
+		for (;;) {
+			Debug( " pam_chauthtok() ...\n" );
+			pretc = pam_chauthtok( pamh, PAM_CHANGE_EXPIRED_AUTHTOK );
+			ReInitErrorLog();
+			Debug( " pam_chauthtok() returned: %s\n", pam_strerror( pamh, pretc ) );
+			if (pdata.abort) {
+				pam_end( pamh, PAM_SUCCESS );
+				pamh = 0;
+				return 0;
+			}
+			if (pretc == PAM_SUCCESS)
+				break;
+			/* effectively there is only PAM_AUTHTOK_ERR */
+			GSendInt( V_FAIL );
+		}
+		if (curpass)
+			free( curpass );
+		curpass = newpass;
+		newpass = 0;
+	} else if (pretc != PAM_SUCCESS) {
+		pam_end( pamh, pretc );
+		pamh = 0;
+		V_RET_AUTH;
+	}
+
+#elif defined(_AIX) /* USE_PAM */
+
+	msg = NULL;
+	if (loginrestrictions( curuser,
+	                       ((td->displayType & d_location) == dForeign) ? S_RLOGIN : S_LOGIN,
+	                       tty, &msg ) == -1)
+	{
+		Debug( "loginrestrictions() - %s\n", msg ? msg : "error" );
+		loginfailed( curuser, hostname, tty );
+		PrepErrorGreet();
+		if (msg) {
+			GSendInt( V_MSG_ERR );
+			GSendStr( msg );
+		}
+		GSendInt( V_AUTH );
+		return 0;
+	}
+	if (msg)
+		free( (void *)msg );
+
+#else /* USE_PAM || _AIX */
+
+# ifdef HAVE_GETUSERSHELL
+	for (;;) {
+		if (!(s = getusershell())) {
+			Debug( "shell not in /etc/shells\n" );
+			endusershell();
+			V_RET_FAIL( "Your login shell is not listed in /etc/shells" );
+		}
+		if (!strcmp( s, p->pw_shell )) {
+			endusershell();
+			break;
+		}
+	}
+# endif
+
+# ifdef USE_LOGIN_CAP
+#  ifdef HAVE_LOGIN_GETCLASS
+	lc = login_getclass( p->pw_class );
+#  else
+	lc = login_getpwclass( p );
+#  endif
+	if (!lc)
+		V_RET_FAIL( 0 );
+# endif
+
+
+/* restrict_nologin */
+# ifndef _PATH_NOLOGIN
+#  define _PATH_NOLOGIN "/etc/nologin"
+# endif
+
+	if ((
+# ifdef USE_LOGIN_CAP
+	     /* Do we ignore a nologin file? */
+	     !login_getcapbool( lc, "ignorenologin", 0 )) &&
+	    (!stat( (nolg = login_getcapstr( lc, "nologin", "", NULL )), &st ) ||
+# endif
+		 !stat( (nolg = _PATH_NOLOGIN), &st )))
+	{
+		PrepErrorGreet();
+		GSendInt( V_MSG_ERR );
+		if (st.st_size && (fd = open( nolg, O_RDONLY )) >= 0) {
+			if ((buf = Malloc( st.st_size + 1 ))) {
+				if (read( fd, buf, st.st_size ) == st.st_size) {
+					buf[st.st_size] = 0;
+					GSendStr( buf );
+					free( buf );
+					close( fd );
+					GSendInt( V_FAIL );
+					LC_RET0;
+				}
+				free( buf );
+			}
+			close( fd );
+		}
+		GSendStr( "Logins are not allowed at the moment.\nTry again later" );
+		GSendInt( V_FAIL );
+		LC_RET0;
+	}
+
+
+/* restrict_nohome */
+# ifdef USE_LOGIN_CAP
+	if (login_getcapbool( lc, "requirehome", 0 )) {
+		struct stat st;
+		if (!*p->pw_dir || stat( p->pw_dir, &st ) || st.st_uid != p->pw_uid) {
+			PrepErrorGreet();
+			GSendInt( V_MSG_ERR );
+			GSendStr( "Home folder not available" );
+			GSendInt( V_FAIL );
+			LC_RET0;
+		}
+	}
+# endif
+
+
+/* restrict_time */
+# ifdef USE_LOGIN_CAP
+#  ifdef HAVE_AUTH_TIMEOK
+	if (!auth_timeok( lc, time( NULL ) )) {
+		PrepErrorGreet();
+		GSendInt( V_MSG_ERR );
+		GSendStr( "You are not allowed to login at the moment" );
+		GSendInt( V_FAIL );
+		LC_RET0;
+	}
+#  endif
+# endif
+
+
+/* restrict_expired; this MUST be the last one */
+# if defined(HAVE_STRUCT_PASSWD_PW_EXPIRE) || defined(USESHADOW)
+
+#  if !defined(HAVE_STRUCT_PASSWD_PW_EXPIRE) || (!defined(USE_LOGIN_CAP) && defined(USESHADOW))
+	if (sp)
+#  endif
+	{
+
+#  define DEFAULT_WARN	(2L * 7L)  /* Two weeks */
+
+		tim = time( NULL ) / 86400L;
+
+#  ifdef USE_LOGIN_CAP
+		quietlog = login_getcapbool( lc, "hushlogin", 0 );
+		warntime = login_getcaptime( lc, "warnexpire",
+		                             DEFAULT_WARN * 86400L,
+		                             DEFAULT_WARN * 86400L ) / 86400L;
+#  else
+		quietlog = 0;
+#	ifdef USESHADOW
+		warntime = sp->sp_warn != -1 ? sp->sp_warn : DEFAULT_WARN;
+#	else
+		warntime = DEFAULT_WARN;
+#	endif
+#  endif
+
+#  ifdef HAVE_STRUCT_PASSWD_PW_EXPIRE
+		if (p->pw_expire) {
+			expir = p->pw_expire / 86400L;
+#  else
+		if (sp->sp_expire != -1) {
+			expir = sp->sp_expire;
+#  endif
+			if (tim > expir) {
+				PrepErrorGreet();
+				GSendInt( V_MSG_ERR );
+				GSendStr( "Your account has expired;"
+				          " please contact your system administrator" );
+				GSendInt( V_FAIL );
+				LC_RET0;
+			} else if (tim > (expir - warntime) && !quietlog) {
+				ASPrintf( &buf,
+				          "Warning: your account will expire in %d day(s)",
+				          expir - tim );
+				if (buf) {
+					PrepErrorGreet();
+					GSendInt( V_MSG_INFO );
+					GSendStr( buf );
+					free( buf );
+				}
+			}
+		}
+
+#  ifdef HAVE_STRUCT_PASSWD_PW_EXPIRE
+		if (p->pw_change) {
+			expir = p->pw_change / 86400L;
+#  else
+		if (!sp->sp_lstchg) {
+			PrepErrorGreet();
+			GSendInt( V_MSG_ERR );
+			GSendStr( "You are required to change your password immediately"
+			          " (root enforced)" );
+			/* XXX todo password change */
+			GSendInt( V_FAIL );
+			LC_RET0;
+		} else if (sp->sp_max != -1) {
+			expir = sp->sp_lstchg + sp->sp_max;
+			if (sp->sp_inact != -1 && tim > expir + sp->sp_inact) {
+				PrepErrorGreet();
+				GSendInt( V_MSG_ERR );
+				GSendStr( "Your account has expired;"
+				          " please contact your system administrator" );
+				GSendInt( V_FAIL );
+				LC_RET0;
+			}
+#  endif
+			if (tim > expir) {
+				PrepErrorGreet();
+				GSendInt( V_MSG_ERR );
+				GSendStr( "You are required to change your password immediately"
+				          " (password aged)" );
+				/* XXX todo password change */
+				GSendInt( V_FAIL );
+				LC_RET0;
+			} else if (tim > (expir - warntime) && !quietlog) {
+				ASPrintf( &buf,
+				          "Warning: your password will expire in %d day(s)",
+				          expir - tim );
+				if (buf) {
+					PrepErrorGreet();
+					GSendInt( V_MSG_INFO );
+					GSendStr( buf );
+					free( buf );
+				}
+			}
+		}
+
+	}
+
+# endif /* HAVE_STRUCT_PASSWD_PW_EXPIRE || USESHADOW */
+
+# ifdef USE_LOGIN_CAP
+	login_close( lc );
+# endif
+
+#endif /* USE_PAM || _AIX */
+
+	return 1;
+
+}
+
+
+static const char *envvars[] = {
+	"TZ", /* SYSV and SVR4, but never hurts */
+#ifdef _AIX
+	"AUTHSTATE", /* for kerberos */
+#endif
+	NULL
+};
+
+
+#if defined(USE_PAM) && defined(HAVE_INITGROUPS)
+int num_saved_gids;
+gid_t saved_gids[NGROUPS];
+
+static int
+saveGids( void )
+{
+	if ((num_saved_gids = getgroups( as(saved_gids), saved_gids )) < 0) {
+		LogError( "saving groups failed: %m\n" );
+		return 0;
+	}
+	return 1;
+}
+
+static int
+restoreGids( void )
+{
+	if (setgroups( num_saved_gids, saved_gids ) < 0) {
+		LogError( "restoring groups failed: %m\n" );
+		return 0;
+	}
+	if (setgid( p->pw_gid ) < 0) {
+		LogError( "restoring gid failed: %m\n" );
+		return 0;
+	}
+	return 1;
+}
+#endif /* USE_PAM && HAVE_INITGROUPS */
+
+static int
+resetGids( void )
+{
+#ifdef HAVE_INITGROUPS
+	if (setgroups( 0, &p->pw_gid /* anything */ ) < 0) {
+		LogError( "restoring groups failed: %m\n" );
+		return 0;
+	}
+#endif
+	if (setgid( 0 ) < 0) {
+		LogError( "restoring gid failed: %m\n" );
+		return 0;
+	}
+	return 1;
+}
+
+static int
+SetGid( const char *name, int gid )
+{
+	if (setgid( gid ) < 0) {
+		LogError( "setgid(%d) (user %s) failed: %m\n", gid, name );
+		return 0;
+	}
+#ifdef HAVE_INITGROUPS
+	if (initgroups( name, gid ) < 0) {
+		LogError( "initgroups for %s failed: %m\n", name );
+		setgid( 0 );
+		return 0;
+	}
+#endif	 /* QNX4 doesn't support multi-groups, no initgroups() */
+	return 1;
+}
+
+static int
+SetUid( const char *name, int uid )
+{
+	if (setuid( uid ) < 0) {
+		LogError( "setuid(%d) (user %s) failed: %m\n", uid, name );
+		return 0;
+	}
+	return 1;
+}
+
+static int
+SetUser( const char *name, int uid, int gid )
+{
+	if (SetGid( name, gid )) {
+		if (SetUid( name, uid ))
+			return 1;
+		resetGids();
+	}
+	return 0;
+}
+
+#if defined(SECURE_RPC) || defined(K5AUTH)
+static void
+NukeAuth( int len, const char *name )
+{
+	int i;
+
+	for (i = 0; i < td->authNum; i++)
+		if (td->authorizations[i]->name_length == len &&
+		    !memcmp( td->authorizations[i]->name, name, len ))
+		{
+			memcpy( &td->authorizations[i], &td->authorizations[i+1],
+			        sizeof(td->authorizations[i]) * (--td->authNum - i) );
+			break;
+		}
+}
+#endif
+
+static void
+mergeSessionArgs( int cansave )
+{
+	char *mfname;
+	const char *fname;
+	int i, needsave;
+
+	mfname = 0;
+	fname = ".dmrc";
+	if ((!curdmrc || newdmrc) && *dmrcDir)
+		if (StrApp( &mfname, dmrcDir, "/", curuser, fname, (char *)0 ))
+			fname = mfname;
+	needsave = 0;
+	if (!curdmrc) {
+		curdmrc = iniLoad( fname );
+		if (!curdmrc) {
+			StrDup( &curdmrc, "[Desktop]\nSession=default\n" );
+			needsave = 1;
+		}
+	}
+	if (newdmrc) {
+		curdmrc = iniMerge( curdmrc, newdmrc );
+		needsave = 1;
+	}
+	if (needsave && cansave)
+		if (!iniSave( curdmrc, fname ) && errno == ENOENT && mfname) {
+			for (i = 0; mfname[i]; i++)
+				if (mfname[i] == '/') {
+					mfname[i] = 0;
+					mkdir( mfname, 0755 );
+					mfname[i] = '/';
+				}
+			iniSave( curdmrc, mfname );
+		}
+	if (mfname)
+		free( mfname );
+}
+
+static int removeAuth;
+#ifdef USE_PAM
+static int removeSession;
+static int removeCreds;
+#endif
+
+int
+StartClient()
+{
+	const char *home, *sessargs, *desksess;
+	char **env, *xma;
+	char **argv, *fname, *str;
+#ifdef USE_PAM
+	char **pam_env;
+# ifdef _AIX
+	char **saved_env;
+# endif
+	struct pam_conv pconv;
+	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], *lname;
+	int i, pid, lfd;
+
+	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 );
+		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(NO_AFS)
+	if (krbtkfile[0] != '\0') {
+		if (k_hasafs()) {
+			if (k_setpag() == -1)
+				LogError( "setpag() for %s failed\n", curuser );
+			if ((ret = k_afsklog( NULL, NULL )) != KSUCCESS)
+				LogError( "AFS Warning: %s\n", krb_get_err_text( ret ) );
+		}
+	}
+#  endif /* KERBEROS && AFS */
+# endif /* _AIX */
+#endif	/* !PAM */
+
+	curuid = p->pw_uid;
+	curgid = p->pw_gid;
+
+	env = baseEnv( curuser );
+	xma = 0;
+	if (td->ctrl.fpath && StrDup( &xma, td->ctrl.fpath )) {
+		if ((td->allowShutdown == SHUT_ALL ||
+		     (td->allowShutdown == SHUT_ROOT && !curuser)) &&
+		    StrApp( &xma, ",maysd", (char *)0 ))
+		{
+			if (td->allowNuke == SHUT_ALL ||
+			    (td->allowNuke == SHUT_ROOT && !curuser))
+				StrApp( &xma, ",mayfn", (char *)0 );
+			StrApp( &xma, td->defSdMode == SHUT_FORCENOW ? ",fn" :
+			        td->defSdMode == SHUT_TRYNOW ? ",tn" : ",sched",
+			        (char *)0 );
+		}
+		if ((td->displayType & d_location) == dLocal && AnyReserveDisplays())
+			StrApp( &xma, ",rsvd", (char *)0 );
+	} else
+		StrDup( &xma, "true" );
+	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
+	/* the greeter is gone by now ... */
+	pconv.conv = PAM_conv_null;
+	pconv.appdata_ptr = 0;
+	if ((pretc = pam_set_item( pamh, PAM_CONV, &pconv )) != PAM_SUCCESS) {
+		ReInitErrorLog();
+		LogError( "pam_set_item() for %s failed: %s\n",
+		          curuser, pam_strerror( pamh, pretc ) );
+		return 0;
+	}
+	ReInitErrorLog();
+#endif
+
+#ifdef USE_PAM
+
+# ifdef HAVE_SETUSERCONTEXT
+	if (setusercontext( lc, p, p->pw_uid, LOGIN_SETGROUP )) {
+		LogError( "setusercontext(groups) for %s failed: %m\n",
+		          curuser );
+		return 0;
+	}
+# else
+	if (!SetGid( curuser, curgid ))
+		return 0;
+# endif
+
+# ifdef _AIX
+	if (!(pam_env = initStrArr( 0 ))) {
+		resetGids();
+		return 0;
+	}
+	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();
+# ifdef _AIX
+	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())
+		return 0;
+# 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
+	ClearCloseOnFork( mstrtalk.pipe->wfd );
+	switch (pid = Fork()) {
+	case 0:
+
+		sessreg( td, getpid(), curuser, curuid );
+
+		if (source( systemEnviron, td->startup, td_setup )) {
+			LogError( "Cannot execute startup script %\"s\n", td->startup );
+			exit( 1 );
+		}
+
+		if (Setjmp( mstrtalk.errjmp ))
+			exit( 1 );
+		GSet( &mstrtalk );
+
+		setsid();
+
+	/* 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 */
+#  ifndef _AIX
+		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 );
+			exit( 1 );
+		}
+#  define D_LOGIN_SETLOGIN LOGIN_SETLOGIN
+# else
+#  define D_LOGIN_SETLOGIN 0
+# endif
+
+# if defined(USE_PAM) && defined(HAVE_INITGROUPS)
+		if (!restoreGids())
+			exit( 1 );
+# endif
+
+# ifndef HAVE_SETUSERCONTEXT
+
+#  ifdef USE_PAM
+		if (!SetUid( curuser, curuid ))
+			exit( 1 );
+#  else
+		if (!SetUser( curuser, curuid, curgid ))
+			exit( 1 );
+#  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 )))
+			exit( 1 );
+
+		/*
+		 * 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 );
+			exit( 1 );
+		}
+
+		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 );
+			exit( 1 );
+		}
+
+		/*
+		 * 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( "Can't set %s's process environment\n", curuser );
+			exit( 1 );
+		}
+		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) {
+			GSendInt( D_ReLogin );
+			GSendStr( curuser );
+			GSendStr( curpass );
+			GSendStr( newdmrc );
+		}
+		if (curpass)
+			bzero( curpass, strlen( curpass ) );
+		SetUserAuthorization( td );
+		home = getEnv( userEnviron, "HOME" );
+		if (home) {
+			if (chdir( home ) < 0) {
+				LogError( "Cannot chdir to %s's home %s: %m, using /\n",
+				          curuser, home );
+				home = 0;
+				userEnviron = setEnv( userEnviron, "HOME", "/" );
+				goto cdroot;
+			}
+			ASPrintf( &lname, td->clientLogFile, td->name );
+			if ((lfd = creat( lname, 0600 )) < 0) {
+				LogWarn( "Cannot create session log file %s: %m\n", lname );
+				free( lname );
+				goto tmperr;
+			}
+		} else {
+		  cdroot:
+			chdir( "/" );
+		  tmperr:
+			ASPrintf( &lname, "/tmp/xerr-%s-%s", curuser, td->name );
+			unlink( lname );
+			if ((lfd = open( lname, O_WRONLY|O_CREAT|O_EXCL, 0600 )) < 0) {
+				LogError( "Cannot create fallback session log file %s: %m\n",
+				          lname );
+				goto logerr;
+			}
+		}
+		dup2( lfd, 1 );
+		dup2( lfd, 2 );
+		close( lfd );
+	  logerr:
+		free( lname );
+		if (!*dmrcDir)
+			mergeSessionArgs( home != 0 );
+		if (!(desksess = iniEntry( curdmrc, "Desktop", "Session", 0 )))
+			desksess = "failsafe"; /* only due to OOM */
+		GSendInt( D_User );
+		GSendInt( curuid );
+		GSendStr( curuser );
+		GSendStr( desksess );
+		close( mstrtalk.pipe->wfd );
+		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] );
+		exit( 1 );
+	case -1:
+		RegisterCloseOnFork( mstrtalk.pipe->wfd );
+		LogError( "Forking session on %s failed: %m\n", td->name );
+		return 0;
+	default:
+		RegisterCloseOnFork( mstrtalk.pipe->wfd );
+		Debug( "StartSession, fork succeeded %d\n", pid );
+		return pid;
+	}
+}
+
+void
+SessionExit( int status )
+{
+	int pid;
+#ifdef USE_PAM
+	int pretc;
+#endif
+
+	if (removeAuth) {
+		if (source( systemEnviron, td->reset, td_setup ))
+			LogError( "Cannot execute reset script %\"s\n", td->reset );
+		sessreg( td, 0, 0, 0 );
+
+		switch ((pid = Fork())) {
+		case 0:
+#if defined(USE_PAM) && defined(HAVE_INITGROUPS)
+			if (restoreGids() && SetUid( curuser, curuid ))
+#else
+			if (SetUser( curuser, curuid, curgid ))
+#endif
+
+			{
+				RemoveUserAuthorization( td );
+#ifdef K5AUTH
+				Krb5Destroy( td->name );
+#endif /* K5AUTH */
+#if !defined(USE_PAM) && !defined(_AIX)
+# ifdef KERBEROS
+				if (krbtkfile[0]) {
+					(void)dest_tkt();
+#  ifndef NO_AFS
+					if (k_hasafs())
+						(void)k_unlog();
+#  endif
+				}
+# endif
+#endif /* !USE_PAM && !_AIX*/
+			}
+			exit( 0 );
+		case -1:
+			LogError( "Cannot clean up session: fork() failed: %m" );
+			break;
+		default:
+			Wait4( pid );
+			break;
+		}
+	}
+
+#ifdef USE_PAM
+	if (removeCreds) {
+# ifdef HAVE_INITGROUPS
+		restoreGids();
+# endif
+		if (removeSession)
+			if ((pretc = pam_close_session( pamh, 0 )) != PAM_SUCCESS)
+				LogError( "pam_close_session() failed: %s\n",
+				          pam_strerror( pamh, pretc ) );
+		if ((pretc = pam_setcred( pamh, PAM_DELETE_CRED )) != PAM_SUCCESS)
+			LogError( "pam_setcred(DELETE_CRED) failed: %s\n",
+			          pam_strerror( pamh, pretc ) );
+		resetGids();
+	}
+	if (pamh) {
+		pam_end( pamh, PAM_SUCCESS );
+		ReInitErrorLog();
+	}
+#endif
+
+	/* make sure the server gets reset after the session is over */
+	if (td->serverPid >= 2) {
+		if (!td->terminateServer && td->resetSignal)
+			TerminateProcess( td->serverPid, td->resetSignal );
+	} else
+		ResetServer( td );
+	Debug( "display %s exiting with status %d\n", td->name, status );
+	exit( status );
+}
+
+int
+ReadDmrc()
+{
+	char *data, *fname = 0;
+	int len, pid, pfd[2], err;
+
+	if (!dmrcuser || !dmrcuser[0] || !(p = getpwnam( dmrcuser )))
+		return GE_NoUser;
+
+	if (*dmrcDir) {
+		if (!StrApp( &fname, dmrcDir, "/", dmrcuser, ".dmrc", (char *)0 ))
+			return GE_Error;
+		if (!(curdmrc = iniLoad( fname ))) {
+			free( fname );
+			return GE_Ok;
+		}
+		free( fname );
+		return GE_NoFile;
+	}
+
+	if (!StrApp( &fname, p->pw_dir, "/.dmrc", (char *)0 ))
+		return GE_Error;
+	if (pipe( pfd ))
+		return GE_Error;
+	if ((pid = Fork()) < 0) {
+		close( pfd[0] );
+		close( pfd[1] );
+		return GE_Error;
+	}
+	if (!pid) {
+		if (!SetUser( p->pw_name, p->pw_uid, p->pw_gid ))
+			exit( 0 );
+		if (!(data = iniLoad( fname ))) {
+			static const int m1 = -1;
+			write( pfd[1], &m1, sizeof(int) );
+			exit( 0 );
+		}
+		len = strlen( data );
+		write( pfd[1], &len, sizeof(int) );
+		write( pfd[1], data, len + 1 );
+		exit( 0 );
+	}
+	close( pfd[1] );
+	free( fname );
+	err = GE_Error;
+	if (Reader( pfd[0], &len, sizeof(int) ) == sizeof(int)) {
+		if (len == -1)
+			err = GE_Denied;
+		else if ((curdmrc = Malloc( len + 1 ))) {
+			if (Reader( pfd[0], curdmrc, len + 1 ) == len + 1)
+				err = GE_Ok;
+			else {
+				free( curdmrc );
+				curdmrc = 0;
+			}
+		}
+	}
+	close( pfd[0] );
+	(void)Wait4( pid );
+	return err;
+}
diff -r -N -u kdebase-3.5.8.orig/kdm/backend/consolekit.c kdebase-3.5.8/kdm/backend/consolekit.c
--- kdebase-3.5.8.orig/kdm/backend/consolekit.c	1969-12-31 21:00:00.000000000 -0300
+++ kdebase-3.5.8/kdm/backend/consolekit.c	2008-01-25 08:38:42.000000000 -0200
@@ -0,0 +1,552 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2006-2007 William Jon McCann <mccann@jhu.edu>
+ * Copyright (C) 2007 Kevin Kofler <Kevin@tigcc.ticalc.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#include "dm.h"
+#include "dm_auth.h"
+#include "dm_error.h"
+
+#include <stdlib.h>
+#include <string.h>
+#include <pwd.h>
+
+#define DBUS_API_SUBJECT_TO_CHANGE
+#include <dbus/dbus.h>
+
+#include "consolekit.h"
+
+
+#define CK_NAME              "org.freedesktop.ConsoleKit"
+#define CK_PATH              "/org/freedesktop/ConsoleKit"
+#define CK_INTERFACE         "org.freedesktop.ConsoleKit"
+#define CK_MANAGER_PATH      "/org/freedesktop/ConsoleKit/Manager"
+#define CK_MANAGER_INTERFACE "org.freedesktop.ConsoleKit.Manager"
+#define CK_SESSION_INTERFACE "org.freedesktop.ConsoleKit.Session"
+
+static DBusConnection *private_connection = NULL;
+
+static void
+add_param_int (DBusMessageIter *iter_struct,
+	       const char      *key,
+	       int              value)
+{
+	DBusMessageIter iter_struct_entry;
+	DBusMessageIter iter_var;
+
+	dbus_message_iter_open_container (iter_struct,
+					  DBUS_TYPE_STRUCT,
+					  NULL,
+					  &iter_struct_entry);
+
+	dbus_message_iter_append_basic (&iter_struct_entry,
+					DBUS_TYPE_STRING,
+					&key);
+
+	dbus_message_iter_open_container (&iter_struct_entry,
+					  DBUS_TYPE_VARIANT,
+					  DBUS_TYPE_INT32_AS_STRING,
+					  &iter_var);
+
+	dbus_message_iter_append_basic (&iter_var,
+					DBUS_TYPE_INT32,
+					&value);
+
+	dbus_message_iter_close_container (&iter_struct_entry,
+					   &iter_var);
+
+	dbus_message_iter_close_container (iter_struct, &iter_struct_entry);
+}
+
+static void
+add_param_boolean (DBusMessageIter *iter_struct,
+		   const char      *key,
+		   int             value)
+{
+	DBusMessageIter iter_struct_entry;
+	DBusMessageIter iter_var;
+
+	dbus_message_iter_open_container (iter_struct,
+					  DBUS_TYPE_STRUCT,
+					  NULL,
+					  &iter_struct_entry);
+
+	dbus_message_iter_append_basic (&iter_struct_entry,
+					DBUS_TYPE_STRING,
+					&key);
+
+	dbus_message_iter_open_container (&iter_struct_entry,
+					  DBUS_TYPE_VARIANT,
+					  DBUS_TYPE_BOOLEAN_AS_STRING,
+					  &iter_var);
+
+	dbus_message_iter_append_basic (&iter_var,
+					DBUS_TYPE_BOOLEAN,
+					&value);
+
+	dbus_message_iter_close_container (&iter_struct_entry,
+					   &iter_var);
+
+	dbus_message_iter_close_container (iter_struct, &iter_struct_entry);
+}
+
+static void
+add_param_string (DBusMessageIter *iter_struct,
+		  const char      *key,
+		  const char      *value)
+{
+	DBusMessageIter iter_struct_entry;
+	DBusMessageIter iter_var;
+
+	dbus_message_iter_open_container (iter_struct,
+					  DBUS_TYPE_STRUCT,
+					  NULL,
+					  &iter_struct_entry);
+
+	dbus_message_iter_append_basic (&iter_struct_entry,
+					DBUS_TYPE_STRING,
+					&key);
+
+	dbus_message_iter_open_container (&iter_struct_entry,
+					  DBUS_TYPE_VARIANT,
+					  DBUS_TYPE_STRING_AS_STRING,
+					  &iter_var);
+
+	dbus_message_iter_append_basic (&iter_var,
+					DBUS_TYPE_STRING,
+					&value);
+
+	dbus_message_iter_close_container (&iter_struct_entry,
+					   &iter_var);
+
+	dbus_message_iter_close_container (iter_struct, &iter_struct_entry);
+}
+
+static int
+session_get_x11_display (DBusConnection *connection,
+			 const char     *ssid,
+			 char          **str)
+{
+	DBusError       error;
+	DBusMessage    *message;
+	DBusMessage    *reply;
+	DBusMessageIter iter;
+	const char     *value;
+
+	if (str != NULL) {
+		*str = NULL;
+	}
+
+	message = dbus_message_new_method_call (CK_NAME,
+						ssid,
+						CK_SESSION_INTERFACE,
+						"GetX11Display");
+	if (message == NULL) {
+		Debug ("ConsoleKit: Couldn't allocate the D-Bus message");
+		return FALSE;
+	}
+
+	dbus_error_init (&error);
+	reply = dbus_connection_send_with_reply_and_block (connection,
+							   message,
+							   -1, &error);
+	if (dbus_error_is_set (&error)) {
+		Debug ("ConsoleKit: %s raised:\n %s\n\n", error.name, error.message);
+		reply = NULL;
+	}
+
+	dbus_connection_flush (connection);
+	dbus_message_unref (message);
+
+	if (reply == NULL) {
+		return FALSE;
+	}
+
+	dbus_message_iter_init (reply, &iter);
+	dbus_message_iter_get_basic (&iter, &value);
+	if (str != NULL) {
+		*str = strdup (value);
+	}
+	dbus_message_unref (reply);
+
+	return TRUE;
+}
+
+static int
+session_unlock (DBusConnection *connection,
+		const char     *ssid)
+{
+	DBusError       error;
+	DBusMessage    *message;
+	DBusMessage    *reply;
+
+	Debug ("ConsoleKit: Unlocking session %s", ssid);
+	message = dbus_message_new_method_call (CK_NAME,
+						ssid,
+						CK_SESSION_INTERFACE,
+						"Unlock");
+	if (message == NULL) {
+		Debug ("ConsoleKit: Couldn't allocate the D-Bus message");
+		return FALSE;
+	}
+
+	dbus_error_init (&error);
+	reply = dbus_connection_send_with_reply_and_block (connection,
+							   message,
+							   -1, &error);
+	dbus_message_unref (message);
+	dbus_message_unref (reply);
+	dbus_connection_flush (connection);
+
+	if (dbus_error_is_set (&error)) {
+		Debug ("ConsoleKit: %s raised:\n %s\n\n", error.name, error.message);
+		return FALSE;
+	}
+
+	return TRUE;
+}
+
+/* from libhal */
+static char **
+get_path_array_from_iter (DBusMessageIter *iter,
+			  int             *num_elements)
+{
+	int count;
+	char **buffer;
+
+	count = 0;
+	buffer = (char **)malloc (sizeof (char *) * 8);
+
+	if (buffer == NULL)
+		goto oom;
+
+	buffer[0] = NULL;
+	while (dbus_message_iter_get_arg_type (iter) == DBUS_TYPE_OBJECT_PATH) {
+		const char *value;
+		char *str;
+
+		if ((count % 8) == 0 && count != 0) {
+			buffer = realloc (buffer, sizeof (char *) * (count + 8));
+			if (buffer == NULL)
+				goto oom;
+		}
+
+		dbus_message_iter_get_basic (iter, &value);
+		str = strdup (value);
+		if (str == NULL)
+			goto oom;
+
+		buffer[count] = str;
+
+		dbus_message_iter_next (iter);
+		count++;
+	}
+
+	if ((count % 8) == 0) {
+		buffer = realloc (buffer, sizeof (char *) * (count + 1));
+		if (buffer == NULL)
+			goto oom;
+	}
+
+	buffer[count] = NULL;
+	if (num_elements != NULL)
+		*num_elements = count;
+	return buffer;
+
+oom:
+	LogWarn ("%s %d : error allocating memory\n", __FILE__, __LINE__);
+	return NULL;
+
+}
+
+static char **
+get_sessions_for_user (DBusConnection *connection,
+		       const char     *user,
+		       const char     *x11_display)
+{
+	DBusError       error;
+	DBusMessage    *message;
+	DBusMessage    *reply;
+	DBusMessageIter iter;
+	DBusMessageIter iter_reply;
+	DBusMessageIter iter_array;
+	struct passwd	*pwent;
+	char           **sessions;
+
+	sessions = NULL;
+	message = NULL;
+	reply = NULL;
+
+	pwent = getpwnam (user);
+
+	dbus_error_init (&error);
+	message = dbus_message_new_method_call (CK_NAME,
+						CK_MANAGER_PATH,
+						CK_MANAGER_INTERFACE,
+						"GetSessionsForUser");
+	if (message == NULL) {
+		Debug ("ConsoleKit: Couldn't allocate the D-Bus message");
+		goto out;
+	}
+
+	dbus_message_iter_init_append (message, &iter);
+	dbus_message_iter_append_basic (&iter,
+					DBUS_TYPE_UINT32,
+					&pwent->pw_uid);
+
+	dbus_error_init (&error);
+	reply = dbus_connection_send_with_reply_and_block (connection,
+							   message,
+							   -1, &error);
+	dbus_connection_flush (connection);
+
+	if (dbus_error_is_set (&error)) {
+		Debug ("ConsoleKit: %s raised:\n %s\n\n", error.name, error.message);
+		goto out;
+	}
+
+	if (reply == NULL) {
+		Debug ("ConsoleKit: No reply for GetSessionsForUser");
+		goto out;
+	}
+
+	dbus_message_iter_init (reply, &iter_reply);
+	if (dbus_message_iter_get_arg_type (&iter_reply) != DBUS_TYPE_ARRAY) {
+		Debug ("ConsoleKit: Wrong reply for GetSessionsForUser - expecting an array.");
+		goto out;
+	}
+
+	dbus_message_iter_recurse (&iter_reply, &iter_array);
+	sessions = get_path_array_from_iter (&iter_array, NULL);
+
+ out:
+	if (message != NULL) {
+		dbus_message_unref (message);
+	}
+	if (reply != NULL) {
+		dbus_message_unref (reply);
+	}
+
+	return sessions;
+}
+
+void
+unlock_ck_session (const char *user,
+		   const char *x11_display)
+{
+	DBusError       error;
+	DBusConnection *connection;
+	char           **sessions;
+	int              i;
+
+	Debug ("ConsoleKit: Unlocking session for %s on %s", user, x11_display);
+
+	dbus_error_init (&error);
+	connection = dbus_bus_get (DBUS_BUS_SYSTEM, &error);
+	if (connection == NULL) {
+		Debug ("ConsoleKit: Failed to connect to the D-Bus daemon: %s", error.message);
+		dbus_error_free (&error);
+		return;
+	}
+
+	sessions = get_sessions_for_user (connection, user, x11_display);
+	if (sessions == NULL || sessions[0] == NULL) {
+		Debug ("ConsoleKit: no sessions found");
+		return;
+	}
+
+	for (i = 0; sessions[i] != NULL; i++) {
+		char *ssid;
+		char *xdisplay;
+
+		ssid = sessions[i];
+		session_get_x11_display (connection, ssid, &xdisplay);
+		Debug ("ConsoleKit: session %s has DISPLAY %s", ssid, xdisplay);
+
+		if (xdisplay != NULL
+		    && x11_display != NULL
+		    && strcmp (xdisplay, x11_display) == 0) {
+			int res;
+
+			res = session_unlock (connection, ssid);
+			if (! res) {
+				LogError ("ConsoleKit: Unable to unlock %s", ssid);
+			}
+		}
+
+		free (xdisplay);
+	}
+
+	freeStrArr (sessions);
+}
+
+char *
+open_ck_session (struct passwd *pwent,
+		 struct display *d)
+{
+	DBusConnection *connection;
+	DBusError       error;
+	DBusMessage    *message;
+	DBusMessage    *reply;
+	DBusMessageIter iter;
+	DBusMessageIter iter_struct;
+	char	       *cookie;
+
+	cookie = NULL;
+
+	Debug ("ConsoleKit: Opening session for %s", pwent->pw_name);
+
+	dbus_error_init (&error);
+	connection = dbus_bus_get_private (DBUS_BUS_SYSTEM, &error);
+	private_connection = connection;
+
+	if (connection == NULL) {
+		Debug ("ConsoleKit: Failed to connect to the D-Bus daemon: %s", error.message);
+		dbus_error_free (&error);
+		return NULL;
+	}
+
+	dbus_connection_set_exit_on_disconnect (connection, FALSE);
+	/* FIXME: What to do about these?
+	dbus_connection_set_watch_functions( connection,
+	                                     dbusAddWatch,
+	                                     dbusRemoveWatch,
+	                                     dbusToggleWatch,
+	                                     data, 0 );
+	dbus_connection_set_timeout_functions( connection,
+	                                       dbusAddTimeout,
+	                                       dbusRemoveTimeout,
+	                                       dbusToggleTimeout,
+	                                       data, 0 );
+	dbus_connection_set_wakeup_main_function( connection,
+	                                          dbusWakeupMain,
+	                                          data, 0 ); */
+
+	dbus_error_init (&error);
+	message = dbus_message_new_method_call (CK_NAME,
+						CK_MANAGER_PATH,
+						CK_MANAGER_INTERFACE,
+						"OpenSessionWithParameters");
+	if (message == NULL) {
+		Debug ("ConsoleKit: Couldn't allocate the D-Bus message");
+		return NULL;
+	}
+
+	dbus_message_iter_init_append (message, &iter);
+	dbus_message_iter_open_container (&iter,
+					  DBUS_TYPE_ARRAY,
+					  DBUS_STRUCT_BEGIN_CHAR_AS_STRING
+					  DBUS_TYPE_STRING_AS_STRING
+					  DBUS_TYPE_VARIANT_AS_STRING
+					  DBUS_STRUCT_END_CHAR_AS_STRING,
+					  &iter_struct);
+
+	add_param_int (&iter_struct, "user", pwent->pw_uid);
+	add_param_string (&iter_struct, "x11-display", d->name);
+	add_param_boolean (&iter_struct, "is-local", ((d->displayType & d_location) == dLocal));
+#ifdef XDMCP
+	if (d->status == remoteLogin && !((d->displayType & d_location) == dLocal)) {
+		add_param_string (&iter_struct, "remote-host-name", d->remoteHost);
+	}
+#endif
+
+#ifdef HAVE_VTS
+	if (d->serverVT > 0) {
+		char device[20];
+
+		/* FIXME: how does xorg construct this */
+		sprintf(device, "/dev/tty%d", d->serverVT);
+		add_param_string (&iter_struct, "x11-display-device", device);
+	}
+#endif
+
+	dbus_message_iter_close_container (&iter, &iter_struct);
+
+	reply = dbus_connection_send_with_reply_and_block (connection,
+							   message,
+							   -1, &error);
+	if (dbus_error_is_set (&error)) {
+		Debug ("ConsoleKit: %s raised:\n %s\n\n", error.name, error.message);
+		reply = NULL;
+	}
+
+	dbus_connection_flush (connection);
+
+	dbus_message_unref (message);
+	dbus_error_free (&error);
+
+	if (reply != NULL) {
+		const char *value;
+
+		dbus_message_iter_init (reply, &iter);
+		dbus_message_iter_get_basic (&iter, &value);
+		cookie = strdup (value);
+		dbus_message_unref (reply);
+	}
+
+	return cookie;
+}
+
+void
+close_ck_session (const char *cookie)
+{
+	DBusError       error;
+	DBusMessage    *message;
+	DBusMessage    *reply;
+	DBusMessageIter iter;
+
+	if (cookie == NULL) {
+		return;
+	}
+
+	if (private_connection == NULL) {
+		return;
+	}
+
+	dbus_error_init (&error);
+	message = dbus_message_new_method_call (CK_NAME,
+						CK_MANAGER_PATH,
+						CK_MANAGER_INTERFACE,
+						"CloseSession");
+	if (message == NULL) {
+		Debug ("ConsoleKit: Couldn't allocate the D-Bus message");
+		return;
+	}
+
+	dbus_message_iter_init_append (message, &iter);
+	dbus_message_iter_append_basic (&iter,
+					DBUS_TYPE_STRING,
+					&cookie);
+
+	reply = dbus_connection_send_with_reply_and_block (private_connection,
+							   message,
+							   -1, &error);
+	if (dbus_error_is_set (&error)) {
+		Debug ("ConsoleKit: %s raised:\n %s\n\n", error.name, error.message);
+		reply = NULL;
+	}
+
+	dbus_connection_flush (private_connection);
+
+	dbus_message_unref (message);
+	dbus_error_free (&error);
+
+        dbus_connection_close (private_connection);
+	private_connection = NULL;
+}
diff -r -N -u kdebase-3.5.8.orig/kdm/backend/consolekit.h kdebase-3.5.8/kdm/backend/consolekit.h
--- kdebase-3.5.8.orig/kdm/backend/consolekit.h	1969-12-31 21:00:00.000000000 -0300
+++ kdebase-3.5.8/kdm/backend/consolekit.h	2008-01-25 08:38:42.000000000 -0200
@@ -0,0 +1,36 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2006 William Jon McCann <mccann@jhu.edu>
+ * Copyright (C) 2007 Kevin Kofler <Kevin@tigcc.ticalc.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+
+#ifndef __CONSOLE_KIT_H
+#define __CONSOLE_KIT_H
+
+#include <pwd.h>
+
+struct display;
+
+char *      open_ck_session       (struct passwd *pwent,
+                                   struct display *display);
+void        close_ck_session      (const char    *cookie);
+void        unlock_ck_session     (const char    *user,
+                                   const char    *x11_display);
+
+#endif /* __CONSOLE_KIT_H */
diff -r -N -u kdebase-3.5.8.orig/kdm/backend/dm.h kdebase-3.5.8/kdm/backend/dm.h
--- kdebase-3.5.8.orig/kdm/backend/dm.h	2005-02-20 06:08:56.000000000 -0300
+++ kdebase-3.5.8/kdm/backend/dm.h	2008-01-25 08:38:42.000000000 -0200
@@ -37,6 +37,8 @@
 #ifndef _DM_H_
 #define _DM_H_ 1
 
+#define WITH_CONSOLE_KIT
+
 #include "greet.h"
 #include <config.ci>
 
@@ -476,7 +478,11 @@
 #define GCONV_BINARY  5
 typedef char *(*GConvFunc)( int what, const char *prompt );
 int Verify( GConvFunc gconv, int rootok );
+#ifdef WITH_CONSOLE_KIT
+int StartClient( const char *ck_session_cookie );
+#else
 int StartClient( void );
+#endif
 void SessionExit( int status ) ATTR_NORETURN;
 int ReadDmrc( void );
 extern char **userEnviron, **systemEnviron;
diff -r -N -u kdebase-3.5.8.orig/kdm/backend/Imakefile kdebase-3.5.8/kdm/backend/Imakefile
--- kdebase-3.5.8.orig/kdm/backend/Imakefile	2004-05-09 11:53:12.000000000 -0300
+++ kdebase-3.5.8/kdm/backend/Imakefile	2008-01-25 08:38:42.000000000 -0200
@@ -155,13 +155,13 @@
 		 netaddr.c reset.c resource.c protodpy.c policy.c \
 		 session.c socket.c streams.c util.c xdmcp.c \
 		 process.c mitauth.c \
-		 genauth.c access.c choose.c \
+		 genauth.c access.c choose.c consolekit.c \
 		 $(XDMAUTHSRCS) $(RPCSRCS) $(KRB5SRCS)
       COMMOBJS = auth.o daemon.o server.o dpylist.o dm.o error.o \
 		 netaddr.o reset.o resource.o protodpy.o policy.o \
 		 session.o socket.o streams.o util.o xdmcp.o \
 		 process.o mitauth.o \
-		 genauth.o access.o choose.o \
+		 genauth.o access.o choose.o consolekit.o \
 		 $(XDMAUTHOBJS) $(RPCOBJS) $(KRB5OBJS)
 
          SRCS1 = $(COMMSRCS) client.c
diff -r -N -u kdebase-3.5.8.orig/kdm/backend/Makefile.am~ kdebase-3.5.8/kdm/backend/Makefile.am~
--- kdebase-3.5.8.orig/kdm/backend/Makefile.am~	1969-12-31 21:00:00.000000000 -0300
+++ kdebase-3.5.8/kdm/backend/Makefile.am~	2008-01-25 08:38:42.000000000 -0200
@@ -0,0 +1,47 @@
+# forcibly remove thread-related defines & flags
+AUTOMAKE_OPTIONS = foreign
+CPPFLAGS = $(USER_INCLUDES) $(X_INCLUDES) $(KRB4_INCS) $(KRB5_INCS) -I.. -I../..
+LDFLAGS = $(USER_LDFLAGS) $(X_LDFLAGS) $(X_RPATH) $(KRB4_RPATH) $(KRB5_RPATH)
+LDADD = $(LIB_X11) -lXau $(LIBXDMCP) $(PASSWDLIBS) \
+    $(LIB_LIBS) $(KRB4_LIBS) $(KRB5_LIBS) $(LIBSOCKET) $(LIBRESOLV) \
+    $(DBUS_LIBS) $(LIBUCB) $(LIBUTIL) $(LIBPOSIX4)
+
+bin_PROGRAMS = kdm
+kdm_SOURCES = \
+    access.c \
+    auth.c \
+    bootman.c \
+    choose.c \
+    client.c \
+    consolekit.c \
+    ctrl.c \
+    daemon.c \
+    dm.c \
+    dpylist.c \
+    error.c \
+    genauth.c \
+    inifile.c \
+    krb5auth.c \
+    mitauth.c \
+    netaddr.c \
+    policy.c \
+    process.c \
+    protodpy.c \
+    reset.c \
+    resource.c \
+    rpcauth.c \
+    server.c \
+    session.c \
+    sessreg.c \
+    socket.c \
+    streams.c \
+    util.c \
+    xdmauth.c \
+    xdmcp.c
+
+EXTRA_DIST = printf.c
+
+noinst_HEADERS = dm.h dm_socket.h dm_error.h dm_auth.h greet.h
+
+# for unsermake (automake is handled by SUBDIRS in ../)
+kdm_COMPILE_FIRST = ../config.ci
diff -r -N -u kdebase-3.5.8.orig/kdm/backend/Makefile.am.orig kdebase-3.5.8/kdm/backend/Makefile.am.orig
--- kdebase-3.5.8.orig/kdm/backend/Makefile.am.orig	1969-12-31 21:00:00.000000000 -0300
+++ kdebase-3.5.8/kdm/backend/Makefile.am.orig	2008-01-25 08:38:42.000000000 -0200
@@ -0,0 +1,47 @@
+# forcibly remove thread-related defines & flags
+AUTOMAKE_OPTIONS = foreign
+CPPFLAGS = $(USER_INCLUDES) $(X_INCLUDES) $(KRB4_INCS) $(KRB5_INCS) -I.. -I../..
+LDFLAGS = $(USER_LDFLAGS) $(X_LDFLAGS) $(X_RPATH) $(KRB4_RPATH) $(KRB5_RPATH)
+LDADD = $(LIB_X11) -lXau $(LIBXDMCP) $(PASSWDLIBS) \
+    $(LIB_LIBS) $(KRB4_LIBS) $(KRB5_LIBS) $(LIBSOCKET) $(LIBRESOLV) \
+    $(LIBUCB) $(LIBUTIL) $(LIBPOSIX4)
+
+bin_PROGRAMS = kdm
+kdm_SOURCES = \
+    access.c \
+    auth.c \
+    bootman.c \
+    choose.c \
+    client.c \
+    consolekit.c \
+    ctrl.c \
+    daemon.c \
+    dm.c \
+    dpylist.c \
+    error.c \
+    genauth.c \
+    inifile.c \
+    krb5auth.c \
+    mitauth.c \
+    netaddr.c \
+    policy.c \
+    process.c \
+    protodpy.c \
+    reset.c \
+    resource.c \
+    rpcauth.c \
+    server.c \
+    session.c \
+    sessreg.c \
+    socket.c \
+    streams.c \
+    util.c \
+    xdmauth.c \
+    xdmcp.c
+
+EXTRA_DIST = printf.c
+
+noinst_HEADERS = dm.h dm_socket.h dm_error.h dm_auth.h greet.h
+
+# for unsermake (automake is handled by SUBDIRS in ../)
+kdm_COMPILE_FIRST = ../config.ci
diff -r -N -u kdebase-3.5.8.orig/kdm/configure.in.in kdebase-3.5.8/kdm/configure.in.in
--- kdebase-3.5.8.orig/kdm/configure.in.in	2006-01-10 13:26:51.000000000 -0200
+++ kdebase-3.5.8/kdm/configure.in.in	2008-01-25 08:38:42.000000000 -0200
@@ -240,4 +240,51 @@
     AC_DEFINE(WITH_KDM_XCONSOLE, 1, [Build kdm with built-in xconsole])
 fi
 
+########### Check for DBus
+
+  AC_MSG_CHECKING(for DBus)
+
+  dbus_inc=NOTFOUND
+  dbus_lib=NOTFOUND
+  dbus=NOTFOUND
+
+  search_incs="$kde_includes $kde_extra_includes /usr/include /usr/include/dbus-1.0 /usr/local/include /usr/local/include/dbus-1.0"
+  AC_FIND_FILE(dbus/dbus.h, $search_incs, dbus_incdir)
+
+  search_incs_arch_deps="$kde_includes $kde_extra_includes /usr/lib$kdelibsuff/dbus-1.0/include /usr/local/lib$kdelibsuff/dbus-1.0/include"
+  AC_FIND_FILE(dbus/dbus-arch-deps.h, $search_incs_arch_deps, dbus_incdir_arch_deps)
+
+  if test -r $dbus_incdir/dbus/dbus.h && test -r $dbus_incdir_arch_deps/dbus/dbus-arch-deps.h ; then
+    DBUS_INCS="-I$dbus_incdir -I$dbus_incdir_arch_deps"
+    dbus_inc=FOUND
+  fi
+
+  search_libs="$kde_libraries $kde_extra_libs /usr/lib$kdelibsuff /usr/local/lib$kdelibsuff"
+  AC_FIND_FILE(libdbus-1.so, $search_libs, dbus_libdir)
+
+  if test -r $dbus_libdir/libdbus-1.so ; then
+    DBUS_LIBS="-L$dbus_libdir -ldbus-1"
+    dbus_lib=FOUND
+  fi
+
+  if test $dbus_inc != FOUND || test $dbus_lib != FOUND ; then 
+    KDE_PKG_CHECK_MODULES( DBUS, "dbus-1", [ DBUS_INCS=$DBUS_CFLAGS; dbus_inc=FOUND; dbus_lib=FOUND; ] , AC_MSG_RESULT( Nothing found on PKG_CONFIG_PATH ) )
+  fi
+
+  dbus_bus_var=`pkg-config --variable=system_bus_default_address dbus-1 2>/dev/null`
+  if test -z "$dbus_bus_var"; then
+        dbus_bus_var="unix:path=/var/run/dbus/system_bus_socket"
+  fi
+  AC_DEFINE_UNQUOTED(DBUS_SYSTEM_BUS, "$dbus_bus_var", [Define the unix domain path for dbus system bus])
+
+  if test $dbus_inc = FOUND && test $dbus_lib = FOUND ; then
+    AC_MSG_RESULT(headers $DBUS_INCS libraries $DBUS_LIBS)
+    dbus=FOUND
+  else
+    AC_MSG_RESULT(searched but not found)
+  fi
+
+  AC_SUBST(DBUS_INCS)
+  AC_SUBST(DBUS_LIBS)
+
 dnl AC_OUTPUT(kdm/kfrontend/sessions/kde.desktop)
--- kdebase-3.5.9/kdm/backend/session.c~	2008-02-14 21:12:09.000000000 +0100
+++ kdebase-3.5.9/kdm/backend/session.c	2008-02-14 21:28:11.000000000 +0100
@@ -45,6 +45,11 @@
 #include <ctype.h>
 #include <signal.h>
 
+#ifdef WITH_CONSOLE_KIT
+#include "consolekit.h"
+#endif
+
+
 struct display *td;
 const char *td_setup = "auto";
 
@@ -530,6 +535,9 @@
 	int ex, cmd;
 	volatile int clientPid = 0;
 	volatile Time_t tdiff = 0;
+#ifdef WITH_CONSOLE_KIT
+       char *ck_session_cookie;
+#endif
 
 	td = d;
 	Debug( "ManageSession %s\n", d->name );
@@ -625,8 +633,12 @@
 
 	if (td_setup)
 		SetupDisplay( td_setup );
-
+#ifdef WITH_CONSOLE_KIT
+       ck_session_cookie = open_ck_session (getpwnam(curuser), d);
+       if (!(clientPid = StartClient(ck_session_cookie))) {
+#else
 	if (!(clientPid = StartClient())) {
+#endif
 		LogError( "Client start failed\n" );
 		SessionExit( EX_NORMAL ); /* XXX maybe EX_REMANAGE_DPY? -- enable in dm.c! */
 	}
@@ -648,6 +660,12 @@
 				catchTerm( SIGTERM );
 		}
 	}
+#ifdef WITH_CONSOLE_KIT
+       if (ck_session_cookie != NULL) {
+               close_ck_session (ck_session_cookie);
+               free (ck_session_cookie);
+       }
+#endif
 	/*
 	 * Sometimes the Xsession somehow manages to exit before
 	 * a server crash is noticed - so we sleep a bit and wait
--- kdebase-3.5.9/kdm/backend/Makefile.am~	2007-10-08 11:51:33.000000000 +0200
+++ kdebase-3.5.9/kdm/backend/Makefile.am	2008-02-14 21:31:44.000000000 +0100
@@ -1,10 +1,10 @@
 # forcibly remove thread-related defines & flags
 AUTOMAKE_OPTIONS = foreign
-CPPFLAGS = $(USER_INCLUDES) $(X_INCLUDES) $(KRB4_INCS) $(KRB5_INCS) -I.. -I../..
+AM_CPPFLAGS = -DWITH_CONSOLE_KIT=1 $(USER_INCLUDES) $(X_INCLUDES) $(KRB4_INCS) $(KRB5_INCS) $(DBUS_INCS) -I.. -I../..
 LDFLAGS = $(USER_LDFLAGS) $(X_LDFLAGS) $(X_RPATH) $(KRB4_RPATH) $(KRB5_RPATH)
 LDADD = $(LIB_X11) -lXau $(LIBXDMCP) $(PASSWDLIBS) $(LIBSHADOW) $(LIBGEN) \
     $(LIB_LIBS) $(KRB4_LIBS) $(KRB5_LIBS) $(LIBSOCKET) $(LIBRESOLV) \
-    $(LIBUCB) $(LIBUTIL) $(LIBPOSIX4)
+    $(DBUS_LIBS) $(LIBUCB) $(LIBUTIL) $(LIBPOSIX4)
 
 bin_PROGRAMS = kdm
 kdm_SOURCES = \
@@ -13,6 +13,7 @@
     bootman.c \
     choose.c \
     client.c \
+    consolekit.c \
     ctrl.c \
     daemon.c \
     dm.c \