$OpenBSD: patch-app_cpp,v 1.2 2009/11/05 19:05:12 landry Exp $ Slim used to spawn 'xauth add . ' via the system() call, so the cookie itself was visible. On multi-user system one can poll for the xauth processes via ps and gather cookies for X sessions. fixes CVE-2009-1756 --- app.cpp.orig Fri Sep 26 02:54:15 2008 +++ app.cpp Wed Oct 28 19:31:08 2009 @@ -32,6 +32,62 @@ using namespace std; +/* Code taken from http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=529306 */ +/* From: Eygene Ryabinkin */ +#include +#include + +/* + * Adds the given cookie to the specified Xauthority file. + * Returns true on success, false on fault. + */ +bool Util::add_mcookie(const std::string &mcookie, const char *display, + const std::string &xauth_cmd, const std::string &authfile) +{ + FILE *fp; + std::string cmd = xauth_cmd + " -f " + authfile + " -q"; + + fp = popen(cmd.c_str(), "w"); + if (!fp) + return false; + fprintf(fp, "remove %s\n", display); + fprintf(fp, "add %s %s %s\n", display, ".", mcookie.c_str()); + fprintf(fp, "exit\n"); + + pclose(fp); + return true; +} +/* + * Interface for random number generator. Just now it uses ordinary + * random/srandom routines and serves as a wrapper for them. + */ +void Util::srandom(unsigned long seed) +{ + ::srandom(seed); +} + +long Util::random(void) +{ + return ::random(); +} + +/* + * Makes seed for the srandom() using "random" values obtained from + * getpid(), time(NULL) and others. + */ +long Util::makeseed(void) +{ + struct timespec ts; + long pid = getpid(); + long tm = time(NULL); + + if (clock_gettime(CLOCK_MONOTONIC, &ts) != 0) { + ts.tv_sec = ts.tv_nsec = 0; + } + + return pid + tm + (ts.tv_sec ^ ts.tv_nsec); +} + #ifdef USE_PAM #include @@ -104,7 +160,8 @@ extern App* LoginApp; void CatchSignal(int sig) { cerr << APPNAME << ": unexpected signal " << sig << endl; - LoginApp->StopServer(); + if (LoginApp->serverStarted) + LoginApp->StopServer(); LoginApp->RemoveLock(); exit(ERR_EXIT); } @@ -131,12 +188,13 @@ void User1Signal(int sig) { App::App(int argc, char** argv): pam(conv, static_cast(&LoginPanel)){ #else -App::App(int argc, char** argv){ +App::App(int argc, char** argv) : mcookiesize(32) { #endif int tmp; ServerPID = -1; + serverStarted = false; testing = false; - mcookie = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"; + mcookie = string(App::mcookiesize, 'a'); daemonmode = false; force_nodaemon = false; firstlogin = true; @@ -856,6 +914,8 @@ int App::StartServer() { char* args = new char[argOption.length()+2]; // NULL plus vt strcpy(args, argOption.c_str()); + serverStarted = false; + int argc = 1; int pos = 0; bool hasVtSet = false; @@ -935,7 +995,7 @@ int App::StartServer() { } delete args; - + serverStarted = true; return ServerPID; } @@ -1127,13 +1187,13 @@ string App::findValidRandomTheme(const string& set) name = name.substr(0, name.length() - 1); } - srandom(getpid()+time(NULL)); + Util::srandom(Util::makeseed()); vector themes; string themefile; Cfg::split(themes, name, ','); do { - int sel = random() % themes.size(); + int sel = Util::random() % themes.size(); name = Cfg::Trim(themes[sel]); themefile = string(THEMESDIR) +"/" + name + THEMESFILE; @@ -1159,34 +1219,32 @@ void App::replaceVariables(string& input, } } - +/* + * We rely on the fact that all bits generated by Util::random() + * are usable, so we are taking full words from its output. + */ void App::CreateServerAuth() { /* create mit cookie */ - int i, r; - int hexcount = 0; - string authfile; - string cmd; + uint16_t word; + uint8_t hi, lo; + int i; + string authfile; const char *digits = "0123456789abcdef"; - srand( time(NULL) ); - for ( i = 0; i < 31; i++ ) { - r = rand()%16; - mcookie[i] = digits[r]; - if (r>9) - hexcount++; + Util::srandom(Util::makeseed()); + for (i = 0; i < App::mcookiesize; i+=4) { + word = Util::random() & 0xffff; + lo = word & 0xff; + hi = word >> 8; + mcookie[i] = digits[lo & 0x0f]; + mcookie[i+1] = digits[lo >> 4]; + mcookie[i+2] = digits[hi & 0x0f]; + mcookie[i+3] = digits[hi >> 4]; } - /* MIT-COOKIE: even occurrences of digits and hex digits */ - if ((hexcount%2) == 0) { - r = rand()%10; - } else { - r = rand()%5+10; - } - mcookie[31] = digits[r]; /* reinitialize auth file */ authfile = cfg->getOption("authfile"); remove(authfile.c_str()); putenv(StrConcat("XAUTHORITY=", authfile.c_str())); - cmd = cfg->getOption("xauth_path") + " -q -f " + authfile + " add :0 . " + mcookie; - system(cmd.c_str()); + Util::add_mcookie(mcookie, ":0", cfg->getOption("xauth_path"), authfile); } char* App::StrConcat(const char* str1, const char* str2) {