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

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.1
This website is maintained by Timothy Pearson.