Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

pin.cpp

Go to the documentation of this file.
00001 
00004 /**********************************************************************
00005  ** Copyright (C) 2000-2002 Trolltech AS.  All rights reserved.
00006  **
00007  ** This file is part of the Qtopia Environment.
00008  **
00009  ** This file may be distributed and/or modified under the terms of the
00010  ** GNU General Public License version 2 as published by the Free Software
00011  ** Foundation and appearing in the file LICENSE.GPL included in the
00012  ** packaging of this file.
00013  **
00014  ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
00015  ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
00016  **
00017  ** See http://www.trolltech.com/gpl/ for GPL licensing information.
00018  **
00019  ** Contact info@trolltech.com if any conditions of this licensing are
00020  ** not clear to you.
00021  **
00022  **********************************************************************/
00023 
00024 #include "pin.h"
00025 #include "pinDialogBase.h"
00026 /* OPIE */
00027 #include <opie2/odebug.h>
00028 #include <opie2/oapplication.h>
00029 /* QT */
00030 #include <qpe/config.h>
00031 #include <qlabel.h>
00032 #include <qlineedit.h>
00033 #include <qtextview.h>
00034 #include <qstring.h>
00035 #include <qdialog.h>
00036 /* UNIX */
00037 #include <unistd.h>
00038 #include <stdlib.h>
00039 #include <time.h>
00040 
00041 extern "C" char *crypt(const char *key, const char *salt);
00042 
00043 using Opie::Security::MultiauthConfigWidget;
00044 using Opie::Security::MultiauthPluginObject;
00045 
00047 static bool isSkip = FALSE;
00048 
00050 
00056 class PinDialog : public PinDialogBase
00057 {
00058     Q_OBJECT
00059 
00060     public:
00061         PinDialog( QWidget* parent = 0, const char* name = 0, WFlags fl = 0 );
00062         ~PinDialog();
00063 
00064         void clear();
00065         void setPrompt( const QString& );
00066 
00067 signals:
00069         void passwordEntered( const QString& );
00071         void skip();
00072 
00073     protected:
00074         bool eventFilter( QObject*, QEvent* );
00075 
00076     private:
00077         void input( QString );
00078         friend class PinPlugin;
00079         QString text;
00080 };
00081 
00082 
00084 PinDialog::PinDialog( QWidget* parent,  const char* name, WFlags fl )
00085     : PinDialogBase( parent, name, fl )
00086 {
00087     QRect desk = oApp->desktop()->geometry();
00088 
00089     if ( desk.width() < 220 ) {
00090         QFont f( font() );
00091         f.setPointSize( 18 );
00092         setFont( f );
00093         f.setPointSize( 12 );
00094         prompt->setFont( f );
00095     }
00096 
00097     button_0->installEventFilter( this );
00098     button_1->installEventFilter( this );
00099     button_2->installEventFilter( this );
00100     button_3->installEventFilter( this );
00101     button_4->installEventFilter( this );
00102     button_5->installEventFilter( this );
00103     button_6->installEventFilter( this );
00104     button_7->installEventFilter( this );
00105     button_8->installEventFilter( this );
00106     button_9->installEventFilter( this );
00107     button_Skip->installEventFilter( this );
00108     button_OK->installEventFilter( this );
00109     setFocus();
00110 }
00111 
00113 PinDialog::~PinDialog()
00114 {
00115     // no need to delete child widgets, Qt does it all for us
00116 }
00117 
00119 bool PinDialog::eventFilter( QObject*o, QEvent*e )
00120 {
00121     if ( e->type() == QEvent::MouseButtonRelease ) {
00122         if ( o == button_OK ) {
00123             emit passwordEntered( text );
00124         }
00125         else if ( o == button_Skip ) {
00126             isSkip = TRUE;
00127             emit skip();
00128         }
00129         else {
00130             QLabel *l = (QLabel*)o;
00131             input(l->text());
00132         }
00133     }
00134     return FALSE;
00135 }
00136 
00137 void PinDialog::input( QString c )
00138 {
00139     text += c;
00140     display->setText( text );
00141 }
00142 
00143 void PinDialog::setPrompt( const QString& s )
00144 {
00145     prompt->setText( s );
00146 }
00147 
00148 void PinDialog::clear()
00149 {
00150     text = "";
00151     input("");
00152 }
00153 
00155 
00159 class PinDlg : public QDialog
00160 {
00161     public:
00162         PinDlg( QWidget *parent, const char * name, bool modal, bool fullscreen = FALSE )
00163             : QDialog( parent, name, modal, fullscreen ? WStyle_NoBorder | WStyle_Customize | WStyle_StaysOnTop : 0 ),
00164         modl(modal)
00165         {
00166             pinD = new PinDialog( this );
00167 
00168             if ( fullscreen ) {
00169                 QRect desk = oApp->desktop()->geometry();
00170                 setGeometry( 0, 0, desk.width(), desk.height() );
00171             }
00172 
00173             connect( pinD, SIGNAL(passwordEntered(const QString&)),
00174                      this, SLOT(accept()) );
00175             connect( pinD, SIGNAL(skip()), this, SLOT(accept()) );
00176         }
00177 
00178         void resizeEvent( QResizeEvent * )
00179         {
00180             pinD->resize( size() );
00181         }
00182 
00183         void reset()
00184         {
00185             pinD->clear();
00186         }
00187 
00189         void accept()
00190         {
00191             if ( !modl )
00192                 oApp->exit_loop();
00193             QDialog::accept();
00194         }
00195 
00196         PinDialog *pinD;
00197         bool modl;
00198 };
00199 
00201 QString PinPlugin::encrypt(const QString& pin)
00202 {
00203     // the salt must begin by "$1$" if we want crypt() to use MD5
00204     char salt[] = "$1$........";
00205     const char *const seedchars = "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
00206     // initialize the random generator
00207     srandom(time(0));
00208     int i;
00209     for(i = 0; i < 8; i++)
00210     {
00211         // initialize the salt with random()
00212         salt[i+3] = seedchars[random() % 64];
00213     }
00214     return QString::fromLatin1(crypt(pin.latin1(),salt));
00215 }
00216 
00218 
00221 bool PinPlugin::verify(const QString& pin, const QString& hash)
00222 {
00223     // the hash, which contains the salt (8 chars after "$1$"), can be given as the salt
00224     return hash.compare( QString::fromLatin1(crypt( pin.latin1(), hash.latin1() )) ) == 0 ? true : false;
00225 }
00226 
00228 
00233 QString PinPlugin::getPIN( const QString& prompt )
00234 {
00235     PinDlg pd(0,0,TRUE);
00236     pd.pinD->setPrompt( prompt );
00237 
00238     pd.showMaximized();
00239     int r = pd.exec();
00240 
00241     if ( r == QDialog::Accepted ) {
00242         if (pd.pinD->text.isEmpty())
00243             return "";
00244         else
00245             return pd.pinD->text;
00246     }
00247     else
00248         return QString::null;
00249 }
00250 
00252 
00256 QString PinPlugin::getCryptedPIN( const QString& prompt )
00257 {
00258     return encrypt(getPIN(prompt));
00259 }
00260 
00262 
00265 void PinPlugin::changePIN()
00266 {
00267     QString new1, new2;
00268     do {
00269         new1 = getPIN(QObject::tr("Enter new PIN"));
00270         if ( new1.isNull() )
00271             return;
00272         new2 = getPIN(QObject::tr("Re-enter new PIN"));
00273     } while (new1 != new2);
00274 
00275     odebug << "writing new PIN hash in Security.conf" << oendl;
00276     Config cfg("Security");
00277     cfg.setGroup("PinPlugin");
00278     cfg.writeEntry("hashedPIN", encrypt(new1));
00279 }
00280 
00282 void PinPlugin::clearPIN()
00283 {
00284     Config cfg("Security");
00285     cfg.setGroup("PinPlugin");
00286     cfg.removeEntry("hashedPIN");
00287 }
00288 
00290 
00293 int PinPlugin::authenticate()
00294 {
00295     // reset skip (if we ran Pin two times in a row, skipping the first time, it must be put to 0 again)
00296     isSkip = FALSE;
00297     // fetch value in config
00298     Config cfg("Security");
00299     cfg.setGroup("PinPlugin");
00300     QString hashedPin = cfg.readEntry("hashedPIN");
00301     if (!hashedPin.isEmpty())
00302     {
00303         // prompt for the PIN in a fullscreen modal dialog
00304         PinDlg pd(0,0,TRUE,TRUE);
00305         pd.reset();
00306         pd.exec();
00307 
00308         // analyse the result
00309         if (isSkip == TRUE)
00310             return MultiauthPluginObject::Skip;
00311         else if (verify(pd.pinD->text, hashedPin))
00312             return MultiauthPluginObject::Success;
00313         else
00314             return MultiauthPluginObject::Failure;
00315     }
00316     owarn << "No PIN has been defined! We consider it as a successful authentication though." << oendl;
00317     return MultiauthPluginObject::Success;
00318 }
00319 
00321 PinPlugin::PinPlugin() : MultiauthPluginObject(), m_pinW(0) {
00322 }
00323 
00325 PinPlugin::~PinPlugin() {
00326     if (m_pinW != 0)
00327         delete m_pinW;
00328 }
00329 
00331 QString PinPlugin::pluginName() const {
00332     return "PIN Plugin";
00333 }
00334 
00335 QString PinPlugin::pixmapNameWidget() const {
00336     return "security/pinplugin";
00337 }
00338 
00339 QString PinPlugin::pixmapNameConfig() const {
00340     return "security/pinplugin";
00341 }
00342 
00344 MultiauthConfigWidget * PinPlugin::configWidget(QWidget * parent) {
00345     if (m_pinW == 0) {
00346         m_pinW = new PinConfigWidget(parent, "PIN configuration widget");
00347 
00348         connect(m_pinW->changePIN, SIGNAL( clicked() ), this, SLOT( changePIN() ));
00349         connect(m_pinW->clearPIN, SIGNAL( clicked() ), this, SLOT( clearPIN() ));
00350     }
00351     return m_pinW;
00352 }
00353 
00354 #include "pin.moc"
00355 

Generated on Sat Nov 5 16:17:46 2005 for OPIE by  doxygen 1.4.2