[PC-BSD Commits] r22037 - pcbsd-projects/PCDM

svn at pcbsd.org svn at pcbsd.org
Wed Apr 3 08:54:31 PDT 2013


Author: kenmoore
Date: 2013-04-03 15:54:31 +0000 (Wed, 03 Apr 2013)
New Revision: 22037

Modified:
   pcbsd-projects/PCDM/main.cpp
   pcbsd-projects/PCDM/pcdm-backend.cpp
   pcbsd-projects/PCDM/pcdm-backend.h
   pcbsd-projects/PCDM/pcdm-config.cpp
   pcbsd-projects/PCDM/pcdm-config.h
   pcbsd-projects/PCDM/pcdm-gui.cpp
   pcbsd-projects/PCDM/pcdm-gui.h
   pcbsd-projects/PCDM/pcdm-xprocess.cpp
   pcbsd-projects/PCDM/pcdm-xprocess.h
Log:
Re-work how PCDM uses PAM for verification. It should now work with encrypted home directories and setup/close the PAM session appropriately. This still needs a bit of testing to make sure it works...



Modified: pcbsd-projects/PCDM/main.cpp
===================================================================
--- pcbsd-projects/PCDM/main.cpp	2013-04-03 11:19:59 UTC (rev 22036)
+++ pcbsd-projects/PCDM/main.cpp	2013-04-03 15:54:31 UTC (rev 22037)
@@ -59,15 +59,19 @@
     //Setup the Auto Login
     QString user = Backend::getALUsername();
     QString dcmd = Backend::getALDesktopCmd();
+    QString pwd = Backend::getALPassword();
     if( user.isEmpty() || dcmd.isEmpty() ){
 	 goodAL=FALSE;   
     }else{
-	desktop.setXUsername(user);
+	/*desktop.setXUsername(user);
 	desktop.setXCommand(dcmd);
 	desktop.setXHomeDir( Backend::getUserHomeDir(user) );
-	desktop.startXSession();
+	desktop.startXSession();*/
+	desktop.loginToXSession(user,pwd, Backend::getUserHomeDir(user), dcmd);
 	splash.close();
-	goodAL=TRUE; //flag this as a good login to skip the GUI
+	if(desktop.isRunning()){
+	  goodAL=TRUE; //flag this as a good login to skip the GUI
+	}
     }
   }
   //qDebug() << "AutoLogin Finished:" << QString::number(clock.elapsed())+" ms";
@@ -103,10 +107,10 @@
       w.setWindowState(Qt::WindowFullScreen);
 
     //Setup the signals/slots to startup the desktop session
-    QObject::connect( &w,SIGNAL(xUserFound(QString)), &desktop,SLOT(setXUsername(QString)) );
-    QObject::connect( &w,SIGNAL(xCmdFound(QString)), &desktop,SLOT(setXCommand(QString)) );
-    QObject::connect( &w,SIGNAL(xHomeFound(QString)), &desktop,SLOT(setXHomeDir(QString)) );
-    QObject::connect( &w,SIGNAL(xSessionStart()), &desktop,SLOT(startXSession()) );
+    QObject::connect( &w,SIGNAL(xLoginAttempt(QString,QString,QString,QString)), &desktop,SLOT(loginToXSession(QString,QString,QString,QString)) );
+    //Setup the signals/slots for return information for the GUI
+    QObject::connect( &desktop, SIGNAL(InvalidLogin()), &w, SLOT(slotLoginFailure()) );
+    QObject::connect( &desktop, SIGNAL(started()), &w, SLOT(slotLoginSuccess()) );
     
     //qDebug() << "Showing GUI:" << QString::number(clock.elapsed())+" ms";
     w.show();

Modified: pcbsd-projects/PCDM/pcdm-backend.cpp
===================================================================
--- pcbsd-projects/PCDM/pcdm-backend.cpp	2013-04-03 11:19:59 UTC (rev 22036)
+++ pcbsd-projects/PCDM/pcdm-backend.cpp	2013-04-03 15:54:31 UTC (rev 22037)
@@ -4,8 +4,8 @@
 *  Available under the 3-clause BSD license
 */
 
