[prev in list] [next in list] [prev in thread] [next in thread] 

List:       kde-commits
Subject:    KDE/kdebase/workspace/kdm
From:       Oswald Buddenhagen <ossi () kde ! org>
Date:       2010-02-28 20:39:28
Message-ID: 1267389568.267487.31895.nullmailer () svn ! kde ! org
[Download RAW message or body]

SVN commit 1097269 by ossi:

make it possible to run greeter as non-root

genkdmconf will try to set it up, but currently it knows how to do
it only on debian-alikes (which have the adduser command).

CCMAIL: kde-packager@kde.org

 M  +2 -1      ChangeLog  
 M  +0 -2      TODO  
 M  +30 -17    backend/auth.c  
 M  +2 -1      backend/dm.h  
 M  +1 -0      backend/dm_auth.h  
 M  +4 -0      backend/dpylist.c  
 M  +21 -18    backend/process.c  
 M  +1 -1      backend/resource.c  
 M  +16 -3     backend/session.c  
 M  +12 -1     config.def  
 M  +82 -1     kfrontend/genkdmconf.c  
 M  +13 -11    kfrontend/kgreeter.cpp  


--- trunk/KDE/kdebase/workspace/kdm/ChangeLog #1097268:1097269
@@ -4,7 +4,8 @@
 
 2010-02-28  Oswald Buddenhagen <ossi@kde.org>
 
-	* Made it possible to run X server as non-root. Option ServerUID.
+	* Made it possible to run X server and greeter as non-root.
+	  Options ServerUID and GreeterUID.
 
 2009-10-17  Oswald Buddenhagen <ossi@kde.org>
 
--- trunk/KDE/kdebase/workspace/kdm/TODO #1097268:1097269
@@ -192,8 +192,6 @@
 - the process reaping from gClose should be in sync with the main loop.
 - kill warning on AIX - see bug #13628 (really present?)
 - xdmcp.c: make networkAddressToName use networkAddressToHostname?
-- options for running the greeter and the core unprivileged. problem: xauth.
-- make the openbsd _x11-user hack in auth.c sane
 - rethink the coupling of the kdm components, particularily the config reader.
   options:
   - keep things basically as-is, make the Xaccess interface even more flexible,
--- trunk/KDE/kdebase/workspace/kdm/backend/auth.c #1097268:1097269
@@ -335,7 +335,7 @@
 #define NAMELEN 255
 
 static FILE *
-makeServerAuthFile( struct display *d )
+makeServerAuthFile( struct display *d, char **authFile )
 {
 	FILE *f;
 	int i;
@@ -352,34 +352,32 @@
 	cleanUpFileName( d->name, cleanname, NAMELEN - 8 );
 	i = sprintf( nambuf, "%s/A%s-", authDir, cleanname );
 	if ((f = mkTempFile( nambuf, i ))) {
-		strDup( &d->authFile, nambuf );
+		strDup( authFile, nambuf );
 		return f;
 	}
 	return 0;
 }
 
