summaryrefslogtreecommitdiff
path: root/core/opie-login/passworddialogimpl.cpp
Unidiff
Diffstat (limited to 'core/opie-login/passworddialogimpl.cpp') (more/less context) (ignore whitespace changes)
-rw-r--r--core/opie-login/passworddialogimpl.cpp232
1 files changed, 232 insertions, 0 deletions
diff --git a/core/opie-login/passworddialogimpl.cpp b/core/opie-login/passworddialogimpl.cpp
new file mode 100644
index 0000000..aeb7516
--- a/dev/null
+++ b/core/opie-login/passworddialogimpl.cpp
@@ -0,0 +1,232 @@
1/*
2               =. This file is part of the OPIE Project
3             .=l. Copyright (c) 2004 Holger Hans Peter Freyther <zecke@handhelds.org>
4           .>+-=
5 _;:,     .>    :=|. This file is free software; you can
6.> <`_,   >  .   <= redistribute it and/or modify it under
7:`=1 )Y*s>-.--   : the terms of the GNU General Public
8.="- .-=="i,     .._ License as published by the Free Software
9 - .   .-<_>     .<> Foundation; either version 2 of the License,
10     ._= =}       : or (at your option) any later version.
11    .%`+i>       _;_.
12    .i_,=:_.      -<s. This file is distributed in the hope that
13     +  .  -:.       = it will be useful, but WITHOUT ANY WARRANTY;
14    : ..    .:,     . . . without even the implied warranty of
15    =_        +     =;=|` MERCHANTABILITY or FITNESS FOR A
16  _.=:.       :    :=>`: PARTICULAR PURPOSE. See the GNU General
17..}^=.=       =       ; Public License for more details.
18++=   -.     .`     .:
19 :     =  ...= . :.=- You should have received a copy of the GNU
20 -.   .:....=;==+<; General Public License along with this file;
21  -_. . .   )=.  = see the file COPYING. If not, write to the
22    --        :-=` Free Software Foundation, Inc.,
23 59 Temple Place - Suite 330,
24 Boston, MA 02111-1307, USA.
25
26*/
27
28
29#include <qlayout.h>
30#include <qlabel.h>
31#include <qlineedit.h>
32#include <qvalidator.h>
33#include <qmessagebox.h>
34#include <qhbox.h>
35#include <qtoolbutton.h>
36
37#include <sys/types.h>
38#include <pwd.h>
39#include <shadow.h>
40#include <stdio.h>
41#include <time.h>
42#include <unistd.h>
43
44
45#include "passworddialogimpl.h"
46
47
48// This function is taken from 'busybox'.
49static int i64c(int i) {
50 if (i <= 0)
51 return ('.');
52 if (i == 1)
53 return ('/');
54 if (i >= 2 && i < 12)
55 return ('0' - 2 + i);
56 if (i >= 12 && i < 38)
57 return ('A' - 12 + i);
58 if (i >= 38 && i < 63)
59 return ('a' - 38 + i);
60 return ('z');
61}
62
63// This function is taken from 'busybox'.
64static char *crypt_make_salt() {
65 time_t now;
66 static unsigned long x;
67 static char result[3];
68
69 ::time(&now);
70 x += now + getpid() + clock();
71 result[0] = i64c(((x >> 18) ^ (x >> 6)) & 077);
72 result[1] = i64c(((x >> 12) ^ x) & 077);
73 result[2] = '\0';
74 return result;
75}
76
77/*
78 * Modal dialog to force root password. It is quite hard as it only leave
79 * when a password is set.
80 * Also it prevalidates the password...
81 */
82PasswordDialogImpl::PasswordDialogImpl( QWidget* parent )
83 : PasswordDialog( parent, 0, true ), m_isSet( PasswordDialogImpl::needDialog() ) {
84}
85
86PasswordDialogImpl::~PasswordDialogImpl() {
87 /* qt does the stuff for us */
88}
89
90void PasswordDialogImpl::done(int res) {
91 m_isSet = true;
92
93 /*
94 * The user hit 'Ok' see if we can safe the file
95 * if not an error will be raised and m_isSet altered.
96 * On cancel we will see if it is now ok...
97 */
98 if ( res == Accepted )
99 writePassword();
100 else if(PasswordDialogImpl::needDialog() ) {
101 switch( QMessageBox::warning(this,tr("Trying to leave without password set") ,
102 tr("<qt>No password was set. This could lead to you not beeing"
103 "able to remotely connect to your machine."
104 "Do you want to continue not setting a password?</qt>" ),
105 QMessageBox::Ok, QMessageBox::Cancel ) ) {
106 case QMessageBox::Cancel:
107 m_isSet = false;
108 break;
109 case QMessageBox::Ok:
110 default:
111 break;
112 }
113
114 }
115
116 if(m_isSet)
117 PasswordDialog::done( res );
118}
119
120/*
121 * Lets see if we can write either shadow
122 *
123 */
124/**
125 * CRYPT the password and then tries to write it either to the shadow password
126 * or to the plain /etc/passwd
127 */
128void PasswordDialogImpl::writePassword() {
129 /*
130 * Check if both texts are the same
131 */
132 if ( m_pass->text() != m_confirm->text() )
133 return error( tr("Passwords don't match"),
134 tr("<qt>The two passwords don't match. Please try again.</qt>") );
135
136
137 /*
138 * Now crypt the password so we can write it later
139 */
140 char* password = ::crypt( m_pass->text().latin1(), crypt_make_salt() );
141
142 if ( !password )
143 return error( tr("Password not legal" ),
144 tr("<qt>The entered password is not a valid password."
145 "Please try entering a valid password.</qt>" ) );
146
147 /* rewind and rewrite the password file */
148 ::setpwent();
149
150 FILE* file = ::fopen( "/etc/passwd.new", "w" );
151 struct passwd* pass;
152 while ( (pass = ::getpwent()) != 0l ) {
153 /* no shadow password support */
154 if ( pass->pw_uid == 0 )
155 pass->pw_passwd = password;
156
157 ::putpwent( pass, file );
158 }
159
160 ::fclose( file );
161 ::endpwent();
162 ::unlink("/etc/passwd");
163 ::rename("/etc/passwd.new","/etc/passwd" );
164
165 /* should be done now */
166#ifdef OPIE_LOGIN_SHADOW_PW
167 #error "Can't write Shadow Passwords fixme"
168#endif
169}
170
171/**
172 * Raise an error. Delete input and set the focus after showing
173 * the error to the user
174 */
175void PasswordDialogImpl::error( const QString& caption, const QString& text ) {
176 m_isSet = false;
177 QMessageBox::critical(this,caption, text,
178 QMessageBox::Ok, QMessageBox::NoButton );
179
180 m_pass->setText("");
181 m_pass->setFocus();
182
183 m_confirm->setText("");
184}
185
186void PasswordDialogImpl::slotToggleEcho( bool b ) {
187 m_pass-> setEchoMode( b ? QLineEdit::Normal : QLineEdit::Password );
188 m_confirm->setEchoMode( b ? QLineEdit::Normal : QLineEdit::Password );
189}
190
191/////////////////////////
192/// static functions
193///
194
195/**
196 * Ask whether or not we need to show the dialog. It returns true if
197 * no root password is set so that the user will be able to set one.
198 */
199bool PasswordDialogImpl::needDialog() {
200 /*
201 * This can cope with no password and shadow passwords
202 * Let us go through the user database until we find 'root' and then
203 * see if it is 'shadow' and see if shadow is empty or see if the password is empty
204 */
205 bool need = false;
206 struct passwd *pwd;
207 ::setpwent();
208
209 while((pwd = ::getpwent() ) ) {
210 /* found root */
211 if( pwd->pw_uid == 0 ) {
212 QString str = QString::fromLatin1(pwd->pw_passwd );
213
214 /*
215 * If str is really empty it is passwordless anyway...
216 * else it is shadow based
217 */
218 if(str.isEmpty() )
219 need = true;
220 else if ( str == '*' || str == 'x' )
221#ifdef OPIE_LOGIN_SHADOW_PW
222 need = QString::fromLatin1( ::getspnam( pwd->pw_name )->sp_pwdp ).isEmpty();
223#else
224 ;
225#endif
226 break;
227 }
228 }
229 ::endpwent();
230
231 return need;
232}