-#include <sys/types.h>
-#include <security/pam_appl.h>
+//#include <sys/types.h>
+//#include <security/pam_appl.h>
 #include <QProcess>
 #include <QProcessEnvironment>
 
@@ -51,7 +51,7 @@
   return displaynameList;
 }
 
-bool Backend::startUserLogin(QString username, QString password, QString xBinary){
+/*bool Backend::startUserLogin(QString username, QString password, QString xBinary){
   bool allowed = verifyUsernamePassword(username, password);
   if(allowed){
     Backend::log("Username/Password Authorized");
@@ -64,7 +64,7 @@
   }
   return allowed;
 }
-
+*/
 QString Backend::getALUsername(){
   //Make sure the requested user is valid
   readSystemUsers(); //first read the available users on this system
@@ -105,7 +105,12 @@
   return rdesktop;
 }
 
-void Backend::startAutoLogin(){
+QString Backend::getALPassword(){
+  QString rpassword = Config::autoLoginPassword();
+  return rpassword;
+}
+
+/*void Backend::startAutoLogin(){
   //Make sure the requested user is valid
   readSystemUsers(); //first read the available users on this system
   QString ruser = Config::autoLoginUsername();
@@ -203,7 +208,7 @@
   saveUsername.clear(); 
   saveX.clear();
 }
-
+*/
 QString Backend::getUsernameFromDisplayname(QString dspname){
   int i = displaynameList.indexOf(dspname);
   return usernameList[i];
@@ -441,7 +446,7 @@
   return output;
 
 }
-
+/*
 pam_handle_t *pamh;  //handle for the PAM process structure
 static struct pam_conv pamc = { openpam_nullconv, NULL }; //null conversation function for PAM
 
@@ -517,6 +522,7 @@
   //return verification result
   return result;	
 }
+*/
 
 void Backend::readSystemUsers(){
   //make sure the lists are empty

Modified: pcbsd-projects/PCDM/pcdm-backend.h
===================================================================
--- pcbsd-projects/PCDM/pcdm-backend.h	2013-04-03 11:19:59 UTC (rev 22036)
+++ pcbsd-projects/PCDM/pcdm-backend.h	2013-04-03 15:54:31 UTC (rev 22037)
@@ -13,9 +13,9 @@
 #include <QDir>
 #include <QProcess>
 
-#include <sys/types.h>
-#include <security/pam_appl.h>
-#include <security/openpam.h>
+//#include <sys/types.h>
+//#include <security/pam_appl.h>
+//#include <security/openpam.h>
 
 #include "pcdm-config.h"
 #include "pcbsd-utils.h"
@@ -37,8 +37,8 @@
     static QString getDesktopIcon(QString);
     static QString getDesktopBinary(QString);
     static QStringList getSystemUsers();
-    static bool startUserLogin(QString, QString, QString);
-    static void startAutoLogin();
+    //static bool startUserLogin(QString, QString, QString);
+    //static void startAutoLogin();
     static QString getUsernameFromDisplayname(QString);
     static QStringList keyModels();
     static QStringList keyLayouts();
@@ -47,17 +47,18 @@
     static QStringList languages();
     static void openLogFile(QString);
     static void log(QString);
-    static void startXSession();  
+    //static void startXSession();  
     static QString getUserHomeDir(QString);
     static void checkLocalDirs();
 
     static QString getALUsername();
     static QString getALDesktopCmd();
+    static QString getALPassword();
     
 private:	
     static void loadXSessionsData();
     static QStringList readXSessionsFile(QString, QString);
-    static bool verifyUsernamePassword(QString, QString);
+    //static bool verifyUsernamePassword(QString, QString);
     static void readSystemUsers();
  
     

Modified: pcbsd-projects/PCDM/pcdm-config.cpp
===================================================================
--- pcbsd-projects/PCDM/pcdm-config.cpp	2013-04-03 11:19:59 UTC (rev 22036)
+++ pcbsd-projects/PCDM/pcdm-config.cpp	2013-04-03 15:54:31 UTC (rev 22037)
@@ -20,7 +20,8 @@
   confStruct << "FALSE";				// [3] Auto-login enabled
   confStruct << "no-username";				// [4] Auto-login username
   confStruct << "no-desktop";				// [5] Auto-login desktop environment
-  confStruct << "/usr/local/share/PCDM/images/default-splash.png"; // [6] Splash Screen File
+  confStruct << "no-password";				// [6] Auto-login password
+  confStruct << "/usr/local/share/PCDM/images/default-splash.png"; // [7] Splash Screen File
   return;
 }
 
@@ -48,7 +49,8 @@
       else if(var=="ENABLE_AUTO_LOGIN"){ confStruct[3] = val; }
       else if(var=="AUTO_LOGIN_USER"){ confStruct[4] = val; }
       else if(var=="AUTO_LOGIN_DESKTOP"){ confStruct[5] = val; }
-      else if(var=="SPLASHSCREEN_FILE"){ confStruct[6] = val; }
+      else if(var=="AUTO_LOGIN_PASSWORD"){ confStruct[6] = val; }
+      else if(var=="SPLASHSCREEN_FILE"){ confStruct[7] = val; }
       else{}
       
     }
@@ -93,6 +95,10 @@
   else{ return (confStruct[1]+"/"+confStruct[5]); } //prepend the xsessions directory path
 }
 
