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

tdesu

  • tdesu
client.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  * This is free software; you can use this library under the GNU Library
9  * General Public License, version 2. See the file "COPYING.LIB" for the
10  * exact licensing terms.
11  *
12  * client.cpp: A client for tdesud.
13  */
14 
15 #include <config.h>
16 #include <stdio.h>
17 #include <unistd.h>
18 #include <stdlib.h>
19 #include <pwd.h>
20 #include <errno.h>
21 #include <string.h>
22 
23 #include <sys/types.h>
24 #include <sys/socket.h>
25 #include <sys/un.h>
26 #include <sys/stat.h>
27 
28 #include <tqglobal.h>
29 #include <tqcstring.h>
30 #include <tqfile.h>
31 #include <tqregexp.h>
32 
33 #include <kdebug.h>
34 #include <kstandarddirs.h>
35 #include <tdeapplication.h>
36 #include <kde_file.h>
37 
38 #include "client.h"
39 
40 class TDEsuClient::TDEsuClientPrivate {
41 public:
42  TQString daemon;
43 };
44 
45 #ifndef SUN_LEN
46 #define SUN_LEN(ptr) ((socklen_t) (((struct sockaddr_un *) 0)->sun_path) \
47  + strlen ((ptr)->sun_path))
48 #endif
49 
50 TDEsuClient::TDEsuClient()
51 {
52  sockfd = -1;
53 #ifdef Q_WS_X11
54  TQCString display(getenv("DISPLAY"));
55  if (display.isEmpty())
56  {
57  kdWarning(900) << k_lineinfo << "$DISPLAY is not set\n";
58  return;
59  }
60 
61  // strip the screen number from the display
62  display.replace(TQRegExp("\\.[0-9]+$"), "");
63 #else
64  TQCString display("QWS");
65 #endif
66 
67  sock = TQFile::encodeName(locateLocal("socket", TQString("tdesud_%1").arg(display.data())));
68  d = new TDEsuClientPrivate;
69  connect();
70 }
71 
72 
73 TDEsuClient::~TDEsuClient()
74 {
75  delete d;
76  if (sockfd >= 0)
77  close(sockfd);
78 }
79 
80 int TDEsuClient::connect()
81 {
82  if (sockfd >= 0)
83  close(sockfd);
84  if (access(sock, R_OK|W_OK))
85  {
86  sockfd = -1;
87  return -1;
88  }
89 
90  sockfd = socket(PF_UNIX, SOCK_STREAM, 0);
91  if (sockfd < 0)
92  {
93  kdWarning(900) << k_lineinfo << "socket(): " << perror << "\n";
94  return -1;
95  }
96  struct sockaddr_un addr;
97  addr.sun_family = AF_UNIX;
98  strcpy(addr.sun_path, sock);
99 
100  if (::connect(sockfd, (struct sockaddr *) &addr, SUN_LEN(&addr)) < 0)
101  {
102  kdWarning(900) << k_lineinfo << "connect():" << perror << endl;
103  close(sockfd); sockfd = -1;
104  return -1;
105  }
106 
107 #if !defined(SO_PEERCRED) || !defined(HAVE_STRUCT_UCRED)
108 # if defined(HAVE_GETPEEREID)
109  uid_t euid;
110  gid_t egid;
111  // Security: if socket exists, we must own it
112  if (getpeereid(sockfd, &euid, &egid) == 0)
113  {
114  if (euid != getuid())
115  {
116  kdWarning(900) << "socket not owned by me! socket uid = " << euid << endl;
117  close(sockfd); sockfd = -1;
118  return -1;
119  }
120  }
121 # else
122 # ifdef __GNUC__
123 # warning "Using sloppy security checks"
124 # endif
125  // We check the owner of the socket after we have connected.
126  // If the socket was somehow not ours an attacker will be able
127  // to delete it after we connect but shouldn't be able to
128  // create a socket that is owned by us.
129  KDE_struct_stat s;
130  if (KDE_lstat(sock, &s)!=0)
131  {
132  kdWarning(900) << "stat failed (" << sock << ")" << endl;
133  close(sockfd); sockfd = -1;
134  return -1;
135  }
136  if (s.st_uid != getuid())
137  {
138  kdWarning(900) << "socket not owned by me! socket uid = " << s.st_uid << endl;
139  close(sockfd); sockfd = -1;
140  return -1;
141  }
142  if (!S_ISSOCK(s.st_mode))
143  {
144  kdWarning(900) << "socket is not a socket (" << sock << ")" << endl;
145  close(sockfd); sockfd = -1;
146  return -1;
147  }
148 # endif
149 #else
150  struct ucred cred;
151  socklen_t siz = sizeof(cred);
152 
153  // Security: if socket exists, we must own it
154  if (getsockopt(sockfd, SOL_SOCKET, SO_PEERCRED, &cred, &siz) == 0)
155  {
156  if (cred.uid != getuid())
157  {
158  kdWarning(900) << "socket not owned by me! socket uid = " << cred.uid << endl;
159  close(sockfd); sockfd = -1;
160  return -1;
161  }
162  }
163 #endif
164 
165  return 0;
166 }
167 
168 TQCString TDEsuClient::escape(const TQCString &str)
169 {
170  TQCString copy = str;
171  int n = 0;
172  while ((n = copy.find("\\", n)) != -1)
173  {
174  copy.insert(n, '\\');
175  n += 2;
176  }
177  n = 0;
178  while ((n = copy.find("\"", n)) != -1)
179  {
180  copy.insert(n, '\\');
181  n += 2;
182  }
183  copy.prepend("\"");
184  copy.append("\"");
185  return copy;
186 }
187 
188 int TDEsuClient::command(const TQCString &cmd, TQCString *result)
189 {
190  if (sockfd < 0)
191  return -1;
192 
193  if (send(sockfd, cmd, cmd.length(), 0) != (int) cmd.length())
194  return -1;
195 
196  char buf[1024];
197  int nbytes = recv(sockfd, buf, 1023, 0);
198  if (nbytes <= 0)
199  {
200  kdWarning(900) << k_lineinfo << "no reply from daemon\n";
201  return -1;
202  }
203  buf[nbytes] = '\000';
204 
205  TQCString reply = buf;
206  if (reply.left(2) != "OK")
207  return -1;
208 
209  if (result)
210  *result = reply.mid(3, reply.length()-4);
211  return 0;
212 }
213 
214 int TDEsuClient::setPass(const char *pass, int timeout)
215 {
216  TQCString cmd = "PASS ";
217  cmd += escape(pass);
218  cmd += " ";
219  cmd += TQCString().setNum(timeout);
220  cmd += "\n";
221  return command(cmd);
222 }
223 
224 int TDEsuClient::exec(const TQCString &prog, const TQCString &user, const TQCString &options, const QCStringList &env)
225 {
226  TQCString cmd;
227  cmd = "EXEC ";
228  cmd += escape(prog);
229  cmd += " ";
230  cmd += escape(user);
231  if (!options.isEmpty() || !env.isEmpty())
232  {
233  cmd += " ";
234  cmd += escape(options);
235  for(QCStringList::ConstIterator it = env.begin();
236  it != env.end(); ++it)
237  {
238  cmd += " ";
239  cmd += escape(*it);
240  }
241  }
242  cmd += "\n";
243  return command(cmd);
244 }
245 
246 int TDEsuClient::setHost(const TQCString &host)
247 {
248  TQCString cmd = "HOST ";
249  cmd += escape(host);
250  cmd += "\n";
251  return command(cmd);
252 }
253 
254 int TDEsuClient::setPriority(int prio)
255 {
256  TQCString cmd;
257  cmd.sprintf("PRIO %d\n", prio);
258  return command(cmd);
259 }
260 
261 int TDEsuClient::setScheduler(int sched)
262 {
263  TQCString cmd;
264  cmd.sprintf("SCHD %d\n", sched);
265  return command(cmd);
266 }
267 
268 int TDEsuClient::delCommand(const TQCString &key, const TQCString &user)
269 {
270  TQCString cmd = "DEL ";
271  cmd += escape(key);
272  cmd += " ";
273  cmd += escape(user);
274  cmd += "\n";
275  return command(cmd);
276 }
277 int TDEsuClient::setVar(const TQCString &key, const TQCString &value, int timeout,
278  const TQCString &group)
279 {
280  TQCString cmd = "SET ";
281  cmd += escape(key);
282  cmd += " ";
283  cmd += escape(value);
284  cmd += " ";
285  cmd += escape(group);
286  cmd += " ";
287  cmd += TQCString().setNum(timeout);
288  cmd += "\n";
289  return command(cmd);
290 }
291 
292 TQCString TDEsuClient::getVar(const TQCString &key)
293 {
294  TQCString cmd = "GET ";
295  cmd += escape(key);
296  cmd += "\n";
297  TQCString reply;
298  command(cmd, &reply);
299  return reply;
300 }
301 
302 TQValueList<TQCString> TDEsuClient::getKeys(const TQCString &group)
303 {
304  TQCString cmd = "GETK ";
305  cmd += escape(group);
306  cmd += "\n";
307  TQCString reply;
308  command(cmd, &reply);
309  int index=0, pos;
310  TQValueList<TQCString> list;
311  if( !reply.isEmpty() )
312  {
313  // kdDebug(900) << "Found a matching entry: " << reply << endl;
314  while (1)
315  {
316  pos = reply.find( '\007', index );
317  if( pos == -1 )
318  {
319  if( index == 0 )
320  list.append( reply );
321  else
322  list.append( reply.mid(index) );
323  break;
324  }
325  else
326  {
327  list.append( reply.mid(index, pos-index) );
328  }
329  index = pos+1;
330  }
331  }
332  return list;
333 }
334 
335 bool TDEsuClient::findGroup(const TQCString &group)
336 {
337  TQCString cmd = "CHKG ";
338  cmd += escape(group);
339  cmd += "\n";
340  if( command(cmd) == -1 )
341  return false;
342  return true;
343 }
344 
345 int TDEsuClient::delVar(const TQCString &key)
346 {
347  TQCString cmd = "DELV ";
348  cmd += escape(key);
349  cmd += "\n";
350  return command(cmd);
351 }
352 
353 int TDEsuClient::delGroup(const TQCString &group)
354 {
355  TQCString cmd = "DELG ";
356  cmd += escape(group);
357  cmd += "\n";
358  return command(cmd);
359 }
360 
361 int TDEsuClient::delVars(const TQCString &special_key)
362 {
363  TQCString cmd = "DELS ";
364  cmd += escape(special_key);
365  cmd += "\n";
366  return command(cmd);
367 }
368 
369 int TDEsuClient::ping()
370 {
371  return command("PING\n");
372 }
373 
374 int TDEsuClient::exitCode()
375 {
376  TQCString result;
377  if (command("EXIT\n", &result) != 0)
378  return -1;
379 
380  return result.toLong();
381 }
382 
383 int TDEsuClient::stopServer()
384 {
385  return command("STOP\n");
386 }
387 
388 static TQString findDaemon()
389 {
390  TQString daemon = locate("bin", "tdesud");
391  if (daemon.isEmpty()) // if not in TDEDIRS, rely on PATH
392  daemon = TDEStandardDirs::findExe("tdesud");
393 
394  if (daemon.isEmpty())
395  {
396  kdWarning(900) << k_lineinfo << "daemon not found\n";
397  }
398  return daemon;
399 }
400 
401 bool TDEsuClient::isServerSGID()
402 {
403  if (d->daemon.isEmpty())
404  d->daemon = findDaemon();
405  if (d->daemon.isEmpty())
406  return false;
407 
408  KDE_struct_stat sbuf;
409  if (KDE_stat(TQFile::encodeName(d->daemon), &sbuf) < 0)
410  {
411  kdWarning(900) << k_lineinfo << "stat(): " << perror << "\n";
412  return false;
413  }
414  return (sbuf.st_mode & S_ISGID);
415 }
416 
417 int TDEsuClient::startServer()
418 {
419  if (d->daemon.isEmpty())
420  d->daemon = findDaemon();
421  if (d->daemon.isEmpty())
422  return -1;
423 
424  if (!isServerSGID()) {
425  kdWarning(900) << k_lineinfo << "tdesud not setgid!\n";
426  }
427 
428  // tdesud only forks to the background after it is accepting
429  // connections.
430  // We start it via tdeinit to make sure that it doesn't inherit
431  // any fd's from the parent process.
432  int ret = kapp->tdeinitExecWait(d->daemon);
433  connect();
434  return ret;
435 }
TDEsuClient::setPriority
int setPriority(int priority)
Set the desired priority (optional), see StubProcess.
Definition: client.cpp:254
TDEsuClient::setScheduler
int setScheduler(int scheduler)
Set the desired scheduler (optional), see StubProcess.
Definition: client.cpp:261
TDEsuClient::isServerSGID
bool isServerSGID()
Returns true if the server is safe (installed setgid), false otherwise.
Definition: client.cpp:401
TDEsuClient::getKeys
TQValueList< TQCString > getKeys(const TQCString &group)
Gets all the keys that are membes of the given group.
Definition: client.cpp:302
TDEsuClient::delGroup
int delGroup(const TQCString &group)
Delete all persistent variables in a group.
Definition: client.cpp:353
TDEsuClient::delCommand
int delCommand(const TQCString &command, const TQCString &user)
Remove a password for a user/command.
Definition: client.cpp:268
TDEsuClient::startServer
int startServer()
Try to start up tdesud.
Definition: client.cpp:417
TDEsuClient::setHost
int setHost(const TQCString &host)
Set the target host (optional).
Definition: client.cpp:246
TDEsuClient::setVar
int setVar(const TQCString &key, const TQCString &value, int timeout=0, const TQCString &group=0)
Set a persistent variable.
Definition: client.cpp:277
TDEsuClient::delVars
int delVars(const TQCString &special_key)
Delete all persistent variables with the given key.
Definition: client.cpp:361
TDEsuClient::stopServer
int stopServer()
Stop the daemon.
Definition: client.cpp:383
TDEsuClient::exec
int exec(const TQCString &command, const TQCString &user, const TQCString &options=0, const QCStringList &env=QCStringList())
Lets tdesud execute a command.
Definition: client.cpp:224
TDEsuClient::findGroup
bool findGroup(const TQCString &group)
Returns true if the specified group exists is cached.
Definition: client.cpp:335
TDEsuClient::getVar
TQCString getVar(const TQCString &key)
Get a persistent variable.
Definition: client.cpp:292
TDEsuClient::setPass
int setPass(const char *pass, int timeout)
Set root's password, lasts one session.
Definition: client.cpp:214
TDEsuClient::ping
int ping()
Ping tdesud.
Definition: client.cpp:369
TDEsuClient::delVar
int delVar(const TQCString &key)
Delete a persistent variable.
Definition: client.cpp:345
TDEsuClient::exitCode
int exitCode()
Wait for the last command to exit and return the exit code.
Definition: client.cpp:374

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
  •     tdecore
  • tdeabc
  • tdecmshell
  • tdecore
  • tdefx
  • tdehtml
  • tdeinit
  • tdeio
  •   bookmarks
  •   httpfilter
  •   kpasswdserver
  •   kssl
  • tdeioslave
  •   http
  •   tdefile
  •   tdeio
  •   tdeioexec
  • tdemdi
  •   tdemdi
  • tdenewstuff
  • tdeparts
  • tdeprint
  • tderandr
  • tderesources
  • tdespell2
  • tdesu
  • tdeui
  • tdeunittest
  • tdeutils
  • tdewallet
Generated for tdesu by doxygen 1.8.8
This website is maintained by Timothy Pearson.