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