-int
-saveServerAuthorizations( struct display *d, Xauth **auths, int count )
+static int
+saveAuthorizations( struct display *d, char **authFile, Xauth **auths, int count )
 {
 	FILE *auth_file;
 	int i;
 
-	if (!d->authFile && d->clientAuthFile && *d->clientAuthFile)
-		strDup( &d->authFile, d->clientAuthFile );
-	if (d->authFile) {
-		if (!(auth_file = fdOpenW( creat( d->authFile, 0600 ) ))) {
-			logError( "Cannot open X server authorization file %s\n", d->authFile );
-			free( d->authFile );
-			d->authFile = 0;
+	if (*authFile) {
+		if (!(auth_file = fdOpenW( creat( *authFile, 0600 ) ))) {
+			logError( "Cannot open X server authorization file %s\n", *authFile );
+			free( *authFile );
+			*authFile = 0;
 			return False;
 		}
 	} else {
-		if (!(auth_file = makeServerAuthFile( d ))) {
+		if (!(auth_file = makeServerAuthFile( d, authFile ))) {
 			logError( "Cannot create X server authorization file\n" );
 			return False;
 		}
 	}
-	debug( "file: %s  auth: %p\n", d->authFile, auths );
+	debug( "file: %s  auth: %p\n", *authFile, auths );
 	for (i = 0; i < count; i++) {
 		/*
 		 * User-based auths may not have data until
@@ -395,15 +393,30 @@
 	if (fclose( auth_file ) == EOF) {
 	  whoops:
 		logError( "Cannot write X server authorization file %s: %m\n",
-		          d->authFile );
-		unlink( d->authFile );
-		free( d->authFile );
-		d->authFile = 0;
+		          *authFile );
+		unlink( *authFile );
+		free( *authFile );
+		*authFile = 0;
 		return False;
 	}
 	return True;
 }
 
+int
+saveGreeterAuthorizations( struct display *d )
+{
+	return saveAuthorizations( d, &d->greeterAuthFile,
+	                           d->authorizations, d->authNum );
+}
+
+int
+saveServerAuthorizations( struct display *d, Xauth **auths, int count )
+{
+	if (!d->authFile && d->clientAuthFile && *d->clientAuthFile)
+		strDup( &d->authFile, d->clientAuthFile );
+	return saveAuthorizations( d, &d->authFile, auths, count );
+}
+
 void
 setLocalAuthorization( struct display *d )
 {
--- trunk/KDE/kdebase/workspace/kdm/backend/dm.h #1097268:1097269
@@ -288,6 +288,7 @@
 	Xauth **authorizations;     /* authorization data */
 	int authNum;                /* number of authorizations */
 	char *authFile;             /* file to store authorization in */
+	char *greeterAuthFile;      /* file to store authorization for greeter in */
 };
 
 #define d_location   1
@@ -475,7 +476,7 @@
 void gClosen( GPipe *pajp );
 int gOpen( GProc *proc,
            char **argv, const char *what, char **env, char *cname,
-           GPipe *igp );
+           const char *user, const char *authfile, GPipe *igp );
 int gClose( GProc *proc, GPipe *gp, int force );
 
 void gSendInt( int val );
--- trunk/KDE/kdebase/workspace/kdm/backend/dm_auth.h #1097268:1097269
@@ -83,6 +83,7 @@
 
 #endif /* XDMCP */
 
+int saveGreeterAuthorizations( struct display *d );
 int saveServerAuthorizations( struct display *d, Xauth **auths, int count );
 void cleanUpFileName( const char *src, char *dst, int len );
 void removeUserAuthorization( struct display *d );
--- trunk/KDE/kdebase/workspace/kdm/backend/dpylist.c #1097268:1097269
@@ -218,6 +218,10 @@
 				(void)unlink( d->authFile );
 				free( d->authFile );
 			}
+			if (d->greeterAuthFile) {
+				(void)unlink( d->greeterAuthFile );
+				free( d->greeterAuthFile );
+			}
 #ifdef XDMCP
 			XdmcpDisposeARRAY8( &d->peer );
 			XdmcpDisposeARRAY8( &d->from );
--- trunk/KDE/kdebase/workspace/kdm/backend/process.c #1097268:1097269
@@ -471,7 +471,7 @@
 
 int
 gOpen( GProc *proc, char **argv, const char *what, char **env, char *cname,
-       GPipe *gp )
+       const char *user, const char *authfile, GPipe *gp )
 {
 	char **margv;
 	int pip[2];
@@ -516,23 +516,26 @@
 		(void)Signal( SIGPIPE, SIG_IGN );
 		close( pip[0] );
 		fcntl( pip[1], F_SETFD, FD_CLOEXEC );
-		if (gp)
-			sprintf( coninfo, "CONINFO=%d %d %d %d",
-			         proc->pipe.fd.r, proc->pipe.fd.w, gp->fd.r, gp->fd.w );
-		else
-			sprintf( coninfo, "CONINFO=%d %d",
-			         proc->pipe.fd.r, proc->pipe.fd.w );
-		env = putEnv( coninfo, env );
-		if (debugLevel & DEBUG_VALGRIND) {
-			char **nmargv = xCopyStrArr( 1, margv );
-			nmargv[0] = locate( "valgrind" );
-			execute( nmargv, env );
-		} else if (debugLevel & DEBUG_STRACE) {
-			char **nmargv = xCopyStrArr( 1, margv );
-			nmargv[0] = locate( "strace" );
-			execute( nmargv, env );
-		} else
-			execute( margv, env );
+		if (changeUser( user, authfile )) {
+			if (gp)
+				sprintf( coninfo, "CONINFO=%d %d %d %d",
+				         proc->pipe.fd.r, proc->pipe.fd.w, gp->fd.r, gp->fd.w );
+			else
+				sprintf( coninfo, "CONINFO=%d %d",
+				         proc->pipe.fd.r, proc->pipe.fd.w );
+			env = putEnv( coninfo, env );
+			if (debugLevel & DEBUG_VALGRIND) {
+				char **nmargv = xCopyStrArr( 1, margv );
+				nmargv[0] = locate( "valgrind" );
+				execute( nmargv, env );
+			} else if (debugLevel & DEBUG_STRACE) {
+				char **nmargv = xCopyStrArr( 1, margv );
+				nmargv[0] = locate( "strace" );
+				execute( nmargv, env );
+			} else {
+				execute( margv, env );
+			}
+		}
 		write( pip[1], "", 1 );
 		exit( 1 );
 	default:
--- trunk/KDE/kdebase/workspace/kdm/backend/resource.c #1097268:1097269
@@ -54,7 +54,7 @@
 	if (!getter.pid) {
 		if (gOpen( &getter,
 		           originalArgv, "_config", 0, strdup( "config reader" ),
-		           0 ))
+		           "", 0, 0 ))
 			logPanic( "Cannot run config reader\n" );
 		debug( "getter now ready\n" );
 	}
