You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

274 lines
6.6 KiB

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