pam_svc.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461
  1. /*
  2. * CDE - Common Desktop Environment
  3. *
  4. * Copyright (c) 1993-2012, The Open Group. All rights reserved.
  5. *
  6. * These libraries and programs are free software; you can
  7. * redistribute them and/or modify them under the terms of the GNU
  8. * Lesser General Public License as published by the Free Software
  9. * Foundation; either version 2 of the License, or (at your option)
  10. * any later version.
  11. *
  12. * These libraries and programs are distributed in the hope that
  13. * they will be useful, but WITHOUT ANY WARRANTY; without even the
  14. * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
  15. * PURPOSE. See the GNU Lesser General Public License for more
  16. * details.
  17. *
  18. * You should have received a copy of the GNU Lesser General Public
  19. * License along with these libraries and programs; if not, write
  20. * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
  21. * Floor, Boston, MA 02110-1301 USA
  22. */
  23. /* $TOG: pam_svc.c /main/5 1997/06/04 16:30:21 samborn $ */
  24. /*******************************************************************************
  25. **
  26. ** pam_svc.c 1.10 95/11/25
  27. **
  28. ** Copyright 1993, 1994, 1995 Sun Microsystems, Inc. All rights reserved.
  29. **
  30. ** This file contains procedures specific to dtlogin's use of
  31. ** PAM (Pluggable Authentication Module) security library.
  32. **
  33. *******************************************************************************/
  34. /* *
  35. * (c) Copyright 1993, 1994 Hewlett-Packard Company *
  36. * (c) Copyright 1993, 1994 International Business Machines Corp. *
  37. * (c) Copyright 1993, 1994, 1995 Sun Microsystems, Inc. *
  38. * (c) Copyright 1993, 1994 Novell, Inc. *
  39. */
  40. /*
  41. * Header Files
  42. */
  43. #include <utmpx.h>
  44. #include <stdio.h>
  45. #include <string.h>
  46. #include <errno.h>
  47. #include <dirent.h>
  48. #include <sys/param.h>
  49. #include <pwd.h>
  50. #include <security/pam_appl.h>
  51. #include "pam_svc.h"
  52. #include "dm.h"
  53. #include "solaris.h"
  54. /*
  55. * Local function declarations
  56. */
  57. static int login_conv(int num_msg, struct pam_message **msg,
  58. struct pam_response **response, void *appdata_ptr);
  59. static char* create_devname(char* short_devname);
  60. /*
  61. * Local structures and variables
  62. */
  63. static struct pam_conv pam_conv = {login_conv, NULL};
  64. static char *saved_user_passwd;
  65. static pam_handle_t *pamh = NULL;
  66. static int pam_auth_trys = 0;
  67. /****************************************************************************
  68. * PamInit
  69. *
  70. * Initialize or Update PAM datastructures.
  71. *
  72. ****************************************************************************/
  73. int
  74. PamInit(char* prog_name,
  75. char* user,
  76. char* line_dev,
  77. char* display_name)
  78. {
  79. int status=PAM_SUCCESS;
  80. if (!pamh) {
  81. /* Open PAM (Plugable Authentication module ) connection */
  82. status = pam_start( prog_name, user, &pam_conv, &pamh );
  83. if (status != PAM_SUCCESS) {
  84. Debug("PamInit: pam_start error=%d\n", status);
  85. pamh = NULL;
  86. } else {
  87. Debug("PamInit: pam_start success\n");
  88. }
  89. } else {
  90. if (prog_name) pam_set_item(pamh, PAM_SERVICE, prog_name);
  91. if (user) pam_set_item(pamh, PAM_USER, user);
  92. }
  93. if (status == PAM_SUCCESS) {
  94. if (line_dev) pam_set_item(pamh, PAM_TTY, line_dev);
  95. if (display_name) pam_set_item(pamh, PAM_RHOST, display_name);
  96. }
  97. return(status);
  98. }
  99. /****************************************************************************
  100. * PamAuthenticate
  101. *
  102. * Authenticate that user / password combination is legal for this system
  103. *
  104. ****************************************************************************/
  105. int
  106. PamAuthenticate ( char* prog_name,
  107. char* display_name,
  108. char* user_passwd,
  109. char* user,
  110. char* line )
  111. {
  112. int status;
  113. char* user_str = user ? user : "NULL";
  114. char* line_str = line ? line : "NULL";
  115. char* line_dev = create_devname(line_str);
  116. Debug("PamAuthenticate: prog_name=%s\n", prog_name);
  117. Debug("PamAuthenticate: display_name=%s\n", display_name);
  118. Debug("PamAuthenticate: user=%s\n", user_str);
  119. Debug("PamAuthenticate: line=%s\n", line_str);
  120. Debug("PamAuthenticate: line_dev=%s\n", line_dev);
  121. if (user_passwd) {
  122. if (strlen(user_passwd) == 0) {
  123. Debug("PamAuthenticate: user passwd empty\n");
  124. } else {
  125. Debug("PamAuthenticate: user passwd present\n");
  126. }
  127. }
  128. else {
  129. Debug("PamAuthenticate: user passwd NULL\n");
  130. /* Password challenge required for dtlogin authentication */
  131. return(PAM_AUTH_ERR);
  132. }
  133. status = PamInit(prog_name, user, line_dev, display_name);
  134. if (status == PAM_SUCCESS) {
  135. struct passwd *pwd;
  136. saved_user_passwd = user_passwd;
  137. status = pam_authenticate( pamh, 0 );
  138. pam_auth_trys++;
  139. if (status != PAM_SUCCESS) {
  140. sleep(PAM_LOGIN_SLEEPTIME);
  141. if (pam_auth_trys > PAM_LOGIN_MAXTRIES) {
  142. sleep(PAM_LOGIN_DISABLETIME);
  143. }
  144. }
  145. };
  146. if (status != PAM_SUCCESS) {
  147. Debug("PamAuthenticate: PAM error=%d\n", status);
  148. if (pamh) {
  149. Debug("PamAuthenticate: calling pam_end\n");
  150. pam_end(pamh, PAM_ABORT);
  151. pamh=NULL;
  152. }
  153. }
  154. return(status);
  155. }
  156. /****************************************************************************
  157. * PamAccounting
  158. *
  159. * Work related to open and close of user sessions
  160. ****************************************************************************/
  161. int
  162. PamAccounting( char* prog_name,
  163. char* display_name,
  164. char* entry_id,
  165. char* user,
  166. char* line,
  167. pid_t pid,
  168. int entry_type,
  169. int exitcode )
  170. {
  171. int session_type, status;
  172. char *user_str = user ? user : "NULL";
  173. char *line_str = line ? line : "NULL";
  174. char *line_dev = create_devname(line_str);
  175. char *tty_line;
  176. Debug("PamAccounting: prog_name=%s\n", prog_name);
  177. Debug("PamAccounting: display_name=%s\n", display_name);
  178. Debug("PamAccounting: entry_id=%c %c %c %c\n", entry_id[0],
  179. entry_id[1], entry_id[2], entry_id[3]);
  180. Debug("PamAccounting: user=%s\n", user_str);
  181. Debug("PamAccounting: line=%s\n", line_str);
  182. Debug("PamAccounting: line_dev=%s\n", line_dev);
  183. Debug("PamAccounting: pid=%d\n", pid);
  184. Debug("PamAccounting: entry_type=%d\n", entry_type);
  185. Debug("PamAccounting: exitcode=%d\n", exitcode);
  186. /* Open Solaris PAM (Plugable Authentication module ) connection */
  187. if (entry_type == ACCOUNTING) {
  188. tty_line = line;
  189. }
  190. else {
  191. tty_line = line_dev;
  192. }
  193. status = PamInit(prog_name, user, tty_line, display_name);
  194. /* Session accounting */
  195. if (status == PAM_SUCCESS) switch(entry_type) {
  196. case USER_PROCESS:
  197. /* New user session, open session accounting logs */
  198. status = pam_open_session(pamh, 0);
  199. if (status != PAM_SUCCESS) {
  200. Debug("PamAccounting: USER_PROCESS open_session error=%d\n",
  201. status);
  202. }
  203. session_type = SOLARIS_LOGIN;
  204. status = solaris_setutmp_mgmt(user, tty_line, display_name,
  205. session_type, entry_type, entry_id);
  206. if (status != SOLARIS_SUCCESS) {
  207. Debug("PamAccounting: USER_PRCESS set_utmp error=%d\n",
  208. status);
  209. }
  210. break;
  211. case ACCOUNTING:
  212. /*
  213. * User session has terminated, mark it DEAD and close
  214. * the sessions accounting logs.
  215. */
  216. status = pam_open_session(pamh, 0);
  217. if (status != PAM_SUCCESS) {
  218. Debug("PamAccounting: ACCOUNTING open_session error=%d\n",
  219. status);
  220. }
  221. entry_type = DEAD_PROCESS;
  222. session_type = SOLARIS_NOLOG;
  223. status = solaris_setutmp_mgmt(user, tty_line, display_name,
  224. session_type, entry_type, entry_id);
  225. if (status != SOLARIS_SUCCESS) {
  226. Debug("PamAccounting: ACCOUNTING set_utmp error=%d\n",
  227. status);
  228. }
  229. /* Intentional fall thru */
  230. case DEAD_PROCESS:
  231. /* Cleanup account files for dead processes */
  232. status = pam_close_session(pamh, 0);
  233. if (status != PAM_SUCCESS) {
  234. Debug("PamAccounting: DEAD_PROCES close_session error=%d\n",
  235. status);
  236. }
  237. status = solaris_reset_utmp_mgmt(&user, &tty_line,
  238. &display_name, 0,
  239. entry_type, entry_id);
  240. if (status != SOLARIS_SUCCESS) {
  241. Debug("PamAccounting: DEAD_PROCESS reset_utmp error=%d\n",
  242. status);
  243. }
  244. break;
  245. case LOGIN_PROCESS:
  246. default:
  247. status = pam_open_session(pamh, 0);
  248. if (status != PAM_SUCCESS) {
  249. Debug("PamAccounting:LOGIN_PROCESS open_session error=%d\n",
  250. status);
  251. }
  252. session_type = 0;
  253. status = solaris_setutmp_mgmt(user, tty_line, display_name,
  254. session_type, entry_type, entry_id);
  255. if (status != SOLARIS_SUCCESS) {
  256. Debug("PamAccounting: LOGIN_PROCESS set_utmp error=%d\n",
  257. status);
  258. }
  259. break;
  260. }
  261. free(line_dev);
  262. return(status);
  263. }
  264. /****************************************************************************
  265. * PamSetCred
  266. *
  267. * Set Users login credentials: uid, gid, and group lists
  268. ****************************************************************************/
  269. int
  270. PamSetCred(char* prog_name, char* user, uid_t uid, gid_t gid)
  271. {
  272. int cred_type, status;
  273. char* user_str = user ? user : "NULL";
  274. Debug("PamSetCred: prog_name=%s\n", prog_name);
  275. Debug("PamSetCred: user=%s\n", user_str);
  276. Debug("PamSetCred: uid=%d\n", uid);
  277. Debug("PamSetCred: gid=%d\n", gid);
  278. status = PamInit(prog_name, user, NULL, NULL);
  279. /* Set users credentials */
  280. if (status == PAM_SUCCESS && setgid(gid) == -1)
  281. status = SOLARIS_BAD_GID;
  282. if (status == PAM_SUCCESS &&
  283. ( !user) || (initgroups(user, gid) == -1) )
  284. status = SOLARIS_INITGROUP_FAIL;
  285. if (status == PAM_SUCCESS)
  286. status = pam_setcred(pamh, PAM_ESTABLISH_CRED);
  287. if (status == PAM_SUCCESS && (setuid(uid) == -1))
  288. status = SOLARIS_BAD_UID;
  289. if (status != PAM_SUCCESS) {
  290. Debug("PamSetCred: user=%s, err=%d)\n", user, status);
  291. }
  292. return(status);
  293. }
  294. /***************************************************************************
  295. * create_devname
  296. *
  297. * A utility function. Takes short device name like "console" and returns
  298. * a long device name like "/dev/console"
  299. ***************************************************************************/
  300. static char*
  301. create_devname(char* short_devname)
  302. {
  303. char* long_devname;
  304. if (short_devname == NULL)
  305. short_devname = "";
  306. long_devname = (char *) malloc (strlen(short_devname) + 5);
  307. if (long_devname == NULL)
  308. return(NULL);
  309. strcpy(long_devname,"/dev/");
  310. strcat(long_devname, short_devname);
  311. return(long_devname);
  312. }
  313. /*****************************************************************************
  314. * login_conv():
  315. *
  316. * This is a conv (conversation) function called from the PAM
  317. * authentication scheme. It returns the user's password when requested by
  318. * internal PAM authentication modules and also logs any internal PAM error
  319. * messages.
  320. *****************************************************************************/
  321. static int
  322. login_conv(int num_msg, struct pam_message **msg,
  323. struct pam_response **response, void *appdata_ptr)
  324. {
  325. struct pam_message *m;
  326. struct pam_response *r;
  327. char *temp;
  328. int k;
  329. #ifdef lint
  330. conv_id = conv_id;
  331. #endif
  332. if (num_msg <= 0)
  333. return (PAM_CONV_ERR);
  334. *response = (struct pam_response*)
  335. calloc(num_msg, sizeof (struct pam_response));
  336. if (*response == NULL)
  337. return (PAM_CONV_ERR);
  338. (void) memset(*response, 0, sizeof (struct pam_response));
  339. k = num_msg;
  340. m = *msg;
  341. r = *response;
  342. while (k--) {
  343. switch (m->msg_style) {
  344. case PAM_PROMPT_ECHO_OFF:
  345. if (saved_user_passwd != NULL) {
  346. r->resp = (char *) malloc(strlen(saved_user_passwd)+1);
  347. if (r->resp == NULL) {
  348. /* __pam_free_resp(num_msg, *response); */
  349. *response = NULL;
  350. return (PAM_CONV_ERR);
  351. }
  352. (void) strcpy(r->resp, saved_user_passwd);
  353. r->resp_retcode=0;
  354. }
  355. m++;
  356. r++;
  357. break;
  358. case PAM_ERROR_MSG:
  359. if (m->msg != NULL) {
  360. Debug ("login_conv ERROR: %s\n", m->msg);
  361. }
  362. m++;
  363. r++;
  364. break;
  365. case PAM_TEXT_INFO:
  366. if (m->msg != NULL) {
  367. Debug ("login_conv INFO: %s\n", m->msg);
  368. }
  369. m++;
  370. r++;
  371. break;
  372. default:
  373. Debug ("login_conv: Unexpected case %d\n",
  374. m->msg_style);
  375. break;
  376. }
  377. }
  378. return (PAM_SUCCESS);
  379. }