Example #1
0
//Stand-alone function to check a username/password combination for validity
void XProcess::checkPW(QString user, QString pwd){
  xuser = Backend::getUsernameFromDisplayname(user); 
  xpwd = pwd;
  bool ok = pam_checkPW();
  pam_shutdown();
  xuser.clear();
  xpwd.clear();
  if(ok){ emit ValidLogin(); }
  else{ emit InvalidLogin(); }
}
Example #2
0
//Stand-alone function to check a username/password combination for validity
void XProcess::checkPW(QString user, QString pwd){
  if(USERS->isReady(user)){ xuser = user; }
  else{ xuser = USERS->findUser(user); } //convert display name into username
  //xuser = Backend::getUsernameFromDisplayname(user); 
  xpwd = pwd;
  bool ok = pam_checkPW();
  pam_shutdown();
  xuser.clear();
  xpwd.clear();
  if(ok){ emit ValidLogin(); }
  else{ emit InvalidLogin(); }
}
Example #3
0
void XProcess::setupDesktop(QString user, QString pwd, QString desktop){
  //Setup internal variables
  xuser = Backend::getUsernameFromDisplayname(user);
  xpwd = pwd;
  xhome = Backend::getUserHomeDir(xuser);
  xcmd = Backend::getDesktopBinary(desktop);
  xde = desktop;
  //Also check password  validity
  bool ok = pam_checkPW();
  pam_shutdown();
  if(ok){ emit ValidLogin(); }
  else{ emit InvalidLogin(); }
}
Example #4
0
void XProcess::slotCleanup(){
  Backend::log("Session Finished\n - Return Code: "+ QString::number(this->exitCode()) );
  pam_shutdown(); //make sure that PAM shuts down properly
  this->closeWriteChannel();
  this->closeReadChannel(QProcess::StandardOutput);
  this->closeReadChannel(QProcess::StandardError);
  //Now remove this user's access to the Xserver
  QString xhostcmd = "xhost -si:localuser:"******" - Removing Stealth session"; }
    QProcess::execute("personacrypt temprem"); //remove the temporary home-dir
  }else if( !xdevpass.isEmpty() ){
    if(DEBUG){ Backend::log(" - Unmounting PersonaCrypt User: "******" WARNING: Could not unmount user device (attempt "+QString::number(tries)+"/10)");
      tries++;
      QObject().thread()->usleep(500000); //wait 1/2 second before trying again (max 5 seconds)
    }
    if(tries>10){ Backend::log(" ERROR: Could not unmount user device"); }
    else{ Backend::log(" SUCCESS: User device unmounted"); }
  }
}
Example #5
0
bool XProcess::startXSession(){
  //Check that the necessary info to start the session is available
  if( xuser.isEmpty() || xcmd.isEmpty() || xhome.isEmpty() || xde.isEmpty() ){
    emit InvalidLogin();  //Make sure the GUI knows that it was a failure
    return FALSE;
  }
  //Backend::log("Starting up Desktop environment ("+xcmd+") as user ("+xuser+")");
  
  //Check for PAM username/password validity
  if( !pam_checkPW() ){ emit InvalidLogin(); pam_shutdown(); return FALSE; }


  //Save the current user/desktop as the last login
  Backend::saveLoginInfo(Backend::getDisplayNameFromUsername(xuser),xde);

  // Get the users uid/gid information
  struct passwd *pw;
  int uid;
  char *ok;

  if (!(pw = getpwnam(xuser.toLatin1()))) {
      uid = strtol(xuser.toLatin1(), &ok, 10);
      if (!(pw = getpwuid(uid))) {
    	  emit InvalidLogin();  //Make sure the GUI knows that it was a failure
          return FALSE;
      }
  }

  // Get the environment before we drop priv
  QProcessEnvironment environ = QProcessEnvironment::systemEnvironment(); //current environment

  QWidget *wid = new QWidget();
  if (setgid(pw->pw_gid) < 0) {
      qDebug() << "setgid() failed!";
      emit InvalidLogin();  //Make sure the GUI knows that it was a failure
      return FALSE;
  }

  // Setup our other groups
  if (initgroups(xuser.toLatin1(), pw->pw_gid) < 0) {
      qDebug() << "initgroups() failed!";
      emit InvalidLogin();  //Make sure the GUI knows that it was a failure
      setgid(0);
      return FALSE;
  }

  // Lets drop to user privs
  if (setuid(pw->pw_uid) < 0) {
      qDebug() << "setuid() failed!";
      emit InvalidLogin();  //Make sure the GUI knows that it was a failure
      return FALSE;
  }

  //Startup the PAM session
  if( !pam_startSession() ){ pam_shutdown(); return FALSE; }
  pam_session_open = TRUE; //flag that pam has an open session
  
  QString cmd;
  // Configure the DE startup command
  //  - Setup to run the user's <home-dir>/.xprofile startup script
  if(QFile::exists(xhome+"/.xprofile")){
    //cmd.append(". "+xhome+"/.xprofile; ");  //make sure to start it in parallel
  }
  //  - Add the DE startup command to the end
  //cmd.append("dbus-launch --exit-with-session "+xcmd);
  cmd.append(xcmd);
  //cmd.append("; kill -l KILL"); //to clean up the session afterwards
  // Get the current locale code
  QLocale mylocale;
  QString langCode = mylocale.name();
  
  //Backend::log("Startup command: "+cmd);
  // Setup the process environment

  // Setup any specialized environment variables
  // USER, HOME, and SHELL are set by the "su" login
  environ.insert("LOGNAME",xuser); //Login name
  environ.insert("USERNAME",xuser); // Username
  environ.insert("PATH",environ.value("PATH")+":"+xhome+"/bin"); // Append the user's home dir to the path
  if( langCode.toLower() == "c" ){} // do nothing extra to it
  else if(!environ.value("MM_CHARSET").isEmpty() ){ langCode.append( "."+environ.value("MM_CHARSET") ); }
  else{ langCode.append(".UTF-8"); }
  environ.insert("LANG",langCode); //Set the proper localized language
  environ.insert("MAIL","/var/mail/"+xuser); //Set the mail variable
  environ.insert("GROUP",xuser); //Set the proper group id
  environ.insert("SHLVL","0"); //Set the proper shell level
  environ.insert("HOME",xhome); //Set the users home directory
  this->setProcessEnvironment(environ);
  this->setWorkingDirectory(xhome); //set the current directory to the user's home directory
  //Log the DE startup outputs as well
  this->setStandardOutputFile(xhome+"/.pcdm-startup.log",QIODevice::Truncate);
  this->setStandardErrorFile(xhome+"/.pcdm-startup.err",QIODevice::Truncate);
  // Startup the process
  QMessageBox::warning(wid, "My Application", "CMD: " + cmd, QMessageBox::Ok, QMessageBox::Ok);
  this->start(cmd);
  return TRUE;
}
Example #6
0
//Start the desktop in the current process with C functions
void XProcess::startDesktop(){
  //Check for PAM username/password validity
  if( !pam_checkPW() ){ qDebug() << "Invalid username/password"; pam_shutdown(); return; }
  //Startup the PAM session
  if( !pam_startSession() ){ qDebug() << "Unable to open PAM session"; pam_shutdown(); return; }
  pam_session_open = TRUE; //flag that pam has an open session
  
  //Save the current user/desktop as the last login
  Backend::saveLoginInfo(Backend::getDisplayNameFromUsername(xuser),xde);

  // We will now fork off, so the child can drop root perms and do its thing
  int pid = fork();
  if(pid < 0){
    Backend::log("Error: Could not fork for user permissions");
    return;
  }else if( pid !=0 ){
    //Parent (calling) process
    int status;
    sleep(2);
    waitpid(pid,&status,0); //wait for the child (session) to finish

    // Child is all done, lets close down the pam session and cleanup
    pam_shutdown();
    exit(0);
  }
  
  // Get the users uid/gid information
  struct passwd *pw;
  int uid;
  char *ok;

  if (!(pw = getpwnam(xuser.toLatin1()))) {
      uid = strtol(xuser.toLatin1(), &ok, 10);
      if (!(pw = getpwuid(uid))) {
    	  emit InvalidLogin();  //Make sure the GUI knows that it was a failure
          return;
      }
  }

  if (setgid(pw->pw_gid) < 0) {
      qDebug() << "setgid() failed!";
      emit InvalidLogin();  //Make sure the GUI knows that it was a failure
      return;
  }

  // Setup our other groups
  if (initgroups(xuser.toLatin1(), pw->pw_gid) < 0) {
      qDebug() << "initgroups() failed!";
      emit InvalidLogin();  //Make sure the GUI knows that it was a failure
      setgid(0);
      return;
  } 

  // Lets drop to user privs
  if (setuid(pw->pw_uid) < 0) {
      qDebug() << "setuid() failed!";
      emit InvalidLogin();  //Make sure the GUI knows that it was a failure
      return;
  }

  QString cmd;
  // Configure the DE startup command
  //  - Setup to run the user's <home-dir>/.xprofile startup script
  if(QFile::exists(xhome+"/.xprofile")){
    cmd.append(". "+xhome+"/.xprofile; ");  //make sure to start it in parallel
  }
  //  - Add the DE startup command to the end
  cmd.append("dbus-launch --exit-with-session "+xcmd);

  // Get the current locale code
  QLocale mylocale;
  QString langCode = mylocale.name();
  
  //Alternate way of starting a process using c library functions
 
  //setup the environment variables
  setenv("LOGNAME",xuser.toUtf8(),1);
  setenv("USERNAME",xuser.toUtf8(),1);
  QString pth = QString(getenv("PATH"))+":"+xhome+"/bin";
  setenv("PATH",pth.toUtf8(),1);
  if(langCode.toLower()=="c"){}
  else if(QString(getenv("MM_CHARSET")).isEmpty() ){ langCode.append("."+QString(getenv("MM_CHARSET"))); }
  else{ langCode.append(".UTF-8"); }
  setenv("LANG",langCode.toUtf8(),1);
  setenv("MAIL",QString("/var/mail/"+xuser).toUtf8(),1);
  setenv("GROUP",xuser.toUtf8(),1);
  setenv("HOME",xhome.toUtf8(),1);
  setenv("SHELL",pw->pw_shell,1);
  setenv("SHLVL","0",1);
  chdir(xhome.toUtf8()); //move to home dir
   
  //Now start the process
  system(cmd.toLatin1());
}
Example #7
0
void XProcess::slotCleanup(int exitCode, QProcess::ExitStatus status){
  pam_shutdown(); //make sure that PAM shuts down properly	
}
Example #8
0
bool XProcess::startXSession(){
  //Returns true if the session can continue, or false if it needs to be closed down
  qDebug() << "Starting X Session:" << xuser << xcmd << xhome << xde << VT;
  //Check that the necessary info to start the session is available
  if( xuser.isEmpty() || xcmd.isEmpty() || xhome.isEmpty() || xde.isEmpty() ){
    emit InvalidLogin();  //Make sure the GUI knows that it was a failure
    return true;
  }
  //Backend::log("Starting up Desktop environment ("+xcmd+") as user ("+xuser+")");

  //Check for PAM username/password validity
  if( !pam_checkPW() ){ emit InvalidLogin(); pam_shutdown(); return true; }

  //Make sure the user is added to any required groups
  QStringList cgroups = Backend::runShellCommand("id -nG "+xuser).join("").split(" "); //current groups
  if(!cgroups.contains("video")){ Backend::runShellCommand("pw group mod video -m "+xuser); } //add user to video group (required for GPU access)

  //If this has a special device password, mount the personacrypt device
  if( !xanonlogin && !xdevpass.isEmpty() ){ //&& Backend::getAvailablePersonaCryptUsers().contains(xuser) ){
    Backend::log(" - PersonaCrypt Login Detected");
    if( !Backend::MountPersonaCryptUser(xuser, xdevpass) ){
      //Could not mount the personacrypt device (invalid password?)
      xdevpass.clear(); //clear the invalid password
      emit InvalidLogin(); pam_shutdown(); return true;
    }else{
      //overwrite the password in memory, but leave it flagged (not empty)
      if(DEBUG){ qDebug() << "Mounted PersonaCrypt Device"; }
      xdevpass.clear();
      xdevpass = "******";
    }
  }

  //Save the current user/desktop as the last login
  Backend::saveLoginInfo(xuser, xhome, xde);

  // Get the users uid/gid information
  struct passwd *pw;
  int uid;
  char *ok;

  if (!(pw = getpwnam(xuser.toLatin1()))) {
      uid = strtol(xuser.toLatin1(), &ok, 10);
      if (!(pw = getpwuid(uid))) {
          return false;
      }
  }

  //Emit the last couple logs before dropping privileges
  Backend::log("Starting session:");
  Backend::log(" - Session Log: ~/.pcdm-startup.log");
  QProcess::execute("killall compton");
  //For sanity's sake, ensure that the ZFS mountpoint are all available first
  if(QFile::exists("/sbin/zfs")){
    QProcess::execute("zfs mount -a"); //just to ensure the user's home dir is actually mounted
  }
  //Check/create the user's home-dir before dropping privs
  if(!QFile::exists(xhome)){
    qDebug() << "No Home dir found - populating...";
    QString hmcmd = "pw usermod "+xuser+" -m";
    QProcess::execute(hmcmd);
  }
  //If this is an anonymous login, create the blank home-dir on top
  if(xanonlogin){
    if(DEBUG){ qDebug() << " - Stealth Session selected"; }
    QProcess::execute("personacrypt tempinit "+xuser+" 10G"); //always use 10GB blank dir
  }

  // Get the environment before we drop priv
  this->setProcessEnvironment( QProcessEnvironment::systemEnvironment() ); //current environment

  //Now allow this user access to the Xserver
  QString xhostcmd = "xhost si:localuser:"******"/tmp/pcdm-session."+VT+".XXXXXX");
  if ( ! tFile->open() )
     return false;

  QTextStream tOut(tFile);

  // Configure the DE startup command
  if(QFile::exists("/usr/local/bin/dbus-launch") && !xcmd.contains("lumina-desktop") ){
    cmd.append("dbus-launch --exit-with-session "+xcmd);
  }else{
    cmd.append(xcmd);
  }

  QString tUid, tGid, logFile;
  tUid.setNum(pw->pw_uid);
  tGid.setNum(pw->pw_gid);
  logFile=xhome + "/.pcdm-startup.log";

  // Locate the auth file
  QString authfile = qgetenv("XAUTHORITY");
  if ( authfile.isEmpty() )
    authfile = xhome + "/.Xauthority";

  //Need to run a couple commands in sequence: so put them in a script file
  tOut << "#!/bin/sh\n\n";

  QString PICOCLIENT = qgetenv("PICO_CLIENT_LOGIN");
  QString PICOHOME = qgetenv("PICO_CLIENT_HOME");
  if ( ! PICOCLIENT.isEmpty() && ! PICOHOME.isEmpty() ) {
    // Change ownership on the Xauthority file for PICO usage
    tOut << "rm "+authfile+"\n";
    tOut << "ln -fs "+PICOHOME+"/.Xauthority "+authfile+"\n";
    QString PICOPULSE = qgetenv("PICO_PULSE_COOKIE");
    // Check if PULSE is enabled
    if ( ! PICOPULSE.isEmpty() ) {
      tOut << "mkdir -p "+xhome+"/.config/pulse 2>/dev/null\n";
      tOut << "cp "+PICOPULSE+" "+xhome+"/.config/pulse/cookie\n";
      tOut << "chown "+tUid+":"+tGid+" " +xhome+"/.config/pulse/cookie\n";
    }
    QProcess::execute("chown "+tUid+" "+PICOHOME+"/.Xauthority"); // Change ownership on the pico login
  } else {
    // Change ownership on the Xauthority file
    QProcess::execute("chown "+tUid+":"+tGid+" "+authfile);
  }

  tOut << Backend::resetKbdCmd() + "\n"; //do this before sourcing .xprofile - in case there is a user-override set there
  tOut << "if [ -e '"+xhome+"/.xprofile' ] ; then\n";
  tOut << "  chmod 755 "+xhome+"/.xprofile\n";
  tOut << "  . "+xhome+"/.xprofile\n";
  tOut << "fi\n";
  tOut << cmd + "\n"; //+ " >" + xhome+ "/.pcdm-startup.log" + " 2>" + xhome + "/.pcdm-startup.log\n";
  tOut << "exit $?"; //Make sure we return the DE return value

  cmd = "/usr/local/share/PCDM/pcdm-session"; //+xuser+" "+tUid+" "+tGid+" "+tFile->fileName()+" "+logFile;
  QStringList cmdArgs; cmdArgs << xuser << tUid << tGid << tFile->fileName() << logFile;
  connect( this, SIGNAL(finished(int, QProcess::ExitStatus)), this, SLOT(slotCleanup()) );
  tFile->setPermissions(QFile::ReadOwner | QFile::WriteOwner |QFile::ReadGroup | QFile::ReadUser | QFile::ReadOther);
  tFile->close();

  if(DEBUG){ Backend::log("Starting session with:\n" + cmd ); }
  this->start(cmd, cmdArgs);
  return true;
}
Example #9
0
bool XProcess::startXSession(){
  //Returns true if the session can continue, or false if it needs to be closed down

  //Check that the necessary info to start the session is available
  if( xuser.isEmpty() || xcmd.isEmpty() || xhome.isEmpty() || xde.isEmpty() ){
    emit InvalidLogin();  //Make sure the GUI knows that it was a failure
    return true;
  }
  //Backend::log("Starting up Desktop environment ("+xcmd+") as user ("+xuser+")");
  
  //Check for PAM username/password validity
  if( !pam_checkPW() ){ emit InvalidLogin(); pam_shutdown(); return true; }

  //If this has a special device password, mount the personacrypt device
  if( !xanonlogin && !xdevpass.isEmpty() && Backend::getAvailablePersonaCryptUsers().contains(xuser) ){
    if( !Backend::MountPersonaCryptUser(xuser, xdevpass) ){ 
      //Could not mount the personacrypt device (invalid password?)
      xdevpass.clear(); //clear the invalid password
      emit InvalidLogin(); pam_shutdown(); return true; 
    }else{
      //overwrite the password in memory, but leave it flagged (not empty)
      if(DEBUG){ qDebug() << "Mounted PersonaCrypt Device"; }
      xdevpass.clear();
      xdevpass = "******"; 
    }
  }

  //Save the current user/desktop as the last login
  Backend::saveLoginInfo(xuser,xde);

  // Get the users uid/gid information
  struct passwd *pw;
  int uid;
  char *ok;

  if (!(pw = getpwnam(xuser.toLatin1()))) {
      uid = strtol(xuser.toLatin1(), &ok, 10);
      if (!(pw = getpwuid(uid))) {
          return false;
      }
  }

  //Emit the last couple logs before dropping privileges
  Backend::log("Starting session:");
  Backend::log(" - Session Log: ~/.pcdm-startup.log");
  //For sanity's sake, ensure that the ZFS mountpoint are all available first
  if(QFile::exists("/sbin/zfs")){
    QProcess::execute("zfs mount -a"); //just to ensure the user's home dir is actually mounted
  }
  //Check/create the user's home-dir before dropping privs
  if(!QFile::exists(xhome)){
    qDebug() << "No Home dir found - populating...";
    QString hmcmd = "pw usermod "+xuser+" -m";
    QProcess::execute(hmcmd);
  }
  //If this is an anonymous login, create the blank home-dir on top
  if(xanonlogin){
    if(DEBUG){ qDebug() << " - Stealth Session selected"; }
    QProcess::execute("personacrypt tempinit "+xuser+" 10G"); //always use 10GB blank dir
  }
  
  // Get the environment before we drop priv
  this->setProcessEnvironment( QProcessEnvironment::systemEnvironment() ); //current environment

  //Now allow this user access to the Xserver
  QString xhostcmd = "xhost si:localuser:"******"/usr/local/bin/dbus-launch")){
    cmd.append("dbus-launch --exit-with-session "+xcmd);
  }
  //Need to run a couple commands in sequence: so put them in a script file
  tOut << "#!/bin/sh\n\n";
  tOut << "if [ -e '"+xhome+"/.xprofile' ] ; then\n";
  tOut << "  chmod 755 "+xhome+"/.xprofile\n";
  tOut << "  . "+xhome+"/.xprofile\n";
  tOut << "fi\n";
  tOut << cmd + "\n"; //+ " >" + xhome+ "/.pcdm-startup.log" + " 2>" + xhome + "/.pcdm-startup.log\n";
  tOut << "exit $?"; //Make sure we return the DE return value

  QString tUid, tGid, logFile;
  tUid.setNum(pw->pw_uid);
  tGid.setNum(pw->pw_gid);
  logFile=xhome + "/.pcdm-startup.log";
  cmd = "/usr/local/share/PCDM/pcdm-session "+xuser+" "+tUid+" "+tGid+" "+tFile->fileName()+" "+logFile;
  connect( this, SIGNAL(finished(int, QProcess::ExitStatus)), this, SLOT(slotCleanup()) );
  tFile->setPermissions(QFile::ReadOwner | QFile::WriteOwner |QFile::ReadGroup | QFile::ReadUser | QFile::ReadOther);
  tFile->close();

  if(DEBUG){ Backend::log("Starting session with:\n" + cmd ); }
  this->start(cmd);
  return true;
}