1 /* SLiM - Simple Login Manager
2 Copyright (C) 2007 Martin Parm
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
8 */
9 #include <string>
10 #include <iostream>
11 #include "PAM.h"
12
13 namespace PAM {
Exception(pam_handle_t * _pam_handle,const std::string & _func_name,int _errnum)14 Exception::Exception(pam_handle_t* _pam_handle,
15 const std::string& _func_name,
16 int _errnum):
17 errnum(_errnum),
18 errstr(pam_strerror(_pam_handle, _errnum)),
19 func_name(_func_name)
20 {}
21
~Exception(void)22 Exception::~Exception(void){}
23
Auth_Exception(pam_handle_t * _pam_handle,const std::string & _func_name,int _errnum)24 Auth_Exception::Auth_Exception(pam_handle_t* _pam_handle,
25 const std::string& _func_name,
26 int _errnum):
27 Exception(_pam_handle, _func_name, _errnum){}
28
Cred_Exception(pam_handle_t * _pam_handle,const std::string & _func_name,int _errnum)29 Cred_Exception::Cred_Exception(pam_handle_t* _pam_handle,
30 const std::string& _func_name,
31 int _errnum):
32 Exception(_pam_handle, _func_name, _errnum){}
33
_end(void)34 int Authenticator::_end(void){
35 int result=pam_end(pam_handle, last_result);
36 pam_handle=0;
37 return result;
38 }
39
Authenticator(conversation * conv,void * data)40 Authenticator::Authenticator(conversation* conv, void* data):
41 pam_handle(0),
42 last_result(PAM_SUCCESS)
43 {
44 pam_conversation.conv=conv;
45 pam_conversation.appdata_ptr=data;
46 }
47
~Authenticator(void)48 Authenticator::~Authenticator(void){
49 if (pam_handle) _end();
50 }
51
start(const std::string & service)52 void Authenticator::start(const std::string& service){
53 switch((last_result=pam_start(service.c_str(), NULL, &pam_conversation, &pam_handle))){
54 default:
55 throw Exception(pam_handle, "pam_start()", last_result);
56
57 case PAM_SUCCESS:
58 break;
59 }
60 return;
61 }
62
end(void)63 void Authenticator::end(void){
64 switch((last_result=_end())){
65 default:
66 throw Exception(pam_handle, "pam_end()", last_result);
67
68 case PAM_SUCCESS:
69 break;
70 }
71 return;
72 }
73
set_item(const Authenticator::ItemType item,const void * value)74 void Authenticator::set_item(const Authenticator::ItemType item, const void* value){
75 switch((last_result=pam_set_item(pam_handle, item, value))){
76 default:
77 _end();
78 throw Exception(pam_handle, "pam_set_item()", last_result);
79
80 case PAM_SUCCESS:
81 break;
82 }
83 return;
84 }
85
get_item(const Authenticator::ItemType item)86 const void* Authenticator::get_item(const Authenticator::ItemType item){
87 const void* data;
88 switch ((last_result=pam_get_item(pam_handle, item, &data))){
89 default:
90 case PAM_SYSTEM_ERR:
91 #ifdef __LIBPAM_VERSION
92 case PAM_BAD_ITEM:
93 #endif
94 _end();
95 throw Exception(pam_handle, "pam_get_item()", last_result);
96
97 case PAM_PERM_DENIED: /* The value of item was NULL */
98 case PAM_SUCCESS:
99 break;
100 }
101 return data;
102 }
103
104 #ifdef __LIBPAM_VERSION
fail_delay(const unsigned int micro_sec)105 void Authenticator::fail_delay(const unsigned int micro_sec){
106 switch((last_result=pam_fail_delay(pam_handle, micro_sec))){
107 default:
108 _end();
109 throw Exception(pam_handle, "fail_delay()", last_result);
110
111 case PAM_SUCCESS:
112 break;
113 }
114 return;
115 }
116 #endif
117
authenticate(void)118 void Authenticator::authenticate(void){
119 switch((last_result=pam_authenticate(pam_handle, 0))){
120 default:
121 case PAM_ABORT:
122 case PAM_AUTHINFO_UNAVAIL:
123 _end();
124 throw Exception(pam_handle, "pam_authenticate()", last_result);
125
126 case PAM_USER_UNKNOWN:
127 case PAM_MAXTRIES:
128 case PAM_CRED_INSUFFICIENT:
129 case PAM_AUTH_ERR:
130 case PAM_CONV_ERR:
131 throw Auth_Exception(pam_handle, "pam_authentication()", last_result);
132
133 case PAM_SUCCESS:
134 break;
135 }
136
137 switch((last_result=pam_acct_mgmt(pam_handle, PAM_SILENT))){
138 /* The documentation and implementation of Linux PAM differs:
139 PAM_NEW_AUTHTOKEN_REQD is described in the documentation but
140 don't exists in the actual implementation. This issue needs
141 to be fixes at some point. */
142
143 default:
144 /* case PAM_NEW_AUTHTOKEN_REQD: */
145 case PAM_ACCT_EXPIRED:
146 case PAM_USER_UNKNOWN:
147 _end();
148 throw Exception(pam_handle, "pam_acct_mgmt()", last_result);
149
150 case PAM_AUTH_ERR:
151 case PAM_PERM_DENIED:
152 throw Auth_Exception(pam_handle, "pam_acct_mgmt()", last_result);
153
154 case PAM_SUCCESS:
155 break;
156 };
157 return;
158 }
159
open_session(void)160 void Authenticator::open_session(void){
161 switch((last_result=pam_setcred(pam_handle, PAM_ESTABLISH_CRED))){
162 default:
163 case PAM_CRED_ERR:
164 case PAM_CRED_UNAVAIL:
165 _end();
166 throw Exception(pam_handle, "pam_setcred()", last_result);
167
168 case PAM_CRED_EXPIRED:
169 case PAM_USER_UNKNOWN:
170 throw Cred_Exception(pam_handle, "pam_setcred()", last_result);
171
172 case PAM_SUCCESS:
173 break;
174 }
175
176 switch((last_result=pam_open_session(pam_handle, 0))){
177 /* The documentation and implementation of Linux PAM differs:
178 PAM_SESSION_ERROR is described in the documentation but
179 don't exists in the actual implementation. This issue needs
180 to be fixes at some point. */
181
182 default:
183 /* case PAM_SESSION_ERROR: */
184 pam_setcred(pam_handle, PAM_DELETE_CRED);
185 _end();
186 throw Exception(pam_handle, "pam_open_session()", last_result);
187
188 case PAM_SUCCESS:
189 break;
190 };
191 return;
192 }
193
close_session(void)194 void Authenticator::close_session(void){
195 switch((last_result=pam_close_session(pam_handle, 0))){
196 /* The documentation and implementation of Linux PAM differs:
197 PAM_SESSION_ERROR is described in the documentation but
198 don't exists in the actual implementation. This issue needs
199 to be fixes at some point. */
200
201 default:
202 /* case PAM_SESSION_ERROR: */
203 pam_setcred(pam_handle, PAM_DELETE_CRED);
204 _end();
205 throw Exception(pam_handle, "pam_close_session", last_result);
206
207 case PAM_SUCCESS:
208 break;
209 };
210 switch((last_result=pam_setcred(pam_handle, PAM_DELETE_CRED))){
211 default:
212 case PAM_CRED_ERR:
213 case PAM_CRED_UNAVAIL:
214 case PAM_CRED_EXPIRED:
215 case PAM_USER_UNKNOWN:
216 _end();
217 throw Exception(pam_handle, "pam_setcred()", last_result);
218
219 case PAM_SUCCESS:
220 break;
221 }
222 return;
223 }
224
setenv(const std::string & key,const std::string & value)225 void Authenticator::setenv(const std::string& key, const std::string& value){
226 std::string name_value = key+"="+value;
227 switch((last_result=pam_putenv(pam_handle, name_value.c_str()))){
228 default:
229 case PAM_PERM_DENIED:
230 case PAM_ABORT:
231 case PAM_BUF_ERR:
232 #ifdef __LIBPAM_VERSION
233 case PAM_BAD_ITEM:
234 #endif
235 _end();
236 throw Exception(pam_handle, "pam_putenv()", last_result);
237
238 case PAM_SUCCESS:
239 break;
240 };
241 return;
242 }
243
delenv(const std::string & key)244 void Authenticator::delenv(const std::string& key){
245 switch((last_result=pam_putenv(pam_handle, key.c_str()))){
246 default:
247 case PAM_PERM_DENIED:
248 case PAM_ABORT:
249 case PAM_BUF_ERR:
250 #ifdef __LIBPAM_VERSION
251 case PAM_BAD_ITEM:
252 #endif
253 _end();
254 throw Exception(pam_handle, "pam_putenv()", last_result);
255
256 case PAM_SUCCESS:
257 break;
258 };
259 return;
260 }
261
getenv(const std::string & key)262 const char* Authenticator::getenv(const std::string& key){
263 return pam_getenv(pam_handle, key.c_str());
264 }
265
getenvlist(void)266 char** Authenticator::getenvlist(void){
267 return pam_getenvlist(pam_handle);
268 }
269 }
270
operator <<(std::ostream & os,const PAM::Exception & e)271 std::ostream& operator<<( std::ostream& os, const PAM::Exception& e){
272 os << e.func_name << ": " << e.errstr;
273 return os;
274 }
275