summaryrefslogtreecommitdiff
path: root/core/opie-login/loginwindowimpl.cpp
Unidiff
Diffstat (limited to 'core/opie-login/loginwindowimpl.cpp') (more/less context) (ignore whitespace changes)
-rw-r--r--core/opie-login/loginwindowimpl.cpp323
1 files changed, 323 insertions, 0 deletions
diff --git a/core/opie-login/loginwindowimpl.cpp b/core/opie-login/loginwindowimpl.cpp
new file mode 100644
index 0000000..3265b46
--- a/dev/null
+++ b/core/opie-login/loginwindowimpl.cpp
@@ -0,0 +1,323 @@
1#include <qapplication.h>
2#include <qpushbutton.h>
3#include <qlayout.h>
4#include <qframe.h>
5#include <qlineedit.h>
6#include <qtimer.h>
7#include <qcombobox.h>
8#include <qpixmap.h>
9#include <qlabel.h>
10#include <qpopupmenu.h>
11#include <qmessagebox.h>
12
13#include <qpe/qcopenvelope_qws.h>
14
15#include <opie/odevice.h>
16
17#include <stdio.h>
18
19#include <pwd.h>
20#include <grp.h>
21#include <unistd.h>
22#include <stdlib.h>
23
24#ifdef USEPAM
25extern "C" {
26#include <security/pam_appl.h>
27}
28#else
29#include <crypt.h>
30#include <shadow.h>
31#endif
32
33#include "loginwindowimpl.h"
34#include "inputmethods.h"
35
36LoginWindowImpl::LoginWindowImpl ( ) : LoginWindow ( 0, "LOGIN-WINDOW", WStyle_Customize | WStyle_NoBorder | WDestructiveClose )
37{
38 QPopupMenu *pop = new QPopupMenu ( this );
39 pop-> insertItem ( tr( "Restart" ), this, SLOT( restart ( )));
40 m_menu-> setPopup ( pop );
41
42 QHBoxLayout *lay = new QHBoxLayout ( m_taskbar, 4, 4 );
43 m_input = new InputMethods ( m_taskbar );
44 lay-> addWidget ( m_input );
45 lay-> addStretch ( 10 );
46
47 setActiveWindow ( );
48 m_password-> setFocus ( );
49
50 m_user-> insertStringList ( getAllUsers ( ));
51
52 QTimer::singleShot ( 0, this, SLOT( showIM ( )));
53
54 QString opiedir = ::getenv ( "OPIEDIR" );
55 QPixmap bgpix ( opiedir + "/pics/launcher/opie-background.jpg" );
56
57 if ( !bgpix. isNull ( ))
58 setBackgroundPixmap ( bgpix );
59
60 m_caption-> setText ( m_caption-> text ( ) + tr( "<center><h1><u>%1 %2</u></h1></center>" ). arg ( ODevice::inst ( )-> systemString ( )). arg ( ODevice::inst ( )-> systemVersionString ( )));
61}
62
63LoginWindowImpl::~LoginWindowImpl ( )
64{
65}
66
67void LoginWindowImpl::keyPressEvent ( QKeyEvent *e )
68{
69 switch ( e-> key ( )) {
70 case Key_F34: suspend ( );
71 break;
72 case Key_F35: backlight ( );
73 break;
74 default : e-> ignore ( );
75 break;
76 }
77 LoginWindow::keyPressEvent ( e );
78}
79
80
81void LoginWindowImpl::toggleEchoMode ( bool t )
82{
83 m_password-> setEchoMode ( t ? QLineEdit::Normal : QLineEdit::Password );
84}
85
86QStringList LoginWindowImpl::getAllUsers ( )
87{
88 struct passwd *pwd;
89 QStringList sl;
90
91 while (( pwd = getpwent ( ))) {
92 if (( pwd-> pw_uid == 0 ) || ( pwd-> pw_uid >= 500 && pwd-> pw_uid < 65534 ))
93 sl << QString ( pwd-> pw_name );
94 }
95
96 endpwent ( );
97
98 return sl;
99}
100
101void LoginWindowImpl::showIM ( )
102{
103 m_input-> showInputMethod ( );
104}
105
106void LoginWindowImpl::restart ( )
107{
108 qApp-> quit ( );
109}
110
111void LoginWindowImpl::suspend ( )
112{
113 system ( "apm -s" );
114 usleep ( 1 * 1000 * 1000 );
115 {
116 QCopEnvelope e("QPE/System", "setBacklight(int)");
117 e << -3; // Force on
118 }
119}
120
121void LoginWindowImpl::backlight ( )
122{
123 {
124 QCopEnvelope e("QPE/System", "setBacklight(int)");
125 e << -2; // toggle
126 }
127}
128
129#ifdef USEPAM
130
131static const char *_PAM_SERVICE = "xdm";
132static const char *PAM_password;
133
134typedef const struct pam_message pam_message_type;
135
136static int PAM_conv( int, pam_message_type **, struct pam_response **, void * );
137
138static struct pam_conv PAM_conversation = {
139 &PAM_conv,
140 NULL
141};
142
143//----------------------------------------------------------------------------
144
145static char *COPY_STRING( const char * s ) {
146 return (s) ? strdup(s) : (char *)NULL;
147}
148
149#define GET_MEM if (reply) realloc(reply, size);\
150 else reply = (struct pam_response *)malloc(size); \
151 if (!reply) return PAM_CONV_ERR; \
152 size += sizeof(struct pam_response)
153
154
155static int PAM_conv( int num_msg, pam_message_type **msg,
156 struct pam_response **resp, void *)
157{
158 int count = 0, replies = 0;
159 struct pam_response *reply = NULL;
160 int size = sizeof(struct pam_response);
161
162 for( count = 0; count < num_msg; count++ ) {
163 switch (msg[count]->msg_style) {
164 case PAM_PROMPT_ECHO_ON:
165 /* user name given to PAM already */
166 return PAM_CONV_ERR;
167
168 case PAM_PROMPT_ECHO_OFF:
169 /* wants password */
170 GET_MEM;
171 reply[replies].resp_retcode = PAM_SUCCESS;
172 reply[replies].resp = COPY_STRING(PAM_password);
173 replies++;
174 /* PAM frees resp */
175 break;
176 case PAM_TEXT_INFO:
177 break;
178 default:
179 /* unknown or PAM_ERROR_MSG */
180 if (reply) free (reply);
181 return PAM_CONV_ERR;
182 }
183 }
184 if (reply) *resp = reply;
185 return PAM_SUCCESS;
186}
187
188
189static bool pwcheck_PAM( const char *user, const char *password )
190{
191 bool pw_correct = false;
192 int pam_error;
193 int pam_return = 0;
194 pam_handle_t *pamh = 0;
195 PAM_password = password;
196
197 pam_error = pam_start( _PAM_SERVICE, user, &PAM_conversation, &pamh );
198 if( pam_error == PAM_SUCCESS ) {
199 pam_error = pam_authenticate( pamh, 0 );
200 if( pam_error == PAM_SUCCESS ) {
201 //-- password correct
202 pw_correct = true;
203 pam_return = PAM_SUCCESS;
204 } else {
205 pam_return = pam_error;
206 }
207 } else {
208 // cerr << "PAM error: " << pam_strerror( pamh, pam_error ) << endl;
209 }
210 pam_end( pamh, pam_return );
211 return pw_correct;
212}
213
214#else
215
216//----------------------------------------------------------------------------
217
218static bool pwcheck_Unix( const char *user, const char *pass )
219{
220 char *encrypted, *correct;
221 struct passwd *pw;
222
223 if ( !user || !pass )
224 return false;
225
226 pw = getpwnam ( user );
227
228 if ( !pw )
229 return false;
230
231 if (( strcmp ( pw-> pw_passwd, "x" ) == 0 ) || ( strcmp ( pw-> pw_passwd, "*" ) == 0 )) {
232 struct spwd *sp = getspnam ( pw-> pw_name );
233
234 if ( !sp )
235 return false;
236
237 correct = sp-> sp_pwdp;
238 }
239 else
240 correct = pw-> pw_passwd;
241
242 if ( correct == 0 || correct[0] == '\0' )
243 return true;
244
245 encrypted = crypt ( pass, correct );
246 return ( strcmp ( encrypted, correct ) == 0 );
247}
248
249#endif
250
251
252bool LoginWindowImpl::changeIdentity ( const char *user )
253{
254 const char *DEFAULT_LOGIN_PATH = "/bin:/usr/bin";
255 const char *DEFAULT_ROOT_LOGIN_PATH = "/usr/sbin:/bin:/usr/bin:/sbin";
256
257 bool fail = false;
258 struct passwd *pw = getpwnam ( user );
259
260 fail |= ( pw == 0 );
261 printf ( "1 %d\n", fail );
262 fail |= ( initgroups ( pw-> pw_name, pw-> pw_gid ));
263 endgrent ( );
264 printf ( "2 %d\n", fail );
265 fail |= ( setgid ( pw-> pw_gid ));
266 printf ( "3 %d\n", fail );
267 fail |= ( setuid ( pw-> pw_uid ));
268
269 printf ( "4 %d\n", fail );
270 fail |= ( chdir ( pw-> pw_dir ) && chdir ( "/" ));
271
272 printf ( "5 %d\n", fail );
273 fail |= ( setenv ( "HOME", pw-> pw_dir, 1 ));
274 printf ( "6 %d\n", fail );
275 fail |= ( setenv ( "SHELL", pw-> pw_shell, 1 ));
276 printf ( "7 %d\n", fail );
277 fail |= ( setenv ( "USER", pw-> pw_name, 1 ));
278 printf ( "8 %d\n", fail );
279 fail |= ( setenv ( "LOGNAME", pw-> pw_name, 1 ));
280 printf ( "9 %d\n", fail );
281 fail |= ( setenv ( "PATH", ( pw-> pw_uid ? DEFAULT_LOGIN_PATH : DEFAULT_ROOT_LOGIN_PATH ), 1 ));
282 printf ( "10 %d\n", fail );
283
284 return !fail;
285}
286
287void LoginWindowImpl::login ( )
288{
289 const char *user = strdup ( m_user-> currentText ( ). local8Bit ( ));
290 const char *pass = strdup ( m_password-> text ( ). local8Bit ( ));
291 bool ok;
292
293 if ( !user || !user [0] )
294 return;
295 if ( !pass )
296 pass = "";
297
298#if defined( USEPAM )
299 ok = pwcheck_PAM ( user, pass );
300#else
301 ok = pwcheck_Unix ( user, pass );
302#endif
303
304 if ( ok ) {
305 if ( changeIdentity ( user )) {
306 QString opie = getenv ( "OPIEDIR" );
307 opie += "/bin/qpe";
308
309 execl ( opie. latin1 ( ), "qpe", 0 );
310
311 QMessageBox::critical ( this, tr( "Failure" ), tr( "Could not start OPIE." ));
312 restart ( );
313 }
314 else {
315 QMessageBox::critical ( this, tr( "Failure" ), tr( "Could not switch to new user identity" ));
316 restart ( );
317 }
318 }
319 else {
320 QMessageBox::warning ( this, tr( "Wrong password" ), tr( "The given password is incorrect." ));
321 m_password-> clear ( );
322 }
323}