KDEsu
su.cpp
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include <config.h>
00019
00020 #include <stdio.h>
00021 #include <stdlib.h>
00022 #include <unistd.h>
00023 #include <fcntl.h>
00024 #include <errno.h>
00025 #include <string.h>
00026 #include <ctype.h>
00027 #include <signal.h>
00028
00029 #include <sys/types.h>
00030 #include <sys/stat.h>
00031
00032 #include <qglobal.h>
00033 #include <qcstring.h>
00034 #include <qfile.h>
00035
00036 #include <kconfig.h>
00037 #include <kdebug.h>
00038 #include <klocale.h>
00039 #include <kstandarddirs.h>
00040
00041 #include "su.h"
00042 #include "kcookie.h"
00043
00044
00045 #ifndef __PATH_SU
00046 #define __PATH_SU "false"
00047 #endif
00048
00049 #ifndef __PATH_SUDO
00050 #define __PATH_SUDO "false"
00051 #endif
00052
00053 SuProcess::SuProcess(const QCString &user, const QCString &command)
00054 {
00055 m_User = user;
00056 m_Command = command;
00057
00058 KConfig* config = KGlobal::config();
00059 config->setGroup("super-user-command");
00060 superUserCommand = config->readEntry("super-user-command", DEFAULT_SUPER_USER_COMMAND);
00061 if ( superUserCommand != "sudo" && superUserCommand != "su" ) {
00062 kdWarning() << "unknown super user command" << endl;
00063 superUserCommand = "su";
00064 }
00065 }
00066
00067
00068 SuProcess::~SuProcess()
00069 {
00070 }
00071
00072 int SuProcess::checkInstall(const char *password)
00073 {
00074 return exec(password, Install);
00075 }
00076
00077 int SuProcess::checkNeedPassword()
00078 {
00079 return exec(0L, NeedPassword);
00080 }
00081
00082
00083
00084
00085
00086 int SuProcess::exec(const char *password, int check)
00087 {
00088 if (check)
00089 setTerminal(true);
00090
00091
00092
00093 if (m_User != "root") {
00094 superUserCommand = "su";
00095 }
00096
00097 QCStringList args;
00098 if (superUserCommand == "sudo") {
00099 args += "-u";
00100 }
00101
00102 #ifdef Q_OS_DARWIN
00103 args += "-c";
00104 args += "staff";
00105 #endif
00106
00107 if ((m_Scheduler != SchedNormal) || (m_Priority > 50))
00108 args += "root";
00109 else
00110 args += m_User;
00111
00112 if (superUserCommand == "su") {
00113 args += "-c";
00114 }
00115 args += QCString(__KDE_BINDIR) + "/kdesu_stub";
00116 #ifndef Q_OS_DARWIN
00117 args += "-";
00118 #endif
00119
00122 QCString command;
00123 if (superUserCommand == "sudo") {
00124 command = __PATH_SUDO;
00125 } else {
00126 command = __PATH_SU;
00127 }
00128
00129 if (::access(command, X_OK) != 0)
00130 {
00132 command = QFile::encodeName( KGlobal::dirs()->findExe(superUserCommand.ascii()) );
00133 if (command.isEmpty())
00134 return check ? SuNotFound : -1;
00135 }
00136
00137
00138 if (StubProcess::exec(command, args) < 0)
00139 {
00140 return check ? SuNotFound : -1;
00141 }
00142
00143
00144 SuErrors ret = (SuErrors) ConverseSU(password);
00145
00146
00147 if (ret == error)
00148 {
00149 if (!check)
00150 kdError(900) << k_lineinfo << "Conversation with " << superUserCommand << " failed\n";
00151 return ret;
00152 }
00153 if (check == NeedPassword)
00154 {
00155 if (ret == killme)
00156 {
00161 if ( superUserCommand == "sudo" ) {
00162
00163 return ret;
00164 }
00165 if (kill(m_Pid, SIGKILL) < 0) {
00166 kdDebug() << k_funcinfo << "kill < 0" << endl;
00167
00168
00169 ret=error;
00170 }
00171 else
00172 {
00173 int iret = waitForChild();
00174 if (iret < 0) ret=error;
00175 else {} ;
00176 }
00177 }
00178 return ret;
00179 }
00180
00181 if (m_bErase && password)
00182 {
00183 char *ptr = const_cast<char *>(password);
00184 const uint plen = strlen(password);
00185 for (unsigned i=0; i < plen; i++)
00186 ptr[i] = '\000';
00187 }
00188
00189 if (ret == notauthorized)
00190 {
00191 kill(m_Pid, SIGKILL);
00192 if (superUserCommand != "sudo") {
00193 waitForChild();
00194 }
00195 return SuIncorrectPassword;
00196 }
00197
00198 int iret = ConverseStub(check);
00199 if (iret < 0)
00200 {
00201 if (!check)
00202 kdError(900) << k_lineinfo << "Converstation with kdesu_stub failed\n";
00203 return iret;
00204 }
00205 else if (iret == 1)
00206 {
00207 kill(m_Pid, SIGKILL);
00208 waitForChild();
00209 return SuIncorrectPassword;
00210 }
00211
00212 if (check == Install)
00213 {
00214 waitForChild();
00215 return 0;
00216 }
00217
00218 iret = waitForChild();
00219 return iret;
00220 }
00221
00222
00223
00224
00225
00226
00227 int SuProcess::ConverseSU(const char *password)
00228 {
00229 enum { WaitForPrompt, CheckStar, HandleStub } state = WaitForPrompt;
00230 int colon;
00231 unsigned i, j;
00232
00233
00234 QCString line;
00235 while (true)
00236 {
00237 line = readLine();
00238 if (line.isNull())
00239 return ( state == HandleStub ? notauthorized : error);
00240 kdDebug(900) << k_lineinfo << "Read line <" << line << ">" << endl;
00241
00242 switch (state)
00243 {
00245 case WaitForPrompt:
00246 {
00247
00248 if (line == "kdesu_stub")
00249 {
00250 unreadLine(line);
00251 return ok;
00252 }
00253
00254 while(waitMS(m_Fd,100)>0)
00255 {
00256
00257
00258
00259
00260 QCString more = readLine();
00261 if (more.isEmpty())
00262 break;
00263
00264 line = more;
00265 kdDebug(900) << k_lineinfo << "Read line <" << more << ">" << endl;
00266 }
00267
00268
00269 const uint len = line.length();
00270 for (i=0,j=0,colon=0; i<len; i++)
00271 {
00272 if (line[i] == ':')
00273 {
00274 j = i; colon++;
00275 continue;
00276 }
00277 if (!isspace(line[i]))
00278 j++;
00279 }
00280 if ((colon == 1) && (line[j] == ':'))
00281 {
00282 if (password == 0L)
00283 return killme;
00284 if (!checkPid(m_Pid))
00285 {
00286 kdError(900) << superUserCommand << " has exited while waiting for pwd." << endl;
00287 return error;
00288 }
00289 if ((WaitSlave() == 0) && checkPid(m_Pid))
00290 {
00291 write(m_Fd, password, strlen(password));
00292 write(m_Fd, "\n", 1);
00293 state=CheckStar;
00294 }
00295 else
00296 {
00297 return error;
00298 }
00299 }
00300 break;
00301 }
00303 case CheckStar:
00304 {
00305 QCString s = line.stripWhiteSpace();
00306 if (s.isEmpty())
00307 {
00308 state=HandleStub;
00309 break;
00310 }
00311 const uint len = line.length();
00312 for (i=0; i< len; i++)
00313 {
00314 if (s[i] != '*')
00315 return error;
00316 }
00317 state=HandleStub;
00318 break;
00319 }
00321 case HandleStub:
00322
00323 if (line == "kdesu_stub")
00324 {
00325 unreadLine(line);
00326 return ok;
00327 } else if (superUserCommand == "sudo") {
00328
00329
00330 return notauthorized;
00331 }
00332 break;
00334 }
00335 }
00336 return ok;
00337 }
00338
00339 void SuProcess::virtual_hook( int id, void* data )
00340 { StubProcess::virtual_hook( id, data ); }
00341
00342