Diffstat (limited to 'core/opie-login/loginapplication.cpp') (more/less context) (ignore whitespace changes)
-rw-r--r-- | core/opie-login/loginapplication.cpp | 193 |
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 | ||
8 | extern "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 | |||
18 | LoginApplication *lApp; | ||
19 | |||
20 | LoginApplication::LoginApplication ( int &argc, char **argv ) | ||
21 | : QPEApplication ( argc, argv, GuiServer ) | ||
22 | { | ||
23 | lApp = this; | ||
24 | } | ||
25 | |||
26 | const char *LoginApplication::s_username = 0; | ||
27 | |||
28 | #ifdef USEPAM | ||
29 | |||
30 | const char *LoginApplication::s_pam_password = 0; | ||
31 | |||
32 | int 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 | |||
70 | bool 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 | |||
89 | bool 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 | |||
122 | bool 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 | |||
150 | bool 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 | |||
164 | const char *LoginApplication::loginAs ( ) | ||
165 | { | ||
166 | return s_username; | ||
167 | } | ||
168 | |||
169 | void LoginApplication::setLoginAs ( const char *name ) | ||
170 | { | ||
171 | s_username = name; | ||
172 | } | ||
173 | |||
174 | QStringList 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 | |||
189 | void LoginApplication::quitToConsole ( ) | ||
190 | { | ||
191 | QPEApplication::quit ( ); | ||
192 | ::kill ( ::getppid ( ), SIGTERM ); | ||
193 | } | ||