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

passworddialogimpl.cpp

Go to the documentation of this file.
00001 /*
00002                =.            This file is part of the OPIE Project
00003              .=l.            Copyright (c)  2004 Holger Hans Peter Freyther <zecke@handhelds.org>
00004            .>+-=
00005  _;:,     .>    :=|.         This file is free software; you can
00006 .> <`_,   >  .   <=          redistribute it and/or modify it under
00007 :`=1 )Y*s>-.--   :           the terms of the GNU General Public
00008 .="- .-=="i,     .._         License as published by the Free Software
00009  - .   .-<_>     .<>         Foundation; either version 2 of the License,
00010      ._= =}       :          or (at your option) any later version.
00011     .%`+i>       _;_.
00012     .i_,=:_.      -<s.       This file is distributed in the hope that
00013      +  .  -:.       =       it will be useful, but WITHOUT ANY WARRANTY;
00014     : ..    .:,     . . .    without even the implied warranty of
00015     =_        +     =;=|`    MERCHANTABILITY or FITNESS FOR A
00016   _.=:.       :    :=>`:     PARTICULAR PURPOSE. See the GNU General
00017 ..}^=.=       =       ;      Public License for more details.
00018 ++=   -.     .`     .:
00019  :     =  ...= . :.=-        You should have received a copy of the GNU
00020  -.   .:....=;==+<;          General Public License along with this file;
00021   -_. . .   )=.  =           see the file COPYING. If not, write to the
00022     --        :-=`           Free Software Foundation, Inc.,
00023                              59 Temple Place - Suite 330,
00024                              Boston, MA 02111-1307, USA.
00025 
00026 */
00027 
00028 #include <qlayout.h>
00029 #include <qlabel.h>
00030 #include <qlineedit.h>
00031 #include <qvalidator.h>
00032 #include <qmessagebox.h>
00033 #include <qhbox.h>
00034 #include <qtoolbutton.h>
00035 
00036 
00037 
00038 #include <sys/types.h>
00039 #include <pwd.h>
00040 #include <shadow.h>
00041 #include <stdio.h>
00042 #include <time.h>
00043 #include <unistd.h>
00044 
00045 // Shitty gcc2 toolchain
00046 extern "C" char* crypt( const char*, const char* );
00047 
00048 
00049 
00050 #include "passworddialogimpl.h"
00051 
00052 
00053 // This function is taken from 'busybox'.
00054 static int i64c(int i) {
00055     if (i <= 0)
00056         return ('.');
00057     if (i == 1)
00058         return ('/');
00059     if (i >= 2 && i < 12)
00060         return ('0' - 2 + i);
00061     if (i >= 12 && i < 38)
00062         return ('A' - 12 + i);
00063     if (i >= 38 && i < 63)
00064         return ('a' - 38 + i);
00065     return ('z');
00066 }
00067 
00068 // This function is taken from 'busybox'.
00069 static char *crypt_make_salt() {
00070     time_t now;
00071     static unsigned long x;
00072     static char result[3];
00073 
00074     ::time(&now);
00075     x += now + getpid() + clock();
00076     result[0] = i64c(((x >> 18) ^ (x >> 6)) & 077);
00077     result[1] = i64c(((x >> 12) ^ x) & 077);
00078     result[2] = '\0';
00079     return result;
00080 }
00081 
00082 /*
00083  * Modal dialog to force root password. It is quite hard as it only leave
00084  * when a password is set.
00085  * Also it prevalidates the password...
00086  */
00087 PasswordDialogImpl::PasswordDialogImpl( QWidget* parent )
00088     : PasswordDialog( parent, 0, true ), m_isSet( PasswordDialogImpl::needDialog() ) {
00089 }
00090 
00091 PasswordDialogImpl::~PasswordDialogImpl() {
00092     /* qt does the stuff for us */
00093 }
00094 
00095 void PasswordDialogImpl::done(int res) {
00096     m_isSet = true;
00097 
00098     /*
00099      * The user hit 'Ok' see if we can safe the file
00100      * if not an error will be raised and m_isSet altered.
00101      * On cancel we will see if it is now ok...
00102      */
00103     if ( res == Accepted )
00104         writePassword();
00105     else if(PasswordDialogImpl::needDialog() ) {
00106         switch( QMessageBox::warning(this,tr("Trying to leave without password set") ,
00107                                      tr("<qt>No password was set. This could lead to you not beeing"
00108                                         "able to remotely connect to your machine."
00109                                         "Do you want to continue not setting a password?</qt>" ),
00110                                      QMessageBox::Ok, QMessageBox::Cancel ) ) {
00111         case QMessageBox::Cancel:
00112             m_isSet = false;
00113             break;
00114         case  QMessageBox::Ok:
00115         default:
00116             break;
00117         }
00118 
00119     }
00120 
00121     if(m_isSet)
00122         PasswordDialog::done( res );
00123 }
00124 
00125 /*
00126  * Lets see if we can write either shadow
00127  *
00128  */
00133 void PasswordDialogImpl::writePassword() {
00134     /*
00135      * Check if both texts are the same
00136      */
00137     if ( m_pass->text() != m_confirm->text() )
00138         return error( tr("Passwords don't match"),
00139                       tr("<qt>The two passwords don't match. Please try again.</qt>") );
00140 
00141 
00142     /*
00143      * Now crypt the password so we can write it later
00144      */
00145     char* password = ::crypt( m_pass->text().latin1(), crypt_make_salt() );
00146 
00147     if ( !password )
00148         return error( tr("Password not legal" ),
00149                       tr("<qt>The entered password is not a valid password."
00150                          "Please try entering a valid password.</qt>" ) );
00151 
00152     /* rewind and rewrite the password file */
00153     ::setpwent();
00154 
00155     FILE* file = ::fopen( "/etc/passwd.new", "w" );
00156     struct passwd* pass;
00157     while ( (pass = ::getpwent()) != 0l ) {
00158         /* no  shadow password support */
00159         if ( pass->pw_uid == 0  )
00160             pass->pw_passwd = password;
00161 
00162         ::putpwent( pass, file );
00163     }
00164 
00165     ::fclose( file );
00166     ::endpwent();
00167     ::rename("/etc/passwd.new","/etc/passwd" );
00168 
00169     /* should be done now */
00170 #ifdef  OPIE_LOGIN_SHADOW_PW
00171     #error "Can't write Shadow Passwords fixme"
00172 #endif
00173 }
00174 
00179 void PasswordDialogImpl::error( const QString& caption, const QString& text ) {
00180     m_isSet = false;
00181     QMessageBox::critical(this,caption, text,
00182                           QMessageBox::Ok, QMessageBox::NoButton );
00183 
00184     m_pass->setText("");
00185     m_pass->setFocus();
00186 
00187     m_confirm->setText("");
00188 }
00189 
00190 void PasswordDialogImpl::slotToggleEcho( bool b ) {
00191     m_pass->   setEchoMode( b ? QLineEdit::Normal : QLineEdit::Password );
00192     m_confirm->setEchoMode( b ? QLineEdit::Normal : QLineEdit::Password );
00193 }
00194 
00198 
00203 bool PasswordDialogImpl::needDialog() {
00204    /*
00205     * This can cope with no password and shadow passwords
00206     * Let us go through the user database until we find  'root' and then
00207     * see if it is 'shadow' and see if shadow is empty or see if the password is empty
00208     */
00209     bool need = false;
00210     struct passwd *pwd;
00211     ::setpwent();
00212 
00213     while((pwd = ::getpwent() ) ) {
00214         /* found root */
00215         if( pwd->pw_uid == 0 ) {
00216             QString str = QString::fromLatin1(pwd->pw_passwd );
00217 
00218             /*
00219              * If str is really empty it is passwordless anyway... or '*' is a hint to set one
00220              * on OE/Familiar
00221              * else it is shadow based
00222              */
00223             if(str.isEmpty() || str == '*' )
00224                 need = true;
00225             else if ( str == 'x' )
00226 #ifdef OPIE_LOGIN_SHADOW_PW
00227                 need =  QString::fromLatin1( ::getspnam( pwd->pw_name )->sp_pwdp ).isEmpty();
00228 #else
00229             ;
00230 #endif
00231             break;
00232         }
00233     }
00234     ::endpwent();
00235 
00236     return need;
00237 }

Generated on Sat Nov 5 16:15:45 2005 for OPIE by  doxygen 1.4.2