Diffstat (limited to 'core/opie-login/passworddialogimpl.cpp') (more/less context) (ignore whitespace changes)
-rw-r--r-- | core/opie-login/passworddialogimpl.cpp | 232 |
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'. | ||
49 | static 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'. | ||
64 | static 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 | */ | ||
82 | PasswordDialogImpl::PasswordDialogImpl( QWidget* parent ) | ||
83 | : PasswordDialog( parent, 0, true ), m_isSet( PasswordDialogImpl::needDialog() ) { | ||
84 | } | ||
85 | |||
86 | PasswordDialogImpl::~PasswordDialogImpl() { | ||
87 | /* qt does the stuff for us */ | ||
88 | } | ||
89 | |||
90 | void 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 | */ | ||
128 | void 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 | */ | ||
175 | void 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 | |||
186 | void 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 | */ | ||
199 | bool 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 | } | ||