--- trunk/KDE/kdebase/workspace/kdm/backend/session.c #1097268:1097269
@@ -35,6 +35,7 @@
  */
 
 #include "dm.h"
+#include "dm_auth.h"
 #include "dm_error.h"
 
 #include <X11/Xlib.h>
@@ -433,9 +434,13 @@
 	/* Load system default Resources (if any) */
 	loadXloginResources();
 
+	if (*greeterUID && !saveGreeterAuthorizations( td ))
+		sessionExit( EX_UNMANAGE_DPY );
+
 	grttalk.pipe = &grtproc.pipe;
 	env = systemEnv( dupEnv(), 0 );
-	if (gOpen( &grtproc, (char **)0, "_greet", env, name, &td->gpipe ))
+	if (gOpen( &grtproc, (char **)0, "_greet", env, name,
+	           greeterUID, td->greeterAuthFile, &td->gpipe ))
 		sessionExit( EX_UNMANAGE_DPY );
 	freeStrArr( env );
 	if ((cmd = ctrlGreeterWait( True ))) {
@@ -462,6 +467,12 @@
 		sessionExit( wcCode( ret ) );
 	}
 
+	if (td->greeterAuthFile) {
+		(void)unlink( td->greeterAuthFile );
+		free( td->greeterAuthFile );
+		td->greeterAuthFile = 0;
+	}
+
 	deleteXloginResources();
 
 	return ret;
@@ -825,9 +836,11 @@
 char **
 systemEnv( char **env, const char *user )
 {
+	const char *authFile;
+
 	env = baseEnv( env, user );
-	if (td->authFile)
-		env = setEnv( env, "XAUTHORITY", td->authFile );
+	if ((authFile = td->greeterAuthFile) || (authFile = td->authFile))
+		env = setEnv( env, "XAUTHORITY", authFile );
 	env = setEnv( env, "PATH", td->systemPath );
 	env = setEnv( env, "SHELL", td->systemShell );
 	return env;
--- trunk/KDE/kdebase/workspace/kdm/config.def #1097268:1097269
@@ -1029,12 +1029,23 @@
  The group to which the global command socket should belong;
  can be either a name or a numerical ID.
 
+Key: GreeterUID
+Type: string
+Default: ""
+User: core
+Instance: "kdm"
+Update: upd_greeteruid
+Comment: &
+Description:
+ The user the greeter should run as. Empty results in <systemitem class="username">root</systemitem>.
+ Consider the impact on <option>LogSource</option> when setting it.
+
 Key: DataDir
 Type: path
 Default: *"/var/lib/kdm"
 User: greeter
 Instance: #""
-Update: upd_datadir
+Update: upd_datadir/1
 Comment:
  The directory in which &kdm; should store persistent working data.
 Description:
--- trunk/KDE/kdebase/workspace/kdm/kfrontend/genkdmconf.c #1097268:1097269
@@ -43,6 +43,7 @@
 #include <time.h>
 #include <limits.h>
 #include <sys/stat.h>
+#include <sys/wait.h>
 #include <sys/param.h>
 
 #define WANT_CONF_GEN
@@ -399,7 +400,29 @@
 	return 0;
 }
 
