diff --git a/ChangeLog b/ChangeLog index 5d0a6275..a3296bb3 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2002-02-24 Tim Jansen + + * fixed DCOP port() call + + * added DCOP documentation + 2002-02-20 Tim Jansen * krfb/xupdatescanner.cc: split tiles into left&right half if neccessary. diff --git a/MODES_SECURITY b/MODES_SECURITY new file mode 100644 index 00000000..c4e9398a --- /dev/null +++ b/MODES_SECURITY @@ -0,0 +1,26 @@ +Modes & Security +================ + +KRfb has 3 different security modes +- stand-alone: + + traditional mode like in versions < 0.7 + + kinetd always disabled + + KRfb only accepts connections from the time the user + started it until he quits krfb + + no security restrictions (password can be empty) +- daemon/invitation only: + + new default since 0.7 + + kinetd is only enabled after the user invited someone + + krfb only accepts invited users, all other requests will be + denied +- daemon/open + + kinetd is always enabled + + a password must be set (enforced by kcontrol module, so this + can be overidden by editing the configuration) + + kinetd accepts both invited and other users + +- an invitation is a password that expires after a default of 60 min +- because of limitations in the Rfb protocol a connecting client must always + enter a password while invitations are valid, even if it is empty + + diff --git a/README b/README index 33931e6b..b043af12 100644 --- a/README +++ b/README @@ -17,5 +17,6 @@ ROADMAP - KRfb roadmap, progress and future features TODO - unscheduled things to be done NOTES - reasons for various decisions DCOP-INTERFACE - short documentation of the DCOP interface +MODES_SECURITY - modes & security settings ChangeLog - more detailed changes with dates diff --git a/ROADMAP b/ROADMAP index c159c4bb..287c687c 100644 --- a/ROADMAP +++ b/ROADMAP @@ -8,8 +8,8 @@ Version 0.6 (2002/02/18): Improved RFB backend - knotify Version 0.7: Better integration with KDE, improved GUI -- i18n - kded module 'kinetd' that listens on the Rfb port and starts KRfb +- invitation support - kcontrol module - on startup a dialog appears that allows the user to invite somebody using email (and later other mechanisms). Dialog can be turned off forever, @@ -17,5 +17,6 @@ Version 0.7: Better integration with KDE, improved GUI - remove STDOUT/STDERR logging Version 0.8: +- i18n - docs diff --git a/configure.in.in b/configure.in.in index 963911ed..1d0c6805 100644 --- a/configure.in.in +++ b/configure.in.in @@ -1,6 +1,6 @@ #MIN_CONFIG -AM_INIT_AUTOMAKE(krfb,0.6) +AM_INIT_AUTOMAKE(krfb,0.7) AC_CHECK_HEADER(X11/extensions/XTest.h, [], diff --git a/kinetd/Makefile.am b/kinetd/Makefile.am index 6573bfb1..f525c471 100644 --- a/kinetd/Makefile.am +++ b/kinetd/Makefile.am @@ -3,7 +3,7 @@ METASOURCES = AUTO # Code lib_LTLIBRARIES = libkded_kinetd.la -libkded_kinetd_la_SOURCES = kinetd.cpp kinetd.h +libkded_kinetd_la_SOURCES = kinetd.cpp kinetd.h kinetd.skel libkded_kinetd_la_LIBADD = $(LIB_QT) $(LIB_KDECORE) $(LIB_KDEUI) # Services diff --git a/kinetd/kinetd.cpp b/kinetd/kinetd.cpp index 8e2a9b47..c3497473 100644 --- a/kinetd/kinetd.cpp +++ b/kinetd/kinetd.cpp @@ -17,38 +17,73 @@ ***************************************************************************/ /* - * TODOs: - * - setup servicetype - * - override configuration in KDEHOME with a KConfig - * - set listening ip address - * - implement autoPortRange + * TODOs: + * - get notified of changes in services */ #include "kinetd.h" #include -#include #include +#include +#include -PortListener::PortListener(KService::Ptr s) : - valid(true), - autoPortRange(0), - multiInstance(false), - enabled(true) +PortListener::PortListener(KService::Ptr s) { + loadConfig(s); + + process.setExecutable(execPath); + + port = portBase; + socket = new KServerSocket(port, false); + while (!socket->bindAndListen()) { + port++; + if (port >= (portBase+autoPortRange)) { + kdDebug() << "Kinetd cannot load service "<name(); execPath = s->exec(); + vid = s->property("X-KDE-KINETD-id"); vport = s->property("X-KDE-KINETD-port"); vautoport = s->property("X-KDE-KINETD-autoPortRange"); venabled = s->property("X-KDE-KINETD-enabled"); - vargument = s->property("X-KDE-KINETD-argument"); - vmultiInstance = s->property("X-KDE-KINETD-multiInstance"); - - if (!vport.isValid()) + vargument = s->property("X-KDE-KINETD-argument"); + vmultiInstance = s->property("X-KDE-KINETD-multiInstance"); + + if (!vid.isValid()) { + kdDebug() << "Kinetd cannot load service "<bindAndListen()) { - // TODO: do something, implement autoport - kdDebug() << "bind failed" <setGroup("ListenerConfig"); + enabled = config->readBoolEntry("enabled_" + serviceName, enabled); } void PortListener::accepted(KSocket *sock) { kdDebug() << "got connection" << endl; - if ((!enabled) || - ((!multiInstance) && process.isRunning())) { + if ((!enabled) || + ((!multiInstance) && process.isRunning())) { delete sock; return; } @@ -90,9 +131,30 @@ bool PortListener::isValid() { return valid; } +bool PortListener::isEnabled() { + return enabled; +} + +void PortListener::setEnabled(bool e) { + if (e == enabled) + return; + enabled = e; + if (!config) + return; + config->setGroup("ListenerConfig"); + config->writeEntry("enabled_" + serviceName, enabled); + config->sync(); +} + +QString PortListener::name() { + return serviceName; +} + PortListener::~PortListener() { if (socket) delete socket; + if (config) + delete config; } @@ -103,20 +165,62 @@ KInetD::KInetD(QCString &n) : loadServiceList(); } -void KInetD::loadServiceList() +void KInetD::loadServiceList() { portListeners.clear(); - - KService::List kinetdModules = + + KService::List kinetdModules = KServiceType::offers("KInetDModule"); - for(KService::List::ConstIterator it = kinetdModules.begin(); - it != kinetdModules.end(); - it++) { + for(KService::List::ConstIterator it = kinetdModules.begin(); + it != kinetdModules.end(); + it++) { KService::Ptr s = *it; - portListeners.append(new PortListener(s)); + PortListener *pl = new PortListener(s); + if (pl->isValid()) + portListeners.append(pl); } } +PortListener *KInetD::getListenerByName(QString name) +{ + PortListener *pl = portListeners.first(); + while (pl) { + if (pl->name() == name) + return pl; + pl = portListeners.next(); + } + return pl; +} + +QStringList KInetD::services() +{ + QStringList list; + PortListener *pl = portListeners.first(); + while (pl) { + list.append(pl->name()); + pl = portListeners.next(); + } + return list; +} + +bool KInetD::isEnabled(QString service) +{ + PortListener *pl = getListenerByName(service); + if (!pl) + return false; + + return pl->isEnabled(); +} + +void KInetD::setEnabled(QString service, bool enable) +{ + PortListener *pl = getListenerByName(service); + if (!pl) + return; + + pl->setEnabled(enable); +} + extern "C" { KDEDModule *create_kinetd(QCString &name) diff --git a/kinetd/kinetd.h b/kinetd/kinetd.h index bdf4028d..feb3ec65 100644 --- a/kinetd/kinetd.h +++ b/kinetd/kinetd.h @@ -23,13 +23,15 @@ #include #include #include +#include +#include class PortListener : public QObject { Q_OBJECT private: bool valid; QString serviceName; - int port, autoPortRange; + int port, portBase, autoPortRange; bool multiInstance; QCString execPath; QString argument; @@ -37,11 +39,18 @@ private: KServerSocket *socket; KProcess process; + + KConfig *config; + + void loadConfig(KService::Ptr s); public: PortListener(KService::Ptr s); ~PortListener(); - + bool isValid(); + QString name(); + void setEnabled(bool enabled); + bool isEnabled(); private slots: void accepted(KSocket*); @@ -49,17 +58,40 @@ private slots: class KInetD : public KDEDModule { Q_OBJECT + K_DCOP + +k_dcop: + /** + * Returns a list of all registered services in KInetd. + * To add a service you need to add a .desktop file with + * the servicetype "KInetDModule" into the services director + * (see kinetdmodule.desktop in servicetypes dir). + * @return a list with the names of all services + */ + QStringList services(); + + /** + * Returns true if the service exists and is available. + * @param service name of a service as specified in its .desktop file + * @return true if a service with the given name exists and is enabled + */ + bool isEnabled(QString service); + + /** + * Enables or disabled the given service. Ignored if the given service + * does not exist. + * @param service name of a service as specified in its .desktop file + * @param enable true to enable, false to disable. + */ + void setEnabled(QString service, bool enable); + private: QPtrList portListeners; public: KInetD(QCString &n); void loadServiceList(); - - - - // DCOP functions - void reloadPortListenerList(); + PortListener *getListenerByName(QString name); }; diff --git a/kinetd/kinetdmodule.desktop b/kinetd/kinetdmodule.desktop index 1a28e863..f54a204b 100644 --- a/kinetd/kinetdmodule.desktop +++ b/kinetd/kinetdmodule.desktop @@ -1,22 +1,34 @@ +# describes the servicetype that you need to implement in order to use +# kinetd. [Desktop Entry] Type=ServiceType X-KDE-ServiceType=KInetDModule Name=KInetD Module Type -[PropertyDef::X-KDE-Kinetd-port] -Type=int - -[PropertyDef::X-KDE-Kinetd-autoPortRange] -Type=int - -[PropertyDef::X-KDE-Kinetd-enabled] -Type=bool - -[PropertyDef::X-KDE-Kinetd-argument] +# id to manipulate the service +[PropertyDef::X-KDE-KINETD-id] Type=QString -[PropertyDef::X-KDE-Kinetd-multiInstance] +# describes the TCP port kinetd should listen to +[PropertyDef::X-KDE-KINETD-port] +Type=int + +# if set and >0 the number of ports kinetd should probe if the port is in use +[PropertyDef::X-KDE-KINETD-autoPortRange] +Type=int + +# if enabled kinetd will listen on the port. Can be overridden using the +# dcop interface. +[PropertyDef::X-KDE-KINETD-enabled] Type=bool +# if set this argument if given to the app to start, followed by the number +# of the socket's fd +[PropertyDef::X-KDE-KINETD-argument] +Type=QString +# if true kinetd can accepts several connections at the same time. Otherwise +# it will block the port when a connection has been established. +[PropertyDef::X-KDE-KINETD-multiInstance] +Type=bool diff --git a/krfb.lsm b/krfb.lsm index d0b48771..0ca8ac09 100644 --- a/krfb.lsm +++ b/krfb.lsm @@ -1,6 +1,6 @@ Begin3 Title: KDE Desktop Sharing (KRfb) -Version: 0.6 +Version: 0.7 Entered-date: Description: KRfb is a RFB (VNC) server that allows sharing a local X11 session. diff --git a/krfb/Makefile.am b/krfb/Makefile.am index 0c3b5e09..83100100 100644 --- a/krfb/Makefile.am +++ b/krfb/Makefile.am @@ -7,10 +7,12 @@ krfb_SOURCES = rfbcontroller.cc configuration.cc trayicon.cpp \ krfb_LDADD = ../libvncserver/libvncserver.a -lz -lpthread -ljpeg -lXtst \ $(LIB_QT) $(LIB_KDECORE) $(LIB_KDEUI) $(LIBSOCKET) -EXTRA_DIST = $(krfb_SOURCES) krfb.desktop lo32-app-krfb.png \ - lo16-app-krfb.png rfbcontroller.h eyes-closed24.png eyes-open24.png \ - xupdatescanner.h trayicon.h configuration.h krfbiface.h krfbiface.kidl \ - eventsrc +kde_services_DATA = kinetd_krfb.desktop + +EXTRA_DIST = $(krfb_SOURCES) $(kde_services_DATA) krfb.desktop \ + lo32-app-krfb.png lo16-app-krfb.png rfbcontroller.h \ + eyes-closed24.png eyes-open24.png xupdatescanner.h trayicon.h \ + configuration.h krfbiface.h krfbiface.kidl eventsrc install-data-local: $(mkinstalldirs) $(kde_appsdir)/Applications/ diff --git a/krfb/kinetd_krfb.desktop b/krfb/kinetd_krfb.desktop index 0f7ac9d1..a50a1ced 100644 --- a/krfb/kinetd_krfb.desktop +++ b/krfb/kinetd_krfb.desktop @@ -2,14 +2,15 @@ Encoding=UTF-8 Type=Service -ServiceTypes=KDEDModule +ServiceTypes=KInetDModule Exec=krfb X-KDE-FactoryName=kinetd -X-KDE-Kinetd-port=5900 -X-KDE-Kinetd-autoPortRange=100 -X-KDE-Kinetd-enabled=true -X-KDE-Kinetd-argument=--kinetd -X-KDE-Kinetd-multiInstance=false +X-KDE-KINETD-id=krfb +X-KDE-KINETD-port=5900 +X-KDE-KINETD-autoPortRange=100 +X-KDE-KINETD-enabled=true +X-KDE-KINETD-argument=--kinetd +X-KDE-KINETD-multiInstance=false Name=KRfb Desktop Sharing Comment=A daemon that allows you to share your desktop diff --git a/krfb/krfbiface.h b/krfb/krfbiface.h index 2c7cb174..133e790c 100644 --- a/krfb/krfbiface.h +++ b/krfb/krfbiface.h @@ -7,17 +7,69 @@ class krfbIface : virtual public DCOPObject { K_DCOP k_dcop: + + /** + * If a client is connected it will be disconnected. + */ virtual void disconnect() = 0; // virtual void setWindowID(int) = 0; + + /** + * Quites krfb, connected clients will be disconnected. + */ virtual void exit() = 0; + /** + * If true krfb will disconnect after a client disconnected. + * @return true if oneConnection feature is turned on + */ virtual bool oneConnection() = 0; - virtual void setOneConnection(bool) = 0; + + /** + * If set to true krfb will disconnect after a client disconnected. + * @param o true to turn oneConnection feature on. + */ + virtual void setOneConnection(bool o) = 0; + + /** + * If this feature is activated krfb will ask the user before an incomning + * connection will be accepted. + * @return true if askOnConnect is activated + */ virtual bool askOnConnect() = 0; - virtual void setAskOnConnect(bool) = 0; + + /** + * If this feature is activated krfb will ask the user before an incomning + * connection will be accepted. + * @param a true to turn the askOnConnect feature on. + */ + virtual void setAskOnConnect(bool a) = 0; + + /** + * If this feature is activated krfb allows the connecting client to + * control the desktop (pointer & keyboard). + * @return true if desktop control is activated + */ virtual bool allowDesktopControl() = 0; - virtual void setAllowDesktopControl(bool) = 0; - virtual void setPassword(QString) = 0; + + /** + * If this feature is activated krfb allows the connecting client to + * control the desktop (pointer & keyboard). + * @return a true to activate desktop control + */ + virtual void setAllowDesktopControl(bool a) = 0; + + /** + * Sets the default password. An empty password can be used to deactivate + * the password authentication, but only if krfb is in stand-alone mode. + * @param p the password to set + */ + virtual void setPassword(QString p) = 0; + + /** + * Returns the port the server is listening on. + * @return the tcp port of the server + */ virtual int port() = 0; }; #endif diff --git a/krfb/main.cpp b/krfb/main.cpp index 766ae072..2aeca1d6 100644 --- a/krfb/main.cpp +++ b/krfb/main.cpp @@ -157,6 +157,8 @@ int main(int argc, char *argv[]) sigemptyset(&sigs); sigaddset(&sigs, SIGPIPE); sigprocmask(SIG_BLOCK, &sigs, 0); - + + controller.startServer(); + return app.exec(); } diff --git a/krfb/rfbcontroller.cc b/krfb/rfbcontroller.cc index 79931f6e..b1ddc0c1 100644 --- a/krfb/rfbcontroller.cc +++ b/krfb/rfbcontroller.cc @@ -249,8 +249,6 @@ RFBController::RFBController(Configuration *c) : asyncQueue.setAutoDelete(true); KeyboardEvent::initKeycodes(); - - startServer(); } RFBController::~RFBController() @@ -314,7 +312,7 @@ void RFBController::startServer(bool xtestGrab) server->frameBuffer = fb; server->autoPort = TRUE; - + server->kbdAddEvent = keyboardHook; server->ptrAddEvent = pointerHook; server->newClientHook = newClientHook; @@ -322,9 +320,9 @@ void RFBController::startServer(bool xtestGrab) passwordChanged(); - scanner = new XUpdateScanner(qt_xdisplay(), - QApplication::desktop()->winId(), - (unsigned char*)fb, w, h, + scanner = new XUpdateScanner(qt_xdisplay(), + QApplication::desktop()->winId(), + (unsigned char*)fb, w, h, server->rfbServerFormat.bitsPerPixel, server->paddedWidthInBytes); diff --git a/krfb/rfbcontroller.h b/krfb/rfbcontroller.h index 9d7150e0..ea89b332 100644 --- a/krfb/rfbcontroller.h +++ b/krfb/rfbcontroller.h @@ -99,13 +99,13 @@ public: * dialog. * The controller has three states: 'waiting for connection', * 'waiting for confirmation' and 'connected'. In the first state socket and - * connection are null, in the second socket is set and in the last both are + * connection are null, in the second socket is set and in the last both are * set. * @author Tim Jansen */ class RFBController : public QObject { Q_OBJECT -public: +public: RFBController(Configuration *c); virtual ~RFBController(); @@ -121,22 +121,22 @@ public: enum rfbNewClientAction handleNewClient(rfbClientPtr cl); void handleClientGone(); int getPort(); + void startServer(bool xtestGrab = true); static bool checkX11Capabilities(); -public slots: +public slots: void rebind(); void passwordChanged(); void closeConnection(); signals: void sessionEstablished(); - void sessionFinished(); + void sessionFinished(); void sessionRefused(); void portProbed(int); - -private: - void startServer(bool xtestGrab = true); + +private: void stopServer(bool xtestUngrab = true); bool checkAsyncEvents(); void sendDelayedKNotifyEvent(QString name, QString desc);