1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
|
/*
# Copyright (c) 2009 - OpenSLX Project, Computer Center University of Freiburg
#
# This program is free software distributed under the GPL version 2.
# See http://openslx.org/COPYING
#
# If you have any feedback please consult http://openslx.org/feedback and
# send your suggestions, praise, or complaints to feedback@openslx.org
#
# General information about OpenSLX can be found at http://openslx.org/
# --------------------------------------------------------------------------
# pvsPrivInputHandler.h
# - Handle privileged input connection requests - implementation
# --------------------------------------------------------------------------
*/
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include <cerrno>
#include <QtDebug>
#include <QSocketNotifier>
#include "inputEvent.h"
#include "inputHandlerChains.h"
#include "pvsPrivInputSocket.h"
#include "pvsPrivInputHandler.h"
using namespace std;
class PrivInputContext : public InputEventContext
{
public:
PrivInputContext(pid_t pid, uid_t uid, gid_t gid)
: _pid(pid), _uid(uid), _gid(gid)
{
}
pid_t senderPid() const
{
return _pid;
}
uid_t senderUid() const
{
return _uid;
}
gid_t senderGid() const
{
return _gid;
}
private:
pid_t _pid;
uid_t _uid;
gid_t _gid;
};
PVSPrivInputHandler::PVSPrivInputHandler(int fd, QObject* parent) :
QObject(parent)
{
_fd = fd;
_notifier = new QSocketNotifier(fd, QSocketNotifier::Read, this);
_notifier->setEnabled(true);
connect(_notifier, SIGNAL(activated(int)), this, SLOT(canRead()));
_handlerChain = makePrivilegedInputEventHandlerChain();
}
PVSPrivInputHandler::~PVSPrivInputHandler()
{
delete _notifier;
}
void PVSPrivInputHandler::canRead()
{
_notifier->setEnabled(false);
// We need to retrieve the credentials of the process:
size_t siz = 8;
_messageAssembly.clear();
_messageAssembly.resize(8);
pid_t pid;
uid_t uid;
gid_t gid;
int err;
if(!pvsPrivInputRecvMessage(_fd, _messageAssembly.data(), siz, pid, uid, gid, &err))
{
switch(err)
{
case EAGAIN:
#if defined(EWOULDBLOCK) && (EWOULDBLOCK != EAGAIN)
case EWOULDBLOCK:
#endif
// That's okay. Nothing to do.
break;
case 0:
// We'll survive. There was no actual error, just the library routine
// that decided it did not really want to receive that packet.
break;
default:
qWarning("Something bad just happened, and cannot handle it. Panicking.");
close(_fd);
deleteLater();
return;
}
}
else
{
if(siz != 8)
{
qWarning("Malformed PVS Input Event packet");
return;
}
QDataStream strm(&_messageAssembly, QIODevice::ReadOnly);
InputEvent evt;
strm.setByteOrder(QDataStream::BigEndian);
strm >> evt;
PrivInputContext ctx(pid, uid, gid);
_handlerChain.handle(evt, &ctx);
}
_notifier->setEnabled(true);
}
|