From kde-commits Sun Feb 28 20:39:28 2010 From: Oswald Buddenhagen Date: Sun, 28 Feb 2010 20:39:28 +0000 To: kde-commits Subject: KDE/kdebase/workspace/kdm Message-Id: <1267389568.267487.31895.nullmailer () svn ! kde ! org> X-MARC-Message: https://marc.info/?l=kde-commits&m=126739015613615 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 - * 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 --- 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 @@ -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 root. + Consider the impact on 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 #include #include +#include #include #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