source: src-qt4/PCDM/src/pcdm-xprocess.cpp @ 90dc161

9.2-releaseenter/10releng/10.0releng/10.0.1releng/10.0.2releng/10.0.3releng/10.1releng/10.1.1releng/10.1.2releng/10.2
Last change on this file since 90dc161 was 90dc161, checked in by Ken Moore <ken@…>, 2 years ago

Completely revamp how PCDM uses the previous login information. Now you no longer need to specify which desktop to auto-login to if you have auto-login selected. It will first try to check for previous login information for that user, then fall back on the last login for the system in order to try and auto login. Also fix the PCDMd script a bit so that autologins work properly when triggered.

  • Property mode set to 100644
File size: 6.9 KB
Line 
1/* PCDM Login Manager:
2*  Written by Ken Moore (ken@pcbsd.org) 2012/2013
3*  Copyright(c) 2013 by the PC-BSD Project
4*  Available under the 3-clause BSD license
5*/
6
7/*
8Sub-classed QProcess for starting an XSession Process
9*/
10
11#include "pcdm-xprocess.h"
12
13XProcess::XProcess() : QProcess(0) {
14  //initialize the variables
15  xuser.clear();
16  xcmd.clear();
17  xhome.clear();
18  xpwd.clear();
19  pam_started = FALSE;
20  pam_session_open = FALSE;
21  //Setup the finished signal/slot
22  connect( this, SIGNAL(finished(int, QProcess::ExitStatus)), this, SLOT(slotCleanup(int, QProcess::ExitStatus)) );
23}
24
25XProcess::~XProcess(){
26  if( isRunning() ){
27    this->terminate();
28  }
29  this->close();
30}
31
32void XProcess::loginToXSession(QString username, QString password, QString homedir, QString desktop){
33  //Setup the variables
34  xuser = username;
35  xpwd = password;
36  xhome = homedir;
37  xcmd = Backend::getDesktopBinary(desktop);
38  xde = desktop;
39  //Now start the login process
40  startXSession();
41}
42
43bool XProcess::isRunning(){
44  if(this->state() != QProcess::NotRunning){ return TRUE; }
45  else{ return FALSE; }
46}
47
48void XProcess::waitForSessionClosed(){
49  // CAUTION!!
50  // This function will pause the calling program to wait for the session to end!
51  if( isRunning() ){
52    this->waitForFinished(-1);
53  }
54}
55
56/*
57 ========== SESSION STARTUP ==========
58*/
59
60bool XProcess::startXSession(){
61  //Check that the necessary info to start the session is available
62  if( xuser.isEmpty() || xcmd.isEmpty() || xhome.isEmpty() || xde.isEmpty() ){
63    emit InvalidLogin();  //Make sure the GUI knows that it was a failure
64    return FALSE;
65  }
66  //Backend::log("Starting up Desktop environment ("+xcmd+") as user ("+xuser+")");
67 
68  //Check for PAM username/password validity
69  if( !pam_checkPW() ){ emit InvalidLogin(); pam_shutdown(); return FALSE; }
70  //Startup the PAM session
71  if( !pam_startSession() ){ pam_shutdown(); return FALSE; }
72  pam_session_open = TRUE; //flag that pam has an open session
73 
74  //Save the current user/desktop as the last login
75  Backend::saveLoginInfo(Backend::getDisplayNameFromUsername(xuser),xde);
76 
77  // Configure the DE startup command
78  QString cmd = "su "+xuser+" -c \""; //switch user command to start process properly
79  //  - Setup to run the user's <home-dir>/.xprofile startup script
80  if(QFile::exists(xhome+"/.xprofile")){
81    cmd.append("(/bin/sh "+xhome+"/.xprofile) &; ");  //make sure to start it in parallel
82  }
83  //  - Add the DE startup command to the end
84  cmd.append("dbus-launch --exit-with-session "+xcmd);
85  //  - Finish up the command formatting
86  cmd.append("\"");
87 
88  //Backend::log("Startup command: "+cmd);
89  // Get the current locale code
90  QLocale mylocale;
91  QString langCode = mylocale.name();
92  // Setup the process environment
93  QProcessEnvironment environ = QProcessEnvironment::systemEnvironment(); //current environment
94
95  // Setup any specialized environment variables
96  // USER, HOME, and SHELL are set by the "su" login
97  environ.insert("LOGNAME",xuser); //Login name
98  environ.insert("USERNAME",xuser); // Username
99  environ.insert("PATH",environ.value("PATH")+":"+xhome+"/bin"); // Append the user's home dir to the path
100  if( langCode.toLower() == "c" ){} // do nothing extra to it
101  else if(!environ.value("MM_CHARSET").isEmpty() ){ langCode.append( "."+environ.value("MM_CHARSET") ); }
102  else{ langCode.append(".UTF-8"); }
103  environ.insert("LANG",langCode); //Set the proper localized language
104  environ.insert("MAIL","/var/mail/"+xuser); //Set the mail variable
105  environ.insert("GROUP",xuser); //Set the proper group id
106  environ.insert("SHLVL","0"); //Set the proper shell level
107  this->setProcessEnvironment(environ);
108  this->setWorkingDirectory(xhome); //set the current directory to the user's home directory
109  //Log the DE startup outputs as well
110  this->setStandardOutputFile(xhome+"/.pcdm-startup.log",QIODevice::Truncate);
111  // Startup the process
112  this->start(cmd);
113  return TRUE;
114}
115
116void XProcess::slotCleanup(int exitCode, QProcess::ExitStatus status){
117  pam_shutdown(); //make sure that PAM shuts down properly     
118}
119
120/*
121 ========== PAM FUNCTIONS ==========
122*/
123static struct pam_conv pamc = { openpam_nullconv, NULL };
124
125bool XProcess::pam_checkPW(){
126 //Requires internal "xuser" and "xpwd" variables to be set
127       
128//Convert the inputs to C character arrays for use in PAM
129  QByteArray tmp = xuser.toUtf8();
130  char* cUser = tmp.data();
131  QByteArray tmp2 = xpwd.toUtf8();
132  char* cPassword = tmp2.data();
133  //initialize variables
134  bool result = FALSE;
135  int ret;
136  //Initialize PAM
137  ret = pam_start("login", cUser, &pamc, &pamh);
138  if( ret == PAM_SUCCESS ){
139    pam_started = TRUE; //flag that pam is started
140    //Place the user-supplied password into the structure
141    ret = pam_set_item(pamh, PAM_AUTHTOK, cPassword);
142    //Set the TTY
143    //ret = pam_set_item(pamh, PAM_TTY, "pcdm-terminal");
144    //Authenticate with PAM
145    ret = pam_authenticate(pamh,0);
146    if( ret == PAM_SUCCESS ){
147      //Check for valid, unexpired account and verify access restrictions
148      ret = pam_acct_mgmt(pamh,0);
149      if( ret == PAM_SUCCESS ){ result = TRUE; }
150   
151    }else{
152      pam_logFailure(ret);
153    }
154  }
155  //return verification result
156  return result;       
157}
158
159bool XProcess::pam_startSession(){
160  //This should only be run if pam_checkPW was successful
161  int ret = pam_open_session(pamh,0);
162  bool ok = FALSE;
163  if(ret == PAM_SUCCESS){ ok = TRUE; }
164  else{ pam_logFailure(ret); }
165 
166  return ok;
167}
168
169bool XProcess::pam_stopSession(){
170  //This should only be run if pam_startSession was successful
171  int ret = pam_close_session(pamh,0);
172  bool ok = FALSE;
173  if(ret == PAM_SUCCESS){ ok = TRUE; }
174  else{ pam_logFailure(ret); }
175 
176  return ok;
177}
178
179void XProcess::pam_logFailure(int ret){
180  //Interpret a PAM error message and log it
181  Backend::log("PAM Error: " + QString::number(ret));
182  switch( ret ){
183  case PAM_ABORT:
184    Backend::log(" - PAM abort error");
185    break;
186  case PAM_AUTHINFO_UNAVAIL:
187    Backend::log(" - Authentication info unavailable");
188    break;
189  case PAM_AUTH_ERR:
190    Backend::log(" - Authentication error");
191    break;
192  case PAM_BUF_ERR:
193    Backend::log(" - Buffer error");
194    break;
195  case PAM_CONV_ERR:
196    Backend::log(" - Conversion error");
197    break;
198  case PAM_CRED_INSUFFICIENT:
199    Backend::log(" - Credentials insufficient");
200    break;
201  case PAM_MAXTRIES:
202    Backend::log(" - Maximum number of tries exceeded");
203    break;
204  case PAM_PERM_DENIED:
205    Backend::log(" - Permission denied");
206    break;
207  case PAM_SERVICE_ERR:
208    Backend::log(" - Service error");
209    break;
210  case PAM_SYMBOL_ERR:
211    Backend::log(" - Symbol error");
212    break;
213  case PAM_SYSTEM_ERR:
214    Backend::log(" - System error");
215    break;
216  case PAM_USER_UNKNOWN:
217    Backend::log(" - Unknown user");
218    break;
219  default:
220    Backend::log(" - Unrecognized authentication error");
221  }
222       
223}
224
225void XProcess::pam_shutdown(){
226  if(pam_session_open){
227    pam_stopSession();
228    pam_session_open = FALSE;
229  }
230  if(pam_started){
231    pam_end(pamh,0);
232    pam_started = FALSE;
233  }
234}
Note: See TracBrowser for help on using the repository browser.