• Skip to content
  • Skip to link menu
Trinity API Reference
  • Trinity API Reference
  • tdesu
 

tdesu

  • tdesu
su.cpp
1/*
2*
3* $Id$
4*
5* This file is part of the KDE project, module tdesu.
6* Copyright (C) 1999,2000 Geert Jansen <jansen@kde.org>
7*
8* Sudo support added by Jonathan Riddell <jriddell@ ubuntu.com>
9* Copyright (C) 2005 Canonical Ltd
10*
11* This is free software; you can use this library under the GNU Library
12* General Public License, version 2. See the file "COPYING.LIB" for the
13* exact licensing terms.
14*
15* su.cpp: Execute a program as another user with "class SuProcess".
16*/
17
18#include <config.h>
19
20#include <stdio.h>
21#include <stdlib.h>
22#include <unistd.h>
23#include <fcntl.h>
24#include <errno.h>
25#include <string.h>
26#include <ctype.h>
27#include <signal.h>
28
29#include <sys/types.h>
30#include <sys/stat.h>
31
32#include <tqglobal.h>
33#include <tqcstring.h>
34#include <tqfile.h>
35
36#include <tdeconfig.h>
37#include <kdebug.h>
38#include <tdelocale.h>
39#include <tdestandarddirs.h>
40
41#include "su.h"
42#include "kcookie.h"
43
44
45#ifndef __PATH_SU
46#define __PATH_SU "false"
47#endif
48
49#ifndef __PATH_SUDO
50#define __PATH_SUDO "false"
51#endif
52
53SuProcess::SuProcess(const TQCString &user, const TQCString &command)
54{
55 m_User = user;
56 m_Command = command;
57
58 TDEConfig* config = TDEGlobal::config();
59 config->setGroup("super-user-command");
60 superUserCommand = config->readEntry("super-user-command", DEFAULT_SUPER_USER_COMMAND);
61 if ( superUserCommand != "sudo" && superUserCommand != "su" ) {
62 kdWarning() << "unknown super user command" << endl;
63 superUserCommand = "su";
64 }
65}
66
67
68SuProcess::~SuProcess()
69{
70}
71
72int SuProcess::checkInstall(const char *password)
73{
74 return exec(password, Install);
75}
76
77int SuProcess::checkNeedPassword()
78{
79 return exec(0L, NeedPassword);
80}
81
82/*
83* Execute a command with su(1).
84*/
85
86int SuProcess::exec(const char *password, int check)
87{
88 if (check)
89 setTerminal(true);
90
91 // since user may change after constructor (due to setUser())
92 // we need to override sudo with su for non-root here
93 if (m_User != "root") {
94 superUserCommand = "su";
95 }
96
97 QCStringList args;
98 if (superUserCommand == "sudo") {
99 args += "-u";
100 }
101
102#ifdef Q_OS_DARWIN
103 args += "-c";
104 args += "staff";
105#endif
106
107 if ((m_Scheduler != SchedNormal) || (m_Priority > 50))
108 args += "root";
109 else
110 args += m_User;
111
112 if (superUserCommand == "su") {
113 args += "-c";
114 }
115 args += TQCString(__TDE_BINDIR) + "/tdesu_stub";
116#ifndef Q_OS_DARWIN
117 args += "-";
118#endif
119
122 TQCString command;
123 if (superUserCommand == "sudo") {
124 command = __PATH_SUDO;
125 } else {
126 command = __PATH_SU;
127 }
128
129 if (::access(command, X_OK) != 0)
130 {
132 command = TQFile::encodeName( TDEGlobal::dirs()->findExe(superUserCommand.ascii()) );
133 if (command.isEmpty())
134 return check ? SuNotFound : -1;
135 }
136
137 // kdDebug(900) << k_lineinfo << "Call StubProcess::exec()" << endl;
138 if (StubProcess::exec(command, args) < 0)
139 {
140 return check ? SuNotFound : -1;
141 }
142 // kdDebug(900) << k_lineinfo << "Done StubProcess::exec()" << endl;
143
144 SuErrors ret = (SuErrors) ConverseSU(password);
145 // kdDebug(900) << k_lineinfo << "Conversation returned " << ret << endl;
146
147 if (ret == error)
148 {
149 if (!check)
150 kdError(900) << k_lineinfo << "Conversation with " << superUserCommand << " failed\n";
151 return ret;
152 }
153 if (check == NeedPassword)
154 {
155 if (ret == killme)
156 {
161 if ( superUserCommand == "sudo" ) {
162 // sudo can not be killed, just return
163 return ret;
164 }
165 if (kill(m_Pid, SIGKILL) < 0) {
166 kdDebug() << k_funcinfo << "kill < 0" << endl;
167 //FIXME SIGKILL doesn't work for sudo,
168 //why is this different from su?
169 ret=error;
170 }
171 else
172 {
173 int iret = waitForChild();
174 if (iret < 0) ret=error;
175 else /* nothing */ {} ;
176 }
177 }
178 return ret;
179 }
180
181 if (m_bErase && password)
182 {
183 char *ptr = const_cast<char *>(password);
184 const uint plen = strlen(password);
185 for (unsigned i=0; i < plen; i++)
186 ptr[i] = '\000';
187 }
188
189 if (ret == notauthorized)
190 {
191 kill(m_Pid, SIGKILL);
192 if (superUserCommand != "sudo") {
193 waitForChild();
194 }
195 return SuIncorrectPassword;
196 }
197
198 int iret = ConverseStub(check);
199 if (iret < 0)
200 {
201 if (!check)
202 kdError(900) << k_lineinfo << "Converstation with tdesu_stub failed\n";
203 return iret;
204 }
205 else if (iret == 1)
206 {
207 kill(m_Pid, SIGKILL);
208 waitForChild();
209 return SuIncorrectPassword;
210 }
211
212 if (check == Install)
213 {
214 waitForChild();
215 return 0;
216 }
217
218 iret = waitForChild();
219 return iret;
220}
221
222/*
223* Conversation with su: feed the password.
224* Return values: -1 = error, 0 = ok, 1 = kill me, 2 not authorized
225*/
226
227int SuProcess::ConverseSU(const char *password)
228{
229 enum { WaitForPrompt, CheckStar, HandleStub } state = WaitForPrompt;
230 int colon;
231 unsigned i, j;
232 // kdDebug(900) << k_lineinfo << "ConverseSU starting." << endl;
233
234 TQCString line;
235 while (true)
236 {
237 line = readLine();
238 if (line.isNull())
239 return ( state == HandleStub ? notauthorized : error);
240 kdDebug(900) << k_lineinfo << "Read line <" << line << ">" << endl;
241
242 switch (state)
243 {
245 case WaitForPrompt:
246 {
247 // In case no password is needed.
248 if (line == "tdesu_stub")
249 {
250 unreadLine(line);
251 return ok;
252 }
253
254 while(waitMS(m_Fd,100)>0)
255 {
256 // There is more output available, so the previous line
257 // couldn't have been a password prompt (the definition
258 // of prompt being that there's a line of output followed
259 // by a colon, and then the process waits).
260 TQCString more = readLine();
261 if (more.isEmpty())
262 break;
263
264 line = more;
265 kdDebug(900) << k_lineinfo << "Read line <" << more << ">" << endl;
266 }
267
268 // Match "Password: " with the regex ^[^:]+:[\w]*$.
269 const uint len = line.length();
270 for (i=0,j=0,colon=0; i<len; i++)
271 {
272 if (line[i] == ':')
273 {
274 j = i; colon++;
275 continue;
276 }
277 if (!isspace(line[i]))
278 j++;
279 }
280 if ((colon == 1) && (line[j] == ':'))
281 {
282 if (password == 0L)
283 return killme;
284 if (!checkPid(m_Pid))
285 {
286 kdError(900) << superUserCommand << " has exited while waiting for pwd." << endl;
287 return error;
288 }
289 if ((WaitSlave() == 0) && checkPid(m_Pid))
290 {
291 write(m_Fd, password, strlen(password));
292 write(m_Fd, "\n", 1);
293 state=CheckStar;
294 }
295 else
296 {
297 return error;
298 }
299 }
300 break;
301 }
303 case CheckStar:
304 {
305 TQCString s = line.stripWhiteSpace();
306 if (s.isEmpty())
307 {
308 state=HandleStub;
309 break;
310 }
311 const uint len = line.length();
312 for (i=0; i< len; i++)
313 {
314 if (s[i] != '*')
315 return error;
316 }
317 state=HandleStub;
318 break;
319 }
321 case HandleStub:
322 // Read till we get "tdesu_stub"
323 if (line == "tdesu_stub")
324 {
325 unreadLine(line);
326 return ok;
327 } else if (superUserCommand == "sudo") {
328 // sudo gives a "sorry" line so reaches here
329 // with the wrong password
330 return notauthorized;
331 }
332 break;
334 } // end switch
335 } // end while (true)
336 return ok;
337}
338
339void SuProcess::virtual_hook( int id, void* data )
340{ StubProcess::virtual_hook( id, data ); }
341
342
PtyProcess::waitMS
static int waitMS(int fd, int ms)
Wait ms miliseconds (ie.
Definition: process.cpp:59
PtyProcess::setTerminal
void setTerminal(bool terminal)
Enables/disables terminal output.
Definition: process.h:105
PtyProcess::waitForChild
int waitForChild()
Waits for the child to exit.
Definition: process.cpp:487
PtyProcess::checkPid
static bool checkPid(pid_t pid)
Basic check for the existence of pid.
Definition: process.cpp:75
PtyProcess::readLine
TQCString readLine(bool block=true)
Reads a line from the program's standard out.
Definition: process.cpp:175
PtyProcess::WaitSlave
int WaitSlave()
Waits until the pty has cleared the ECHO flag.
Definition: process.cpp:413
PtyProcess::exec
int exec(const TQCString &command, const QCStringList &args)
Forks off and execute a command.
Definition: process.cpp:324
PtyProcess::unreadLine
void unreadLine(const TQCString &line, bool addNewline=true)
Puts back a line of input.
Definition: process.cpp:311
StubProcess::ConverseStub
int ConverseStub(int check)
Exchange all parameters with tdesu_stub.
Definition: stub.cpp:80
SuProcess::checkNeedPassword
int checkNeedPassword()
Checks if a password is needed.
Definition: su.cpp:77
SuProcess::checkInstall
int checkInstall(const char *password)
Checks if the stub is installed and the password is correct.
Definition: su.cpp:72
SuProcess::exec
int exec(const char *password, int check=NoCheck)
Definition: su.cpp:86

tdesu

Skip menu "tdesu"
  • Main Page
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Class Members
  • Related Pages

tdesu

Skip menu "tdesu"
  • arts
  • dcop
  • dnssd
  • interfaces
  •   kspeech
  •     interface
  •     library
  •   tdetexteditor
  • kate
  • kded
  • kdoctools
  • kimgio
  • kjs
  • libtdemid
  • libtdescreensaver
  • tdeabc
  • tdecmshell
  • tdecore
  • tdefx
  • tdehtml
  • tdeinit
  • tdeio
  •   bookmarks
  •   httpfilter
  •   kpasswdserver
  •   kssl
  •   tdefile
  •   tdeio
  •   tdeioexec
  • tdeioslave
  •   http
  • tdemdi
  •   tdemdi
  • tdenewstuff
  • tdeparts
  • tdeprint
  • tderandr
  • tderesources
  • tdespell2
  • tdesu
  • tdeui
  • tdeunittest
  • tdeutils
  • tdewallet
Generated for tdesu by doxygen 1.9.4
This website is maintained by Timothy Pearson.