-QString Config::splashscreen(){
+QString Config::autoLoginPassword(){
   return confStruct[6];	
 }
+
+QString Config::splashscreen(){
+  return confStruct[7];	
+}

Modified: pcbsd-projects/PCDM/pcdm-config.h
===================================================================
--- pcbsd-projects/PCDM/pcdm-config.h	2013-04-03 11:19:59 UTC (rev 22036)
+++ pcbsd-projects/PCDM/pcdm-config.h	2013-04-03 15:54:31 UTC (rev 22037)
@@ -29,6 +29,7 @@
   static bool useAutoLogin(); 		//returns whether auto-login is enabled
   static QString autoLoginUsername();	//returns username to log into automatically
   static QString autoLoginDesktop();	//return *.desktop file to startup automatically
+  static QString autoLoginPassword();	//returns password to log in automatically
   static QString splashscreen();	//return the image file for the splashscreen
 
 };

Modified: pcbsd-projects/PCDM/pcdm-gui.cpp
===================================================================
--- pcbsd-projects/PCDM/pcdm-gui.cpp	2013-04-03 11:19:59 UTC (rev 22036)
+++ pcbsd-projects/PCDM/pcdm-gui.cpp	2013-04-03 15:54:31 UTC (rev 22037)
@@ -230,11 +230,16 @@
   //Get user inputs
   QString username = Backend::getUsernameFromDisplayname(displayname);
   QString binary = Backend::getDesktopBinary(deSwitcher->currentItem());
+  QString homedir = Backend::getUserHomeDir(username);
   //Disable user input while confirming login
   loginW->setEnabled(FALSE);
   deSwitcher->setEnabled(FALSE);
   toolbar->setEnabled(FALSE);
   //Try to login