+static int
+runAndWait( char **args )
+{
+	int pid, ret;
 
+	switch ((pid = fork())) {
+	case 0:
+		execv( args[0], args );
+		fprintf( stderr, "Cannot execute %s: %s\n",
+		         args[0], strerror( errno ) );
+		_exit( 127 );
+	case -1:
+		fprintf( stderr, "Cannot fork to execute %s: %s\n",
+		         args[0], strerror( errno ) );
+		return -1;
+	}
+	while (waitpid( pid, &ret, 0 ) < 0)
+		if (errno != EINTR)
+			return -1;
+	return ret;
+}
+
+
 /*
  * target data to be written to kdmrc
  */
@@ -2042,20 +2065,78 @@
 	chmod( dir, st.st_mode | 0755 );
 }
 
+static gid_t greeter_gid;
+static uid_t greeter_uid;
+
 static void
+upd_greeteruid( Entry *ce, Section *cs ATTR_UNUSED )
+{
+	struct passwd *pw;
+	char *ok, *adduser;
+	int uid;
+
+	if (use_destdir || !ce->active)
+		return;
+	if (!(pw = getpwnam( ce->value ))) {
+		uid = strtol( ce->value, &ok, 10 );
+		if (*ok || !(pw = getpwuid( uid ))) {
+			if ((adduser = locate( "adduser" ))) { /* Debian-style */
+				const char *args[] = {
+					adduser, "--system", "--group",
+					"--home", "/var", "--no-create-home",
+					ce->value, 0
+				};
+				if (runAndWait( (char **)args )) {
+					fprintf( stderr, "Warning: Creation of missing GreeterUID"
+					                 " user %s failed\n", ce->value );
+					ce->active = False;
+					return;
+				}
+			} else {
+				fprintf( stderr, "Warning: Do not know how to create missing"
+				                 " GreeterUID user %s\n", ce->value );
+				ce->active = False;
+				return;
+			}
+			if (!(pw = getpwnam( ce->value ))) {
+				fprintf( stderr, "Warning: Newly created GreeterUID user %s"
+				                 " still missing!?\n", ce->value );
+				ce->active = False;
+				return;
+			}
+		}
+	}
+	greeter_uid = pw->pw_uid;
+	greeter_gid = pw->pw_gid;
+}
+
+static void
 upd_datadir( Entry *ce, Section *cs ATTR_UNUSED )
 {
 	char *oldsts, *newsts;
 	const char *dir;
+	struct stat st;
 
 	if (use_destdir)
 		return;
 	dir = ce->active ? ce->value : def_DataDir;
+	ASPrintf( &newsts, "%s/kdmsts", dir );
 	if (mkdirp( dir, 0755, "data", 0 ) && oldkde) {
 		ASPrintf( &oldsts, "%s/kdm/kdmsts", oldkde );
-		ASPrintf( &newsts, "%s/kdmsts", dir );
 		rename( oldsts, newsts );
 	}
+	if (stat( dir, &st ))
+		return;
+	if ((st.st_uid != greeter_uid || st.st_gid != greeter_gid) &&
+	    chown( dir, greeter_uid, greeter_gid ))
+		fprintf( stderr, "Warning: Cannot assign ownership of data directory"
+		                 " %s: %s\n", dir, strerror( errno ) );
+	if (stat( newsts, &st ))
+		return;
+	if ((st.st_uid != greeter_uid || st.st_gid != greeter_gid) &&
+	    chown( newsts, greeter_uid, greeter_gid ))
+		fprintf( stderr, "Warning: Cannot assign ownership of status file"
+		                 " %s: %s\n", newsts, strerror( errno ) );
 }
 
 static void
--- trunk/KDE/kdebase/workspace/kdm/kfrontend/kgreeter.cpp #1097268:1097269
@@ -366,14 +366,15 @@
 {
 	struct passwd *ps;
 
-	// XXX remove seteuid-voodoo when we run as nobody
-	if (!(ps = getpwnam( "nobody" )))
-		return;
-	if (setegid( ps->pw_gid ))
-		return;
-	if (seteuid( ps->pw_uid )) {
-		setegid( 0 );
-		return;
+	if (!getuid()) {
+		if (!(ps = getpwnam( "nobody" )))
+			return;
+		if (setegid( ps->pw_gid ))
+			return;
+		if (seteuid( ps->pw_uid )) {
+			setegid( 0 );
+			return;
+		}
 	}
 
 	QImage default_pix;
@@ -436,9 +437,10 @@
 			userList->sort();
 	}
 
-	// XXX remove seteuid-voodoo when we run as nobody
-	seteuid( 0 );
-	setegid( 0 );
+	if (!getuid()) {
+		seteuid( 0 );
+		setegid( 0 );
+	}
 }
 
 void
[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic