You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
tdebase/tdmlib/kgreeterplugin.h

427 lines
16 KiB

/*
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 <tqvariant.h>
#include <tqmessagebox.h>
#include <kdemacros.h>
class KdmThemer;
class TQWidget;
class TQLayoutItem;
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 TQString &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( TQMessageBox::Icon type, const TQString &text ) = 0;
};
/**
* Abstract base class for conversation plugins ("talkers") to be used with
* TDM, 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: tdm login dialog
* - Shutdown: tdm shutdown dialog
* - Unlock: tdm unlock dialog (TODO)
* - ChangeTok: tdm password change dialog (TODO)
* - ExUnlock: kdesktop_lock unlock dialog
* - ExChangeTok: tdepasswd 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 TQStringList &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 TQString &entity, int field ) = 0;
/**
* Obtain the actually logged in entity.
* Will be called only after succeeded() was called.
*/
virtual TQString 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 TQString &user ) = 0;
/**
* Lock or unlock editing of the username entry field
* @param lock true to lock, false to unlock
*/
virtual void lockUserEntry( const bool lock ) = 0;
/**
* "Push" a password into the talker.
* @param pass the password to set.
*/
virtual void setPassword( const TQString &pass ) = 0;
/**
* Set the talker's password prompt to a custom string
* @param prompt the password prompt to set, or TQString::null for default
*/
virtual void setPasswordPrompt( const TQString &prompt ) = 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;
/**
* En-/disable display of informational messages
* The default is to display all informational messages
* @param on the state to set
*/
virtual void setInfoMessageDisplay( 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 prompt 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 TQLayoutItem containg the widget(s) to actually handle the
* conversation. See TQLayout and TQWidgetItem for possible implementations.
*/
TQLayoutItem *getLayoutItem() const { return layoutItem; }
protected:
KGreeterPluginHandler *handler;
TQLayoutItem *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 TDM) is "EchoMode", which is an int
* (in fact, KPasswordEdit::EchoModes).
* Other keys are obtained from the PluginOptions option; see tdmrc
* 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 TQString &method,
TQVariant (*getConf)( void *ctx, const char *key,
const TQVariant &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,
TQWidget *parent, TQWidget *predecessor,
const TQString &fixedEntity,
KGreeterPlugin::Function func,
KGreeterPlugin::Context ctx );
};
#endif