+  emit xLoginAttempt(username, password, homedir, binary);
+  //Return signals are connected to the slotLogin[Success/Failure] functions
+  
+  /*
   bool success = Backend::startUserLogin(username, password, binary); 
   if(success){
     emit xUserFound(username);
@@ -244,8 +249,19 @@
     saveLastLogin( displayname, deSwitcher->currentItem() );
     slotClosePCDM(); //now start to close down the PCDM GUI
   }else{
-    //Display an info box that the login failed
-    QMessageBox notice(this);
+   
+  }
+  */
+}
+
+void PCDMgui::slotLoginSuccess(){
+  saveLastLogin( loginW->currentUsername(), deSwitcher->currentItem() );
+  slotClosePCDM(); //now start to close down the PCDM GUI
+}
+
+void PCDMgui::slotLoginFailure(){
+  //Display an info box that the login failed
+  QMessageBox notice(this);
     notice.setWindowTitle(tr("Invalid Username/Password"));
     notice.setIcon(QMessageBox::Warning);
     notice.setText(tr("Username/Password combination is invalid, please try again."));
@@ -253,7 +269,7 @@
     notice.setStandardButtons(QMessageBox::Ok);
     notice.setDefaultButton(QMessageBox::Ok);
     notice.exec();
-  }
+	
   //Re-Enable user input
   loginW->setEnabled(TRUE);
   deSwitcher->setEnabled(TRUE);

Modified: pcbsd-projects/PCDM/pcdm-gui.h
===================================================================
--- pcbsd-projects/PCDM/pcdm-gui.h	2013-04-03 11:19:59 UTC (rev 22036)
+++ pcbsd-projects/PCDM/pcdm-gui.h	2013-04-03 15:54:31 UTC (rev 22037)
@@ -45,6 +45,8 @@
 
 private slots:
     void slotStartLogin(QString,QString);
+    void slotLoginSuccess();
+    void slotLoginFailure();
     void slotUserChanged(QString);
     void slotUserSelected(QString);
     void slotRestartComputer();
@@ -81,10 +83,11 @@
     void saveLastLogin(QString, QString);
 
 signals:
-    void xUserFound(QString);
+    void xLoginAttempt(QString, QString, QString, QString);
+    /*void xUserFound(QString);
     void xCmdFound(QString);
     void xHomeFound(QString);
-    void xSessionStart();
+    void xSessionStart(); */
 };
 
 #endif // PCDMGUI_H

