• 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 <tdestandarddirs.h>
38#include <tdeapplication.h>
39#include <kde_file.h>
40
41#include "client.h"
42
43class TDEsuClient::TDEsuClientPrivate {
44public:
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
53TDEsuClient::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
76TDEsuClient::~TDEsuClient()
77{
78 delete d;
79 if (sockfd >= 0)
80 close(sockfd);
81}
82
83int 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
186TQCString 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
206int 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
232int 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
242int 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
264int TDEsuClient::setHost(const TQCString &host)
265{
266 TQCString cmd = "HOST ";
267 cmd += escape(host);
268 cmd += "\n";
269 return command(cmd);
270}
271
272int TDEsuClient::setPriority(int prio)
273{
274 TQCString cmd;
275 cmd.sprintf("PRIO %d\n", prio);
276 return command(cmd);
277}
278
279int TDEsuClient::setScheduler(int sched)
280{
281 TQCString cmd;
282 cmd.sprintf("SCHD %d\n", sched);
283 return command(cmd);
284}
285
286int 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}
295int 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
310TQCString 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
320TQValueList<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
353bool 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
363int TDEsuClient::delVar(const TQCString &key)
364{
365 TQCString cmd = "DELV ";
366 cmd += escape(key);
367 cmd += "\n";
368 return command(cmd);
369}
370
371int TDEsuClient::delGroup(const TQCString &group)
372{
373 TQCString cmd = "DELG ";
374 cmd += escape(group);
375 cmd += "\n";
376 return command(cmd);
377}
378
379int 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
387int TDEsuClient::ping()
388{
389 return command("PING\n");
390}
391
392int TDEsuClient::exitCode()
393{
394 TQCString result;
395 if (command("EXIT\n", &result) != 0)
396 return -1;
397
398 return result.toLong();
399}
400
401int TDEsuClient::stopServer()
402{
403 return command("STOP\n");
404}
405
406static 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
419bool 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
435int 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 = tdeApp->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.4
This website is maintained by Timothy Pearson.