su.cpp00001
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
00054 #define DEFAULT_SUPER_USER_COMMAND "sudo"
00055
00056 SuProcess::SuProcess(const QCString &user, const QCString &command)
00057 {
00058 m_User = user;
00059 m_Command = command;
00060
00061 KConfig* config = KGlobal::config();
00062 config->setGroup("super-user-command");
00063 superUserCommand = config->readEntry("super-user-command", DEFAULT_SUPER_USER_COMMAND);
00064 if ( superUserCommand != "sudo" && superUserCommand != "su" ) {
00065 kdWarning() << "unknown super user command" << endl;
00066 superUserCommand = "su";
00067 }
00068 }
00069
00070
00071 SuProcess::~SuProcess()
00072 {
00073 }
00074
00075 int SuProcess::checkInstall(const char *password)
00076 {
00077 return exec(password, Install);
00078 }
00079
00080 int SuProcess::checkNeedPassword()
00081 {
00082 return exec(0L, NeedPassword);
00083 }
00084
00085
00086
00087
00088
00089 int SuProcess::exec(const char *password, int check)
00090 {
00091 if (check)
00092 setTerminal(true);
00093
00094
00095
00096 if (m_User != "root") {
00097 superUserCommand = "su";
00098 }
00099
00100 QCStringList args;
00101 if (superUserCommand == "sudo") {
00102 args += "-u";
00103 }
00104
00105 if ((m_Scheduler != SchedNormal) || (m_Priority > 50))
00106 args += "root";
00107 else
00108 args += m_User;
00109
00110
00111 if (superUserCommand == "su") {
00112 args += "-c";
00113 }
00114 args += QCString(__KDE_BINDIR) + "/kdesu_stub";
00115 args += "-";
00116
00119 QCString command;
00120 if (superUserCommand == "sudo") {
00121 command = __PATH_SUDO;
00122 } else {
00123 command = __PATH_SU;
00124 }
00125
00126 if (::access(command, X_OK) != 0)
00127 {
00129 command = QFile::encodeName( KGlobal::dirs()->findExe(superUserCommand.ascii()) );
00130 if (command.isEmpty())
00131 return check ? SuNotFound : -1;
00132 }
00133
00134
00135 if (StubProcess::exec(command, args) < 0)
00136 {
00137 return check ? SuNotFound : -1;
00138 }
00139
00140
00141 SuErrors ret = (SuErrors) ConverseSU(password);
00142
00143
00144 if (ret == error)
00145 {
00146 if (!check)
00147 kdError(900) << k_lineinfo << "Conversation with su failed\n";
00148 return ret;
00149 }
00150 if (check == NeedPassword)
00151 {
00152 if (ret == killme)
00153 {
00158 if ( superUserCommand == "sudo" ) {
00159
00160 return ret;
00161 }
00162 if (kill(m_Pid, SIGKILL) < 0) {
00163 kdDebug() << k_funcinfo << "kill < 0" << endl;
00164
00165
00166 ret=error;
00167 }
00168 else
00169 {
00170 int iret = waitForChild();
00171 if (iret < 0) ret=error;
00172 else {} ;
00173 }
00174 }
00175 return ret;
00176 }
00177
00178 if (m_bErase && password)
00179 {
00180 char *ptr = const_cast<char *>(password);
00181 const uint plen = strlen(password);
00182 for (unsigned i=0; i < plen; i++)
00183 ptr[i] = '\000';
00184 }
00185
00186 if (ret == notauthorized)
00187 {
00188 kill(m_Pid, SIGKILL);
00189 if (superUserCommand != "sudo") {
00190 waitForChild();
00191 }
00192 return SuIncorrectPassword;
00193 }
00194
00195 int iret = ConverseStub(check);
00196 if (iret < 0)
00197 {
00198 if (!check)
00199 kdError(900) << k_lineinfo << "Converstation with kdesu_stub failed\n";
00200 return iret;
00201 }
00202 else if (iret == 1)
00203 {
00204 kill(m_Pid, SIGKILL);
00205 waitForChild();
00206 return SuIncorrectPassword;
00207 }
00208
00209 if (check == Install)
00210 {
00211 waitForChild();
00212 return 0;
00213 }
00214
00215 iret = waitForChild();
00216 return iret;
00217 }
00218
00219
00220
00221
00222
00223
00224 int SuProcess::ConverseSU(const char *password)
00225 {
00226 enum { WaitForPrompt, CheckStar, HandleStub } state = WaitForPrompt;
00227 int colon;
00228 unsigned i, j;
00229
00230
00231 QCString line;
00232 while (true)
00233 {
00234 line = readLine();
00235 if (line.isNull())
00236 return ( state == HandleStub ? notauthorized : error);
00237 kdDebug(900) << k_lineinfo << "Read line <" << line << ">" << endl;
00238
00239 switch (state)
00240 {
00242 case WaitForPrompt:
00243 {
00244
00245 if (line == "kdesu_stub")
00246 {
00247 unreadLine(line);
00248 return ok;
00249 }
00250
00251 while(waitMS(m_Fd,100)>0)
00252 {
00253
00254
00255
00256
00257 QCString more = readLine();
00258 if (more.isEmpty())
00259 break;
00260
00261 line = more;
00262 kdDebug(900) << k_lineinfo << "Read line <" << more << ">" << endl;
00263 }
00264
00265
00266 const uint len = line.length();
00267 for (i=0,j=0,colon=0; i<len; i++)
00268 {
00269 if (line[i] == ':')
00270 {
00271 j = i; colon++;
00272 continue;
00273 }
00274 if (!isspace(line[i]))
00275 j++;
00276 }
00277 if ((colon == 1) && (line[j] == ':'))
00278 {
00279 if (password == 0L)
00280 return killme;
00281 if (!checkPid(m_Pid))
00282 {
00283 kdError(900) << "su has exited while waiting for pwd." << endl;
00284 return error;
00285 }
00286 if ((WaitSlave() == 0) && checkPid(m_Pid))
00287 {
00288 write(m_Fd, password, strlen(password));
00289 write(m_Fd, "\n", 1);
00290 state=CheckStar;
00291 }
00292 else
00293 {
00294 return error;
00295 }
00296 }
00297 break;
00298 }
00300 case CheckStar:
00301 {
00302 QCString s = line.stripWhiteSpace();
00303 if (s.isEmpty())
00304 {
00305 state=HandleStub;
00306 break;
00307 }
00308 const uint len = line.length();
00309 for (i=0; i< len; i++)
00310 {
00311 if (s[i] != '*')
00312 return error;
00313 }
00314 state=HandleStub;
00315 break;
00316 }
00318 case HandleStub:
00319
00320 if (line == "kdesu_stub")
00321 {
00322 unreadLine(line);
00323 return ok;
00324 } else if (superUserCommand == "sudo") {
00325
00326
00327 return notauthorized;
00328 }
00329 break;
00331 }
00332 }
00333 return ok;
00334 }
00335
00336 void SuProcess::virtual_hook( int id, void* data )
00337 { StubProcess::virtual_hook( id, data ); }
00338
00339
|