Modified: pcbsd-projects/PCDM/pcdm-xprocess.cpp
===================================================================
--- pcbsd-projects/PCDM/pcdm-xprocess.cpp	2013-04-03 11:19:59 UTC (rev 22036)
+++ pcbsd-projects/PCDM/pcdm-xprocess.cpp	2013-04-03 15:54:31 UTC (rev 22037)
@@ -11,48 +11,76 @@
 #include "pcdm-xprocess.h"
 
 XProcess::XProcess() : QProcess(0) {
+  //initialize the variables
   xuser.clear();
   xcmd.clear();
   xhome.clear();
-  //session = new QProcess();
+  xpwd.clear();
+  pam_started = FALSE;
+  pam_session_open = FALSE;
+  //Setup the finished signal/slot
+  connect( this, SIGNAL(finished(int, QProcess::ExitStatus)), this, SLOT(slotCleanup(int, QProcess::ExitStatus)) );
 }
 
 XProcess::~XProcess(){
-  if( this->state() != QProcess::NotRunning){
+  if( isRunning() ){
     this->terminate();
   }
   this->close();
 }
 
-void XProcess::setXUsername(QString username){
-  xuser = username;	
+void XProcess::loginToXSession(QString username, QString password, QString homedir, QString cmd){
+  //Setup the variables
+  xuser = username;
+  xpwd = password;
+  xhome = homedir;
+  xcmd = cmd;
+  //Now start the login process
+  startXSession();
 }
 
-void XProcess::setXCommand(QString cmd){
-  xcmd = cmd;
+bool XProcess::isRunning(){
+  if(this->state() != QProcess::NotRunning){ return TRUE; }
+  else{ return FALSE; }
 }
 
-void XProcess::setXHomeDir(QString home){
-  xhome = home;	
+void XProcess::waitForSessionClosed(){
+  // CAUTION!! 
+  // This function will pause the calling program to wait for the session to end!
+  if( isRunning() ){
+    this->waitForFinished(-1);
+  }
 }
 
-void XProcess::startXSession(){
+/*
+ ========== SESSION STARTUP ==========
+*/
+
+bool XProcess::startXSession(){
   //Check that the necessary info to start the session is available
-  if( xuser.isEmpty() || xcmd.isEmpty() || xhome.isEmpty() ){
-    return;
+  if( xuser.isEmpty() || xcmd.isEmpty() || xhome.isEmpty() || xpwd.isEmpty() ){
+    return FALSE;
   }
   //Backend::log("Starting up Desktop environment ("+xcmd+") as user ("+xuser+")");
-
-  // Use the saved information
+  
+  //Check for PAM username/password validity
+  if( !pam_checkPW() ){ emit InvalidLogin(); return FALSE; }
+  pam_started = TRUE; //flag that pam is started
+  //Startup the PAM session
+  if( !pam_startSession() ){ return FALSE; }
+  pam_session_open = TRUE; //flag that pam has an open session
+  
+  // Configure the DE startup command
   QString cmd = "su "+xuser+" -c \""; //switch user command to start process properly
-  // Setup to run the user's <home-dir>/.xprofile startup script
+  //  - Setup to run the user's <home-dir>/.xprofile startup script
   if(QFile::exists(xhome+"/.xprofile")){
     cmd.append("(/bin/sh "+xhome+"/.xprofile) &; ");  //make sure to start it in parallel
   }
-  //Add the DE startup command to the end
+  //  - Add the DE startup command to the end
   cmd.append(xcmd);
-  //Finish up the command formatting
+  //  - Finish up the command formatting
   cmd.append("\"");
+  
   //Backend::log("Startup command: "+cmd);
   // Get the current locale code
   QLocale mylocale;
@@ -78,12 +106,124 @@
   this->setStandardOutputFile(xhome+"/.pcdm-startup.log",QIODevice::Truncate);
   // Startup the process
   this->start(cmd);
+  return TRUE;
 }
 
-void XProcess::waitForSessionClosed(){
-  // CAUTION!! 
-  // This function will pause the calling program to wait for the session to end!
-  if( this->state() != QProcess::NotRunning ){
-    this->waitForFinished(-1);
+void XProcess::slotCleanup(int exitCode, QProcess::ExitStatus status){
+  pam_shutdown(); //make sure that PAM shuts down properly	
+}
+
+/*
+ ========== PAM FUNCTIONS ==========
+*/
+static struct pam_conv pamc = { openpam_nullconv, NULL };
+
+bool XProcess::pam_checkPW(){
+ //Requires internal "xuser" and "xpwd" variables to be set
+	
+//Convert the inputs to C character arrays for use in PAM
+  QByteArray tmp = xuser.toUtf8();
+  char* cUser = tmp.data();
+  QByteArray tmp2 = xpwd.toUtf8();
+  char* cPassword = tmp2.data();
+  //initialize variables
+  bool result = FALSE;
+  int ret;
+  //Initialize PAM
+  ret = pam_start("login", cUser, &pamc, &pamh);
+  if( ret == PAM_SUCCESS ){
+    //Place the user-supplied password into the structure 
+    ret = pam_set_item(pamh, PAM_AUTHTOK, cPassword);
+    //Set the TTY 
+    //ret = pam_set_item(pamh, PAM_TTY, "pcdm-terminal");
+    //Authenticate with PAM
+    ret = pam_authenticate(pamh,0);
+    if( ret == PAM_SUCCESS ){
+      //Check for valid, unexpired account and verify access restrictions
+      ret = pam_acct_mgmt(pamh,0);
+      if( ret == PAM_SUCCESS ){ result = TRUE; }
+    
+    }else{
+      pam_logFailure(ret);
+    }
   }
+  //return verification result
+  return result;	
 }
+
+bool XProcess::pam_startSession(){
+  //This should only be run if pam_checkPW was successful
+  int ret = pam_open_session(pamh,0);
+  bool ok = FALSE;
+  if(ret == PAM_SUCCESS){ ok = TRUE; }
+  else{ pam_logFailure(ret); }
+  
+  return ok;
+}
+
+bool XProcess::pam_stopSession(){
+  //This should only be run if pam_startSession was successful
+  int ret = pam_close_session(pamh,0);
+  bool ok = FALSE;
+  if(ret == PAM_SUCCESS){ ok = TRUE; }
+  else{ pam_logFailure(ret); }
+  
+  return ok;
+}
+
+void XProcess::pam_logFailure(int ret){
+  //Interpret a PAM error message and log it
+  Backend::log("PAM Error: " + QString::number(ret));
+  switch( ret ){
+  case PAM_ABORT:
+    Backend::log(" - PAM abort error");
+    break;
+  case PAM_AUTHINFO_UNAVAIL:
+    Backend::log(" - Authentication info unavailable");
+    break;
+  case PAM_AUTH_ERR:
+    Backend::log(" - Authentication error");
+    break;
+  case PAM_BUF_ERR:
+    Backend::log(" - Buffer error");
+    break;
+  case PAM_CONV_ERR:
+    Backend::log(" - Conversion error");
+    break;
+  case PAM_CRED_INSUFFICIENT:
+    Backend::log(" - Credentials insufficient");
+    break;
+  case PAM_MAXTRIES:
+    Backend::log(" - Maximum number of tries exceeded");
+    break;
+  case PAM_PERM_DENIED:
+    Backend::log(" - Permission denied");
+    break;
+  case PAM_SERVICE_ERR:
+    Backend::log(" - Service error");
+    break;
+  case PAM_SYMBOL_ERR:
+    Backend::log(" - Symbol error");
+    break;
+  case PAM_SYSTEM_ERR:
+    Backend::log(" - System error");
+    break;
+  case PAM_USER_UNKNOWN:
+    Backend::log(" - Unknown user");
+    break;
+  default:
+    Backend::log(" - Unrecognized authentication error");
+  }
+	
+}
+
+void XProcess::pam_shutdown(){
+  if(pam_session_open){
+    pam_stopSession();
+    pam_session_open = FALSE;
+  }
+  if(pam_started){
+    pam_end(pamh,0);
+    pam_started = FALSE;
+  }
+}

Modified: pcbsd-projects/PCDM/pcdm-xprocess.h
===================================================================
--- pcbsd-projects/PCDM/pcdm-xprocess.h	2013-04-03 11:19:59 UTC (rev 22036)
+++ pcbsd-projects/PCDM/pcdm-xprocess.h	2013-04-03 15:54:31 UTC (rev 22037)
@@ -16,6 +16,12 @@
 #include <QProcess>
 #include <QProcessEnvironment>
 
+#include <sys/types.h>
+#include <security/pam_appl.h>
+#include <security/openpam.h>
+
+#include "pcdm-backend.h"
+
 class XProcess : public QProcess
 {
 	Q_OBJECT
@@ -23,17 +29,31 @@
   public:
 	XProcess();
 	~XProcess();
+	bool isRunning();
         void waitForSessionClosed();
   
   public slots:
-	void setXUsername(QString);
-        void setXCommand(QString);
-        void setXHomeDir(QString);
-        void startXSession();
-  
+        void loginToXSession(QString, QString, QString, QString); //user, pwd, homedir, cmd
+  	
   private:
-	QString xuser, xcmd, xhome;
-	//QProcess* session;
+	QString xuser, xcmd, xhome, xpwd;
+  	bool startXSession();
+	
+	// PAM stuff and simplification functions
+	pam_handle_t *pamh;  //handle for the PAM process structure
+	//static struct pam_conv pamc;// = { openpam_nullconv, NULL }; //null conversation function for PAM
+	bool pam_started, pam_session_open;
+	bool pam_checkPW();
+	bool pam_startSession();
+	bool pam_stopSession();
+	void pam_logFailure(int);
+  	void pam_shutdown(); //cleanly close all the PAM stuff
+	
+  private slots:
+  	void slotCleanup(int, QProcess::ExitStatus);
 
+  signals:
+  	void InvalidLogin();
+
 };
 #endif



More information about the Commits mailing list