summaryrefslogtreecommitdiffstats
path: root/kdmlib/kgreeterplugin.h
diff options
context:
space:
mode:
Diffstat (limited to 'kdmlib/kgreeterplugin.h')
-rw-r--r--kdmlib/kgreeterplugin.h401
1 files changed, 401 insertions, 0 deletions
diff --git a/kdmlib/kgreeterplugin.h b/kdmlib/kgreeterplugin.h
new file mode 100644
index 000000000..e7677415c
--- /dev/null
+++ b/kdmlib/kgreeterplugin.h
@@ -0,0 +1,401 @@
+/*
+
+ Authentication method specific conversation plugin for KDE's greeter widgets
+
+ Copyright (C) 2003 Oswald Buddenhagen <ossi@kde.org>
+ Copyright (C) 2003 Fabian Kaiser <xfk@softpro.de>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef KGREETERPLUGIN_H
+#define KGREETERPLUGIN_H
+
+#include <qvariant.h>
+#include <qmessagebox.h>
+#include <kdemacros.h>
+
+class KdmThemer;
+
+class QWidget;
+class QLayoutItem;
+
+class KGreeterPluginHandler {
+public:
+ /* keep in sync with V_IS_* */
+ enum { IsSecret = 1, IsUser = 2, IsPassword = 4, IsOldPassword = 8,
+ IsNewPassword = 16 };
+ /**
+ * Reply to textPrompt().
+ * @param text text to return to core; null to abort auth cycle
+ * @param tag zero or one of Is*
+ */
+ virtual void gplugReturnText( const char *text, int tag ) = 0;
+ /**
+ * Reply to binaryPrompt().
+ * @param data data in pam_client format to return to the core;
+ * null to abort auth cycle
+ */
+ virtual void gplugReturnBinary( const char *data ) = 0;
+ /**
+ * Tell the greeter who is logging in.
+ * Call this preferably before gplugStart, as otherwise the .dmrc
+ * load will be delayed. Don't call at all if your plugin doesn't
+ * have the Local flag set. Call only for internally generated
+ * user changes.
+ * @param user the user logging in
+ */
+ virtual void gplugSetUser( const QString &user ) = 0;
+ /**
+ * Start processing.
+ */
+ virtual void gplugStart() = 0;
+ /**
+ * Plugins that expect user input from a different device than the mouse or
+ * keyboard must call this when user activity is detected to prevent the
+ * greeter from resetting/going away. Events should be compressed to no
+ * more than ten per second; one every five seconds is actually enough.
+ * Events should be actual changes to the input fields, not random motion.
+ */
+ virtual void gplugActivity() = 0;
+ /**
+ * Show a message box on behalf of the talker.
+ * @param type message severity
+ * @param text message text
+ */
+ virtual void gplugMsgBox( QMessageBox::Icon type, const QString &text ) = 0;
+};
+
+/**
+ * Abstract base class for conversation plugins ("talkers") to be used with
+ * KDM, kdesktop_lock, etc.
+ * The authentication method used by a particular instance of a plugin
+ * may be configurable, but the instance must handle exactly one method,
+ * i.e., info->method must be determined at the latest at init() time.
+ */
+class KGreeterPlugin {
+public:
+ KGreeterPlugin( KGreeterPluginHandler *h ) : handler( h ) {}
+ virtual ~KGreeterPlugin() {}
+
+ /**
+ * Variations of the talker:
+ * - Authenticate: authentication
+ * - AuthChAuthTok: authentication and password change
+ * - ChAuthTok: password change
+ */
+ enum Function { Authenticate, AuthChAuthTok, ChAuthTok };
+
+ /**
+ * Contexts the talker can be used in:
+ * - Login: kdm login dialog
+ * - Shutdown: kdm shutdown dialog
+ * - Unlock: kdm unlock dialog (TODO)
+ * - ChangeTok: kdm password change dialog (TODO)
+ * - ExUnlock: kdesktop_lock unlock dialog
+ * - ExChangeTok: kdepasswd password change dialog (TODO)
+ *
+ * The Ex* contexts exist within a running session; the talker must know
+ * how to obtain the currently logged in user (+ domain/realm, etc.)
+ * itself (i.e., fixedEntity will be null). The non-Ex variants will have
+ * a fixedEntity passed in.
+ */
+ enum Context { Login, Shutdown, Unlock, ChangeTok,
+ ExUnlock, ExChangeTok };
+
+ /**
+ * Provide the talker with a list of selectable users. This can be used
+ * for autocompletion, etc.
+ * Will be called only when not running.
+ * @param users the users to load.
+ */
+ virtual void loadUsers( const QStringList &users ) = 0;
+
+ /**
+ * Preload the talker with an (opaque to the greeter) entity.
+ * Will be called only when not running.
+ * @param entity the entity to preload the talker with. That
+ * will usually be something like "user" or "user@domain".
+ * @param field the sub-widget (probably line edit) to put the cursor into.
+ * If -1, preselect the user for timed login. This means pre-filling
+ * the password field with anything, disabling it, and placing the
+ * cursor in the user name field.
+ */
+ virtual void presetEntity( const QString &entity, int field ) = 0;
+
+ /**
+ * Obtain the actually logged in entity.
+ * Will be called only after succeeded() was called.
+ */
+ virtual QString getEntity() const = 0;
+
+ /**
+ * "Push" a user into the talker. That can be a click into the user list
+ * or successful authentication without the talker calling gplugSetUser.
+ * Will be called only when running.
+ * @param user the user to set. Note that this is a UNIX login, not a
+ * canonical entity
+ */
+ virtual void setUser( const QString &user ) = 0;
+
+ /**
+ * En-/disable any widgets contained in the talker.
+ * Will be called only when not running.
+ * @param on the state to set
+ */
+ virtual void setEnabled( bool on ) = 0;
+
+ /**
+ * Called when a message from the authentication backend arrives.
+ * @param message the message received from the backend
+ * @param error if true, @p message is an error message, otherwise it's
+ * an informational message
+ * @return true means that the talker already handled the message, false
+ * that the greeter should display it in a message box
+ *
+ * FIXME: Filtering a message usually means that the backend issued a
+ * prompt and obtains the authentication data itself. However, in that
+ * state the backend is unresponsive, e.g., no shutdown is possible.
+ * The frontend could send the backend a signal, but the "escape path"
+ * within the backend is unclear (PAM won't like simply longjmp()ing
+ * out of it).
+ */
+ virtual bool textMessage( const char *message, bool error ) = 0;
+
+ /**
+ * Prompt the user for data. Reply by calling handler->gplugReturnText().
+ * @param propmt the prompt to display. It may be null, in which case
+ * "Username"/"Password" should be shown and the replies should be tagged
+ * with the respective Is* flag.
+ * @param echo if true, a normal input widget can be used, otherwise one that
+ * visually obscures the user's input.
+ * @param nonBlocking if true, report whatever is already available,
+ * otherwise wait for user input.
+ */
+ virtual void textPrompt( const char *prompt, bool echo, bool nonBlocking ) = 0;
+
+ /**
+ * Request binary authentication data from the talker. Reply by calling
+ * handler->gplugReturnBinary().
+ * @param prompt prompt in pam_client format
+ * @param nonBlocking if true, report whatever is already available,
+ * otherwise wait for user input.
+ * @return always true for now
+ *
+ * TODO:
+ * @return if true, the prompt was handled by the talker, otherwise the
+ * handler has to use libpam_client to obtain the authentication data.
+ * In that state the talker still can abort the data fetch by
+ * gplugReturn()ing a null array. When the data was obtained, another
+ * binaryPrompt with a null prompt will be issued.
+ */
+ virtual bool binaryPrompt( const char *prompt, bool nonBlocking ) = 0;
+
+ /**
+ * This can either
+ * - Start a processing cycle. Will be called only when not running.
+ * - Restart authTok cycle - will be called while running and implies
+ * revive(). PAM is a bit too clever, so we need this.
+ * In any case the talker is running afterwards.
+ */
+ virtual void start() = 0;
+
+ /**
+ * Request to suspend the auth. Make sure that a second talker of any
+ * type will be able to operate while this one is suspended (no busy
+ * device nodes, etc.).
+ * Will be called only if running within Login context. (Actually it
+ * won't be called at all, but be prepared.)
+ */
+ virtual void suspend() = 0;
+
+ /**
+ * Request to resume the auth from the point it was suspended at.
+ * Will be called only when suspended.
+ */
+ virtual void resume() = 0;
+
+ /**
+ * The "login" button was pressed in the greeter.
+ * This might call gplugReturn* or gplugStart.
+ * Will be called only when running.
+ */
+ virtual void next() = 0;
+
+ /**
+ * Abort auth cycle. Note that this should _not_ clear out already
+ * entered auth tokens if they are still on the screen.
+ * Will be called only when running and stops it.
+ */
+ virtual void abort() = 0;
+
+ /**
+ * Indicate successful end of the current phase.
+ * This is more or less a request to disable editable widgets
+ * responsible for the that phase.
+ * There will be no further attempt to enter that phase until the
+ * widget is destroyed.
+ * Will be called only when running and stops it.
+ */
+ virtual void succeeded() = 0;
+
+ /**
+ * Indicate unsuccessful end of the current phase.
+ * This is mostly a request to disable all editable widgets.
+ * The widget will be treated as dead until revive() is called.
+ * Will be called only when running and stops it.
+ */
+ virtual void failed() = 0;
+
+ /**
+ * Prepare retrying the previously failed phase.
+ * This is mostly a request to re-enable all editable widgets failed()
+ * disabled previously, clear the probably incorrect authentication tokens
+ * and to set the input focus appropriately.
+ * Will be called only after failed() (possibly with clear() in between),
+ * or after presetEntity() with field -1.
+ */
+ virtual void revive() = 0;
+
+ /**
+ * Clear any edit widgets, particularily anything set by setUser.
+ * Will be called only when not running.
+ */
+ virtual void clear() = 0;
+
+ /**
+ * Obtain the QLayoutItem containg the widget(s) to actually handle the
+ * conversation. See QLayout and QWidgetItem for possible implementations.
+ */
+ QLayoutItem *getLayoutItem() const { return layoutItem; }
+
+protected:
+ KGreeterPluginHandler *handler;
+ QLayoutItem *layoutItem;
+};
+
+struct KDE_EXPORT kgreeterplugin_info {
+ /**
+ * Human readable name of this plugin (should be a little more
+ * informative than just the libary name). Must be I18N_NOOP()ed.
+ */
+ const char *name;
+
+ /**
+ * The authentication method to use - the meaning is up to the backend,
+ * but will usually be related to the PAM service.
+ */
+ const char *method;
+
+ /**
+ * Capabilities.
+ */
+ enum {
+ /**
+ * All users exist on the local system permanently (will be listed
+ * by getpwent()); an entity corresponds to a UNIX user.
+ */
+ Local = 1,
+ /**
+ * The entities consist of multiple fields.
+ * PluginOptions/<plugin>.FocusField is used instead of FocusPasswd.
+ */
+ Fielded = 2,
+ /**
+ * An entity can be preset, the talker has a widget where a user can
+ * be selected explicitly. If the method is "classic", timed login
+ * is possible, too.
+ * This also means that setUser/gplugSetUser can be used and a
+ * userlist can be shown at all - provided Local is set as well.
+ */
+ Presettable = 4
+ };
+
+ /*
+ * Capability flags.
+ */
+ int flags;
+
+ /**
+ * Call after loading the plugin.
+ *
+ * @param method if non-empty and the plugin is unable to handle that
+ * method, return false. If the plugin has a constant method defined
+ * above, it can ignore this parameter.
+ * @param getConf can be used to obtain configuration items from the
+ * greeter; you have to pass it the @p ctx pointer.
+ * The only predefined key (in KDM) is "EchoMode", which is an int
+ * (in fact, KPasswordEdit::EchoModes).
+ * Other keys are obtained from the PluginOptions option; see kdmrc
+ * for details.
+ * If the key is unknown, dflt is returned.
+ * @param ctx context pointer for @p getConf
+ * @return if false, unload the plugin again (don't call done() first)
+ */
+ bool (*init)( const QString &method,
+ QVariant (*getConf)( void *ctx, const char *key,
+ const QVariant &dflt ),
+ void *ctx );
+
+ /**
+ * Call before unloading the plugin.
+ * This pointer can be null.
+ */
+ void (*done)( void );
+
+ /**
+ * Factory method to create an instance of the plugin.
+ * Note that multiple instances can exist at one time, but only
+ * one of them is active at any moment (the others would be suspended
+ * or not running at all).
+ * @param handler the object offering the necessary callbacks
+ * @param parent parent widget
+ * @param predecessor the focus widget before the conversation widget
+ * @param fixedEntity see below
+ * @param func see below
+ * @param ctx see below
+ * @return an instance of this conversation plugin
+ *
+ * Valid combinations of Function and Context:
+ * - Authenticate:Login - init
+ * - Authenticate:Shutdown - init, for now "root" is passed as fixedEntitiy
+ * and it is not supposed to be displayed. Plugins with Local not set
+ * might have to conjure something up to make getEntity() return a
+ * canonical entitiy. FIXME: don't restrict shutdown to root.
+ * - AuthChAuthTok:Login, AuthChAuthTok:Shutdown - cont/cont,
+ * only relevant for classic method (as it is relevant only for password-
+ * less logins, which always use classic). The login should not be shown -
+ * it is known to the user already; the backend won't ask for it, either.
+ * - ChAuthTok:Login & ChAuthTok:Shutdown - cont
+ * - Authenticate:Unlock & Authenticate:ExUnlock - init,
+ * AuthChAuthTok:ChangeTok & AuthChAuthTok:ExChangeTok - init/cont,
+ * display fixedEntity as labels. The backend does not ask for the UNIX
+ * login, as it already knows it - but it will ask for all components of
+ * the entity if it is no UNIX login.
+ *
+ * "init" means that the plugin is supposed to call gplugStart, "cont"
+ * that the backend is already in a cycle of the method the plugin was
+ * initialized with.
+ */
+ KGreeterPlugin *(*create)( KGreeterPluginHandler *handler,
+ KdmThemer *themer,
+ QWidget *parent, QWidget *predecessor,
+ const QString &fixedEntity,
+ KGreeterPlugin::Function func,
+ KGreeterPlugin::Context ctx );
+};
+
+#endif