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