2 * KFontInst - KDE Font Installer
4 * Copyright 2003-2007 Craig Drummond <craig@kde.org>
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; see the file COPYING. If not, write to
20 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
21 * Boston, MA 02110-1301, USA.
25 // This file contains code taken from kdelibs/kdesu/client.cpp
35 #include <sys/types.h>
36 #include <sys/socket.h>
39 #include <QtCore/QByteArray>
40 #include <config-workspace.h>
45 #define SUN_LEN(ptr) ((socklen_t) (((struct sockaddr_un *) 0)->sun_path) \
46 + strlen ((ptr)->sun_path))
52 CSocket::CSocket(int fd
)
63 bool CSocket::read(QVariant
&var
, int timeout
)
70 if(readBlock((char *)&type
, sizeof(type
), timeout
))
77 if(readBlock((char *)(&val
), sizeof(int), timeout
))
84 case QVariant::ULongLong
:
87 if(readBlock((char *)(&val
), sizeof(qulonglong
), timeout
))
97 if(readBlock((char *)(&val
), sizeof(unsigned char), timeout
))
99 var
=QVariant((bool)val
);
104 case QVariant::String
:
108 if(readBlock((char *)&len
, sizeof(unsigned int), timeout
))
110 QByteArray
data(len
, '\0');
112 if(readBlock(data
.data(), len
, timeout
))
114 var
=QVariant(QString::fromUtf8(data
));
127 bool CSocket::read(QString
&str
, int timeout
)
131 if(read(var
, timeout
) && QVariant::String
==var
.type())
140 bool CSocket::read(int &i
, int timeout
)
144 if(read(var
, timeout
) && QVariant::Int
==var
.type())
153 bool CSocket::read(qulonglong
&i
, int timeout
)
157 if(read(var
, timeout
) && QVariant::ULongLong
==var
.type())
166 bool CSocket::read(bool &b
, int timeout
)
170 if(read(var
, timeout
) && QVariant::Bool
==var
.type())
179 bool CSocket::write(const QVariant
&var
, int timeout
)
184 int type(var
.type());
190 int val(var
.toInt());
191 return writeBlock((const char *)(&type
), sizeof(int), timeout
) &&
192 writeBlock((const char *)(&val
), sizeof(int), timeout
);
194 case QVariant::ULongLong
:
196 qulonglong
val(var
.toInt());
197 return writeBlock((const char *)(&type
), sizeof(int), timeout
) &&
198 writeBlock((const char *)(&val
), sizeof(qulonglong
), timeout
);
202 unsigned char val(var
.toBool());
204 return writeBlock((const char *)(&type
), sizeof(int), timeout
) &&
205 writeBlock((const char *)(&val
), sizeof(unsigned char), timeout
);
208 case QVariant::String
:
210 QByteArray
data(var
.toString().toUtf8());
211 int len(data
.size());
213 return writeBlock((const char *)(&type
), sizeof(int), timeout
) &&
214 writeBlock((const char *)(&len
), sizeof(int), timeout
) &&
215 writeBlock(data
.constData(), len
, timeout
);
225 bool CSocket::connectToServer(const QByteArray
&sock
, unsigned int socketUid
)
230 if (access(sock
, R_OK
|W_OK
))
233 itsFd
=::socket(PF_UNIX
, SOCK_STREAM
, 0);
236 kWarning() << k_lineinfo
<< "socket(): " << errno
;
239 struct sockaddr_un addr
;
240 addr
.sun_family
= AF_UNIX
;
241 strcpy(addr
.sun_path
, sock
);
243 if (::connect(itsFd
, (struct sockaddr
*) &addr
, SUN_LEN(&addr
)) < 0)
245 kWarning() << k_lineinfo
<< "connect():" << errno
;
251 #if !defined(SO_PEERCRED) || !defined(HAVE_STRUCT_UCRED)
252 # if defined(HAVE_GETPEEREID)
255 // Security: if socket exists, we must own it
256 if (getpeereid(itsFd
, &euid
, &egid
) == 0)
258 if (euid
!= socketUid
)
260 kWarning(900) << "socket not owned by me! socket uid = " << euid
;
268 # warning "Using sloppy security checks"
270 // We check the owner of the socket after we have connected.
271 // If the socket was somehow not ours an attacker will be able
272 // to delete it after we connect but shouldn't be able to
273 // create a socket that is owned by us.
275 if (KDE_lstat(sock
, &s
)!=0)
277 kWarning(900) << "stat failed (" << sock
<< ")";
282 if (s
.st_uid
!= socketUid
)
284 kWarning(900) << "socket not owned by me! socket uid = " << s
.st_uid
;
289 if (!S_ISSOCK(s
.st_mode
))
291 kWarning(900) << "socket is not a socket (" << sock
<< ")";
299 socklen_t siz
= sizeof(cred
);
301 // Security: if socket exists, we must own it
302 if (getsockopt(itsFd
, SOL_SOCKET
, SO_PEERCRED
, &cred
, &siz
) == 0)
304 if (cred
.uid
!= socketUid
)
306 kWarning(900) << "socket not owned by me! socket uid = " << cred
.uid
;
317 bool CSocket::readBlock(char *data
, int size
, int timeout
)
319 int bytesToRead
=size
;
323 if(waitForReadyRead(timeout
))
325 int bytesRead
=::read(itsFd
, &data
[size
-bytesToRead
], bytesToRead
);
328 bytesToRead
-=bytesRead
;
335 while(bytesToRead
>0);
340 bool CSocket::writeBlock(const char *data
, int size
, int timeout
)
342 int bytesToWrite
=size
;
346 if(waitForReadyWrite(timeout
))
348 int bytesWritten
=::write(itsFd
, (char *)&data
[size
-bytesToWrite
], bytesToWrite
);
351 bytesToWrite
-=bytesWritten
;
358 while(bytesToWrite
>0);
363 bool CSocket::waitForReadyRead(int timeout
)
369 FD_SET(itsFd
, &fdSet
);
374 if(select(itsFd
+ 1, &fdSet
, NULL
, NULL
, -1==timeout
? NULL
: &tv
)<0)
382 return FD_ISSET(itsFd
, &fdSet
);
387 bool CSocket::waitForReadyWrite(int timeout
)
393 FD_SET(itsFd
, &fdSet
);
398 if(select(itsFd
+ 1, NULL
, &fdSet
, NULL
, -1==timeout
? NULL
: &tv
)<0)
406 return FD_ISSET(itsFd
, &fdSet
);