summaryrefslogtreecommitdiff
path: root/core/opie-login/loginapplication.cpp
Unidiff
Diffstat (limited to 'core/opie-login/loginapplication.cpp') (more/less context) (show whitespace changes)
-rw-r--r--core/opie-login/loginapplication.cpp193
1 files changed, 193 insertions, 0 deletions
diff --git a/core/opie-login/loginapplication.cpp b/core/opie-login/loginapplication.cpp
new file mode 100644
index 0000000..cd58c47
--- a/dev/null
+++ b/core/opie-login/loginapplication.cpp
@@ -0,0 +1,193 @@
1#include <pwd.h>
2#include <grp.h>
3#include <unistd.h>
4#include <stdlib.h>
5#include <signal.h>
6
7#ifdef USEPAM
8extern "C" {
9#include <security/pam_appl.h>
10}
11#else
12#include <crypt.h>
13#include <shadow.h>
14#endif
15
16#include "loginapplication.h"
17
18LoginApplication *lApp;
19
20LoginApplication::LoginApplication ( int &argc, char **argv )
21 : QPEApplication ( argc, argv, GuiServer )
22{
23 lApp = this;
24}
25
26const char *LoginApplication::s_username = 0;
27
28#ifdef USEPAM
29
30const char *LoginApplication::s_pam_password = 0;
31
32int LoginApplication::pam_helper ( int num_msg, const struct pam_message **msg, struct pam_response **resp, void * )
33{
34 int replies = 0;
35 struct pam_response *reply = 0;
36 int size = sizeof( struct pam_response );
37
38 for ( int i = 0; i < num_msg; i++ ) {
39 switch ( msg [i]-> msg_style ) {
40 case PAM_PROMPT_ECHO_ON: // user name given to PAM already
41 return PAM_CONV_ERR;
42
43 case PAM_PROMPT_ECHO_OFF: // wants password
44 reply = (struct pam_response *) ::realloc ( reply, size );
45 if ( !reply )
46 return PAM_CONV_ERR;
47 size += sizeof( struct pam_response );
48
49 reply [replies]. resp_retcode = PAM_SUCCESS;
50 reply [replies]. resp = ::strdup ( s_pam_password );
51 replies++; // PAM frees resp
52 break;
53
54 case PAM_TEXT_INFO:
55 break;
56
57 default:
58 /* unknown or PAM_ERROR_MSG */
59 if ( reply )
60 ::free ( reply );
61 return PAM_CONV_ERR;
62 }
63 }
64 if ( reply )
65 *resp = reply;
66 return PAM_SUCCESS;
67}
68
69
70bool LoginApplication::checkPassword ( const char *user, const char *pass )
71{
72 static struct pam_conv conv = { &LoginApplication::pam_helper, 0 };
73
74 int pam_error;
75 pam_handle_t *pamh = 0;
76
77 pam_error = ::pam_start( "xdm", user, &conv, &pamh );
78 if ( pam_error == PAM_SUCCESS ) {
79 s_pam_password = pass;
80 pam_error = ::pam_authenticate ( pamh, 0 );
81 s_pam_password = 0;
82 }
83 ::pam_end ( pamh, pam_error );
84 return ( pam_error == PAM_SUCCESS );
85}
86
87#else
88
89bool LoginApplication::checkPassword ( const char *user, const char *pass )
90{
91 char *encrypted, *correct;
92 struct passwd *pw;
93
94 if ( !user || !pass )
95 return false;
96
97 pw = ::getpwnam ( user );
98
99 if ( !pw )
100 return false;
101
102 if (( ::strcmp ( pw-> pw_passwd, "x" ) == 0 ) || ( ::strcmp ( pw-> pw_passwd, "*" ) == 0 )) {
103 struct spwd *sp = ::getspnam ( pw-> pw_name );
104
105 if ( !sp )
106 return false;
107
108 correct = sp-> sp_pwdp;
109 }
110 else
111 correct = pw-> pw_passwd;
112
113 if ( correct == 0 || correct[0] == '\0' )
114 return true;
115
116 encrypted = ::crypt ( pass, correct );
117 return ( ::strcmp ( encrypted, correct ) == 0 );
118}
119
120#endif
121
122bool LoginApplication::changeIdentity ( )
123{
124 const char *DEFAULT_LOGIN_PATH = "/bin:/usr/bin";
125 const char *DEFAULT_ROOT_LOGIN_PATH = "/usr/sbin:/bin:/usr/bin:/sbin";
126
127 if ( !s_username )
128 return false;
129 struct passwd *pw = ::getpwnam ( s_username );
130 if ( !pw )
131 return false;
132
133 bool fail = false;
134 fail |= ( ::initgroups ( pw-> pw_name, pw-> pw_gid ));
135 ::endgrent ( );
136 fail |= ( ::setgid ( pw-> pw_gid ));
137 fail |= ( ::setuid ( pw-> pw_uid ));
138
139 fail |= ( ::chdir ( pw-> pw_dir ) && ::chdir ( "/" ));
140
141 fail |= ( ::setenv ( "HOME", pw-> pw_dir, 1 ));
142 fail |= ( ::setenv ( "SHELL", pw-> pw_shell, 1 ));
143 fail |= ( ::setenv ( "USER", pw-> pw_name, 1 ));
144 fail |= ( ::setenv ( "LOGNAME", pw-> pw_name, 1 ));
145 fail |= ( ::setenv ( "PATH", ( pw-> pw_uid ? DEFAULT_LOGIN_PATH : DEFAULT_ROOT_LOGIN_PATH ), 1 ));
146
147 return !fail;
148}
149
150bool LoginApplication::login ( )
151{
152 char *opie = ::getenv ( "OPIEDIR" );
153 char *arg = new char [::strlen ( opie ) + 8 + 1];
154
155 ::strcpy ( arg, opie );
156 ::strcat ( arg, "/bin/qpe" );
157
158 // start qpe via a login shell
159 ::execl ( "/bin/sh", "-sh", "-c", arg, 0 );
160
161 return false;
162}
163
164const char *LoginApplication::loginAs ( )
165{
166 return s_username;
167}
168
169void LoginApplication::setLoginAs ( const char *name )
170{
171 s_username = name;
172}
173
174QStringList LoginApplication::allUsers ( )
175{
176 struct passwd *pwd;
177 QStringList sl;
178
179 while (( pwd = ::getpwent ( ))) {
180 if (( pwd-> pw_uid == 0 ) || ( pwd-> pw_uid >= 500 && pwd-> pw_uid < 65534 ))
181 sl << QString ( pwd-> pw_name );
182 }
183
184 ::endpwent ( );
185
186 return sl;
187}
188
189void LoginApplication::quitToConsole ( )
190{
191 QPEApplication::quit ( );
192 ::kill ( ::getppid ( ), SIGTERM );
193}