/*
# Copyright (c) 2009,2010 - 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/
# -----------------------------------------------------------------------------
# src/net/pvsCheckPrivileges_linux.h
# - Linux implementation of privilege checking
# -----------------------------------------------------------------------------
*/
#ifndef PVSCHECKPRIVILEGES_H_
#define PVSCHECKPRIVILEGES_H_
#include <sys/types.h>
#include <QObject>
#include <QString>
#include <QList>
#include <QMultiMap>
#include <QHash>
#include "inputEventHandler.h"
/**
* Store the information in an InputEventContext as a plain old datatype.
*/
struct CachedInputContext
{
CachedInputContext(InputEventContext const* source)
{
if(source)
{
pid = source->senderPid();
uid = source->senderUid();
gid = source->senderGid();
}
else
{
pid = (pid_t)-1;
uid = (uid_t)-1;
gid = (gid_t)-1;
}
}
CachedInputContext()
{
pid = (pid_t)-1;
uid = (uid_t)-1;
gid = (gid_t)-1;
}
pid_t pid;
uid_t uid;
gid_t gid;
bool isValid() const
{
return (pid != (pid_t)-1) && (uid != (uid_t)-1) && (gid != (gid_t)-1);
}
bool operator==(CachedInputContext const& other) const
{
return (other.pid == pid) && (other.uid == uid) && (other.gid == gid);
}
};
uint qHash(CachedInputContext const& p);
class QFileSystemWatcher;
/**
* Check user privileges and handle communications with ConsoleKit and PolicyKit.
* This is a singleton class.
*/
class PVSCheckPrivileges : public QObject
{
Q_OBJECT
public:
/**
* SessionKind distinguishes between local and remote users.
*/
typedef enum {
SESSION_LOCAL, /**< User is local */
SESSION_NONLOCAL, /**< User is remote */
SESSION_LOOKUP_FAILURE, /**< Failure to look up whether the user is local or remote */
SESSION_UNKNOWN /**< User session kind not (yet) known */
} SessionKind;
/**
* UserPrivilege distinguishes between privileged and unprivileged users.
*/
typedef enum {
USER_PRIVILEGED, /**< User is privileged */
USER_UNPRIVILEGED, /**< User is unprivileged */
USER_LOOKUP_FAILURE, /**< Failure to look up whether the user is privileged or unprivileged */
USER_UNKNOWN /**< User privilege level not (yet) known */
} UserPrivilege;
/** \name Conversion Functions */
/* @{ */
static QString toString(SessionKind k)
{
switch(k)
{
case SESSION_LOOKUP_FAILURE: return "SESSION_LOOKUP_FAILURE";
case SESSION_LOCAL: return "SESSION_LOCAL";
case SESSION_NONLOCAL: return "SESSION_NONLOCAL";
case SESSION_UNKNOWN: return "SESSION_UNKNOWN";
default: return QString("unknown value (%1)").arg(k);
}
}
static QString toString(UserPrivilege k)
{
switch(k)
{
case USER_PRIVILEGED: return "USER_PRIVILEGED";
case USER_UNPRIVILEGED: return "USER_UNPRIVILEGED";
case USER_LOOKUP_FAILURE: return "USER_LOOKUP_FAILURE";
case USER_UNKNOWN: return "USER_UNKNOWN";
default: return QString("unknown value (%1)").arg(k);
}
}
/* @} */
/** \name Singleton pattern */
/* @{ */
/** Retrieve the singleton instance. */
static PVSCheckPrivileges* instance();
/** Delete the singleton instance. */
static void deleteInstance();
/* @} */
/** \name Privilege Checks */
/* @{ */
/** Check for a minimum SessionKind level. \return true if the requirement is fulfilled. */
bool require(SessionKind sessionKind, CachedInputContext const& sender);
/** Check for a minimum UserPrivilege level. \return true if the requirement is fulfilled. */
bool require(UserPrivilege userPrivilege, CachedInputContext const& sender);
/** Check for a minimum SessionKind and UserPrivilege level. \return true if both requirements are fulfilled. */
bool require(SessionKind sessionKind, UserPrivilege userPrivilege, CachedInputContext const& sender);
/* @} */
/** \name Session Information */
/* @{ */
/** Retrieve the name of the user's X session, according to ConsoleKit. */
QString getX11SessionName(CachedInputContext const& sender);
/** Retrieve the TTY device of the user's X session, according to ConsoleKit. */
QString getX11DisplayDevice(CachedInputContext const& sender);
public slots:
void updateCachedUserDatabase();
void rereadConfiguration();
private:
PVSCheckPrivileges(QObject* parent = 0);
virtual ~PVSCheckPrivileges();
typedef QPair<pid_t, QPair<uid_t, gid_t> > piduidgid;
piduidgid makePidUidGid(pid_t pid, uid_t uid, gid_t gid)
{
return qMakePair(pid, qMakePair(uid, gid));
}
QString getSessionReference(CachedInputContext const& sender);
SessionKind getSessionKind(CachedInputContext const& sender);
UserPrivilege getUserPrivilege(CachedInputContext const& sender);
static PVSCheckPrivileges* _instance;
QHash<CachedInputContext, UserPrivilege> _savedUserPrivilege;
QHash<CachedInputContext, SessionKind> _savedSessionKind;
QHash<CachedInputContext, QString> _savedConsoleKitSession;
QList<uid_t> _privilegedUsers;
QList<gid_t> _privilegedGroups;
QMultiMap<uid_t, gid_t> _userGroupMap;
QFileSystemWatcher* _watcher;
};
#endif /* PVSCHECKPRIVILEGES_H_ */