pam_framework_utils.c 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888
  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. /* $XConsortium: pam_framework_utils.c /main/8 1996/11/20 11:07:39 drk $ */
  24. /*
  25. * Copyright (c) 1992-1995, by Sun Microsystems, Inc.
  26. * All rights reserved.
  27. */
  28. #ident "@(#)pam_framework_utils.c 1.37 95/12/20 SMI" /* */
  29. #include <syslog.h>
  30. #include <dlfcn.h>
  31. #include <sys/types.h>
  32. #include <sys/stat.h>
  33. #include <utmpx.h>
  34. #include <string.h>
  35. #include <stdlib.h>
  36. #include <unistd.h>
  37. #include <libintl.h>
  38. #include <synch.h>
  39. #include <shadow.h>
  40. #include <locale.h>
  41. #include <stdio.h>
  42. #include <Dt/MsgCatP.h>
  43. #include <X11/Xthreads.h>
  44. #include <X11/Xos.h>
  45. #include <errno.h>
  46. #ifdef X_NOT_STDC_ENV
  47. extern int errno;
  48. #endif
  49. #include <security/pam_appl.h>
  50. #include <security/pam_modules.h>
  51. #include "pam_impl.h"
  52. #include "pam_loc.h"
  53. static void __pam_msg_destroy(void *);
  54. static char * __pam_thread_backup(char *);
  55. static int __pam_input_output(pam_handle_t *, int, int, char [][], void *,
  56. struct pam_response **);
  57. /*
  58. * __pam_free_resp():
  59. * free storage for responses used in the call back "pam_conv" functions
  60. */
  61. void
  62. __pam_free_resp(int num_msg, struct pam_response *resp)
  63. {
  64. int i;
  65. struct pam_response *r;
  66. if (resp) {
  67. r = resp;
  68. for (i = 0; i < num_msg; i++, r++) {
  69. if (r->resp)
  70. free(r->resp);
  71. }
  72. free(resp);
  73. }
  74. }
  75. /*
  76. * __pam_display_msg():
  77. * display message by calling the call back functions
  78. * provided by the application through "pam_conv" structure
  79. */
  80. int
  81. __pam_display_msg(pamh, msg_style, num_msg, messages, conv_apdp)
  82. pam_handle_t *pamh;
  83. int msg_style;
  84. int num_msg;
  85. char messages[PAM_MAX_NUM_MSG][PAM_MAX_MSG_SIZE];
  86. void *conv_apdp;
  87. {
  88. struct pam_response *ret_respp = NULL;
  89. return (__pam_input_output(pamh, msg_style, num_msg, messages,
  90. conv_apdp, &ret_respp));
  91. }
  92. int
  93. __pam_get_input(pamh, msg_style, num_msg, messages, conv_apdp, ret_respp)
  94. pam_handle_t *pamh;
  95. int msg_style;
  96. int num_msg;
  97. char messages[PAM_MAX_NUM_MSG][PAM_MAX_MSG_SIZE];
  98. void *conv_apdp;
  99. struct pam_response **ret_respp;
  100. {
  101. return (__pam_input_output(pamh, msg_style, num_msg, messages,
  102. conv_apdp, ret_respp));
  103. }
  104. static int
  105. __pam_input_output(pamh, msg_style, num_msg, messages, conv_apdp, ret_respp)
  106. pam_handle_t *pamh;
  107. int msg_style;
  108. int num_msg;
  109. char messages[PAM_MAX_NUM_MSG][PAM_MAX_MSG_SIZE];
  110. void *conv_apdp;
  111. struct pam_response **ret_respp;
  112. {
  113. struct pam_message *msg;
  114. struct pam_message *m;
  115. int i;
  116. int k;
  117. int retcode;
  118. struct pam_conv *pam_convp;
  119. if ((retcode = pam_get_item(pamh, PAM_CONV, (void **)&pam_convp))
  120. != PAM_SUCCESS) {
  121. return (retcode);
  122. }
  123. if (pam_convp == NULL)
  124. return (PAM_SYSTEM_ERR);
  125. i = 0;
  126. k = num_msg;
  127. msg = (struct pam_message *)calloc(num_msg,
  128. sizeof (struct pam_message));
  129. if (msg == NULL) {
  130. return (PAM_BUF_ERR);
  131. }
  132. m = msg;
  133. while (k--) {
  134. /*
  135. * fill out the message structure to display prompt message
  136. */
  137. m->msg_style = msg_style;
  138. m->msg = messages[i];
  139. m++;
  140. i++;
  141. }
  142. /*
  143. * Call conv function to display the prompt.
  144. */
  145. retcode = (pam_convp->conv)(num_msg, &msg, ret_respp, conv_apdp);
  146. return (retcode);
  147. }
  148. /*
  149. * __pam_get_authtok()
  150. * retrieves a password of length "len" from the pam handle
  151. * (pam_get_item) or from the input stream (pam_get_input).
  152. *
  153. * This function allocates memory for the new authtok.
  154. * Applications calling this function are responsible for
  155. * freeing this memory.
  156. *
  157. * If "source" is
  158. * PAM_HANDLE
  159. * and "type" is:
  160. * PAM_AUTHTOK - password is taken from pam handle (PAM_AUTHTOK)
  161. * PAM_OLDAUTHTOK - password is taken from pam handle (PAM_OLDAUTHTOK)
  162. *
  163. * If "source" is
  164. * PAM_PROMPT
  165. * and "type" is:
  166. * 0: Prompt for new passwd, do not even attempt
  167. * to store it in the pam handle.
  168. * PAM_AUTHTOK: Prompt for new passwd, store in pam handle as
  169. * PAM_AUTHTOK item if this value is not already set.
  170. * PAM_OLDAUTHTOK: Prompt for new passwd, store in pam handle as
  171. * PAM_OLDAUTHTOK item if this value is not
  172. * already set.
  173. */
  174. int
  175. __pam_get_authtok(pam_handle_t *pamh, int source, int type, int len,
  176. char *prompt, char **authtok)
  177. {
  178. int error = PAM_SYSTEM_ERR;
  179. char *new_password = NULL;
  180. struct pam_response *ret_resp = (struct pam_response *)0;
  181. char messages[PAM_MAX_NUM_MSG][PAM_MAX_MSG_SIZE];
  182. char *backup_prompt = PAM_MSG(pamh, 31, "password: ");
  183. if (len >= PAM_MAX_RESP_SIZE) {
  184. syslog(LOG_ERR,
  185. "__pam_get_authtok: requested passwd length too long");
  186. return (PAM_BUF_ERR);
  187. }
  188. if ((*authtok = (char *)calloc(len + 1, sizeof (char))) == NULL) {
  189. *authtok = NULL;
  190. return (PAM_BUF_ERR);
  191. }
  192. if (prompt == NULL)
  193. prompt = backup_prompt;
  194. switch (source) {
  195. case PAM_HANDLE:
  196. /* get password from pam handle item list */
  197. switch (type) {
  198. case PAM_AUTHTOK:
  199. case PAM_OLDAUTHTOK:
  200. if ((error = pam_get_item(pamh, type,
  201. (void **)&new_password)) != PAM_SUCCESS) {
  202. free(*authtok);
  203. *authtok = NULL;
  204. return (error);
  205. }
  206. if (new_password == NULL || new_password[0] == '\0') {
  207. free(*authtok);
  208. *authtok = NULL;
  209. } else {
  210. strncpy(*authtok, new_password, len);
  211. (*authtok)[len] = '\0';
  212. }
  213. break;
  214. default:
  215. syslog(LOG_ERR,
  216. "__pam_get_authtok() invalid type: %d", type);
  217. free(*authtok);
  218. *authtok = NULL;
  219. return (PAM_SYMBOL_ERR);
  220. }
  221. break;
  222. case PAM_PROMPT:
  223. /*
  224. * Prompt for new password and save in pam handle item list
  225. * if the that item is not already set.
  226. */
  227. strncpy(messages[0], prompt, sizeof (messages[0]));
  228. if ((error = __pam_get_input(pamh, PAM_PROMPT_ECHO_OFF,
  229. 1, messages, NULL, &ret_resp)) != PAM_SUCCESS) {
  230. free(*authtok);
  231. *authtok = NULL;
  232. return (error);
  233. }
  234. /* save the new password if this item was NULL */
  235. if (type) {
  236. pam_get_item(pamh, type, (void **)&new_password);
  237. if (new_password == NULL)
  238. pam_set_item(pamh, type, ret_resp->resp);
  239. }
  240. strncpy(*authtok, ret_resp->resp, len);
  241. (*authtok)[len] = '\0';
  242. memset(ret_resp->resp, 0, strlen(ret_resp->resp));
  243. __pam_free_resp(1, ret_resp);
  244. break;
  245. default:
  246. syslog(LOG_ERR,
  247. "__pam_get_authtok() invalid source: %d", source);
  248. free(*authtok);
  249. *authtok = NULL;
  250. return (PAM_SYMBOL_ERR);
  251. }
  252. return (PAM_SUCCESS);
  253. }
  254. #if !defined(NL_CAT_LOCALE)
  255. #define NL_CAT_LOCALE 0
  256. #endif
  257. typedef struct _pam_msg_data {
  258. nl_catd fd;
  259. } _pam_msg_data;
  260. static void
  261. __pam_msg_cleanup(
  262. pam_handle_t *pamh,
  263. void *data,
  264. int pam_status)
  265. {
  266. _pam_msg_data *msg_data = (_pam_msg_data *) data;
  267. CATCLOSE(msg_data->fd);
  268. free(msg_data);
  269. }
  270. static void
  271. __pam_msg_destroy(void *tsd)
  272. {
  273. if (tsd)
  274. free((char *)tsd);
  275. }
  276. static char *
  277. __pam_thread_backup(char *msg)
  278. {
  279. char *data_buffer = 0;
  280. static xmutex_rec thread_lock = XMUTEX_INITIALIZER;
  281. static xthread_key_t thread_key = 0;
  282. static char fallback_buff[PAM_MAX_MSG_SIZE];
  283. memset(fallback_buff, 0, sizeof (fallback_buff));
  284. if (thread_key == 0) {
  285. xmutex_lock(&thread_lock);
  286. if (thread_key == 0)
  287. xthread_key_create(&thread_key, __pam_msg_destroy);
  288. xmutex_unlock(&thread_lock);
  289. if (thread_key == 0) {
  290. strncat(fallback_buff, msg, PAM_MAX_MSG_SIZE-1);
  291. return (fallback_buff);
  292. }
  293. }
  294. xthread_get_specific(thread_key, (void **)&data_buffer);
  295. if (data_buffer == (char *)NULL) {
  296. if ((data_buffer = (char *)calloc(PAM_MAX_MSG_SIZE,
  297. sizeof (char))) == NULL) {
  298. /* what else can i do? */
  299. strncat(fallback_buff, msg, PAM_MAX_MSG_SIZE-1);
  300. return (fallback_buff);
  301. }
  302. xthread_set_specific(thread_key, (void *)data_buffer);
  303. }
  304. /*
  305. * Memset the buffer because we might have stale data from
  306. * a previous thr_setspecific() call.
  307. */
  308. memset(data_buffer, 0, PAM_MAX_MSG_SIZE);
  309. strncat(data_buffer, msg, PAM_MAX_MSG_SIZE-1);
  310. return (data_buffer);
  311. }
  312. /*
  313. *
  314. * Function: __pam_get_i18n_msg
  315. *
  316. *
  317. * Parameters:
  318. *
  319. * int set - The message catalog set number.
  320. *
  321. * int n - The message number.
  322. *
  323. * char *s - The default message if the message is not
  324. * retrieved from a message catalog.
  325. *
  326. * Returns: the string for set 'set' and number 'n'.
  327. *
  328. */
  329. char *
  330. __pam_get_i18n_msg(
  331. pam_handle_t *pamh,
  332. char *filename,
  333. int set,
  334. int n,
  335. char *s)
  336. {
  337. char *msg;
  338. char *output_msg;
  339. nl_catd nlmsg_fd;
  340. /*
  341. * If pam handle was supplied,
  342. * look for stored message file descriptor.
  343. */
  344. if (pamh != NULL) {
  345. _pam_msg_data *msg_data;
  346. int status = pam_get_data(pamh, filename, (void**) &msg_data);
  347. if (status == PAM_SUCCESS) {
  348. return (CATGETS(msg_data->fd, set, n, s));
  349. }
  350. if (status == PAM_NO_MODULE_DATA) {
  351. /*
  352. * No message file descriptor found, make and store one.
  353. */
  354. nlmsg_fd = CATOPEN(filename, NL_CAT_LOCALE);
  355. msg = CATGETS(nlmsg_fd, set, n, s);
  356. if ((msg_data = (_pam_msg_data *)
  357. calloc(1, sizeof (_pam_msg_data))) == NULL) {
  358. output_msg = __pam_thread_backup(msg);
  359. CATCLOSE(nlmsg_fd);
  360. return (output_msg);
  361. }
  362. msg_data->fd = nlmsg_fd;
  363. pam_set_data(pamh, filename, msg_data, __pam_msg_cleanup);
  364. return (msg);
  365. }
  366. }
  367. /* NULL pamh */
  368. nlmsg_fd = CATOPEN(filename, NL_CAT_LOCALE);
  369. msg = CATGETS(nlmsg_fd, set, n, s);
  370. output_msg = __pam_thread_backup(msg);
  371. CATCLOSE(nlmsg_fd);
  372. return (output_msg);
  373. }
  374. #ifdef PAM_MAYBE_WILL_BE_USED_LATER
  375. extern int pam_debug;
  376. /* Errors returned by __setutmp_mgmt/__reset_utmp_mgmt() */
  377. #define __NOENTRY 27 /* No entry found */
  378. #define __ENTRYFAIL 28 /* Couldn't make/remove the entry */
  379. /* Errors returned by __setproc_cred() */
  380. #define __BAD_GID 29 /* Invalid Group ID */
  381. #define __INITGROUP_FAIL 30 /* Initialization of group IDs failed */
  382. #define __BAD_UID 31 /* Invaid User ID */
  383. #define __SETGROUP_FAIL 32 /* Set of group IDs failed */
  384. #define INIT_PROC_PID 1
  385. #define PAMTXD "SUNW_OST_SYSOSPAM"
  386. #define SCPYN(a, b) (void) strncpy(a, b, sizeof (a))
  387. /* utility function to do UTMP/WTMP management */
  388. int
  389. __setutmp_mgmt(
  390. char *user, /* user */
  391. char *ttyn, /* ttyn */
  392. char *rhost, /* remote hostname */
  393. int flags, /* Flags - see below */
  394. int type, /* type of utmp/wtmp entry */
  395. char id[] /* 4 byte id field for utmp */
  396. );
  397. /* Flags for the flags field */
  398. #define __UPDATE_ENTRY 1 /* Update an existing entry */
  399. #define __NOLOG 2 /* Don't log the new session */
  400. #define __LOGIN 4 /* login type entry (sigh...) */
  401. /*
  402. * __reset_utmp_mgmt is a utility function which terminates UTMP/WTMP mgmt
  403. */
  404. int
  405. __reset_utmp_mgmt(
  406. char **user, /* user */
  407. char **ttyn, /* tty name */
  408. char **rhost, /* remote host */
  409. int flags, /* flags - see below */
  410. int status, /* logout process status */
  411. char id[] /* logout ut_id (/etc/inittab id) */
  412. );
  413. /* flags for the flags field */
  414. #define __NOOP 8 /* No utmp action desired */
  415. /* __setproc_cred is a utility function to set process credentials */
  416. int
  417. __setproc_cred(
  418. char *user, /* user */
  419. int flags, /* flags - see below */
  420. uid_t uid, /* User ID to set for this process */
  421. gid_t gid, /* Group ID */
  422. int ngroups, /* Number of groups */
  423. gid_t *grouplist /* Group list */
  424. );
  425. /* flags indicates specific set credential actions */
  426. #define __INITGROUPS 0x00000001 /* Request to initgroups() */
  427. #define __SETGROUPS 0x00000002 /* Request to setgroups() */
  428. #define __SETEGID 0x00000004 /* Set effective gid only */
  429. #define __SETGID 0x00000008 /* Set real gid */
  430. #define __SETEUID 0x00000010 /* Set effective uid only */
  431. #define __SETUID 0x00000020 /* Set real uid */
  432. #define __SETEID (__SETEGID|__SETEUID) /* Set effective ids only */
  433. #define __SETRID (__SETGID|__SETUID) /* Set real ids */
  434. /*
  435. * __setutmp_mgmt - A utility function used to do UTMP/WTMP management.
  436. * This function is NOT meant to be part of the official
  437. * PAM API, and only serves as a convenience function.
  438. *
  439. * "user" is the current username.
  440. * "ttyn" is the tty name.
  441. * "rhost" is the remote hostname.
  442. * The following flags may be set in the "flags" field:
  443. *
  444. * __UPDATE_ENTRY No new entry will be created if utmp
  445. * entry not found - return __NOENTRY
  446. * __NOLOG Generate a wtmp/wtmpx entry only
  447. * __LOGIN Caller is a login application - update
  448. * utmp entry accordingly
  449. *
  450. * "type" is used to indicate the type of utmp/wtmp entry written
  451. * (see also utmp.h and utmpx.h)
  452. * "id is an optional application-defined 4 byte array that represents
  453. * the /sbin/inittab id (created by the process that puts an entry in
  454. * utmp).
  455. *
  456. * Upon successful completion, PAM_SUCCESS is returned.
  457. * Error values may include:
  458. *
  459. * __NOENTRY An entry for the specified process was not found
  460. * __ENTRYFAIL Could not make/remove entry for specified process
  461. */
  462. int
  463. __setutmp_mgmt(
  464. char *user,
  465. char *ttyn,
  466. char *rhost,
  467. int flags,
  468. int type,
  469. char id[])
  470. {
  471. int tmplen;
  472. struct utmpx *u = (struct utmpx *)0;
  473. struct utmpx utmp;
  474. char *ttyntail;
  475. int err = PAM_SUCCESS;
  476. if (pam_debug)
  477. syslog(LOG_DEBUG, "pam_open_session(%d)\n", type);
  478. (void) memset((void *)&utmp, 0, sizeof (utmp));
  479. (void) time(&utmp.ut_tv.tv_sec);
  480. utmp.ut_pid = getpid();
  481. if (rhost != NULL && rhost[0] != '\0') {
  482. (void) strcpy(utmp.ut_host, rhost);
  483. tmplen = strlen(rhost) + 1;
  484. if (tmplen < sizeof (utmp.ut_host))
  485. utmp.ut_syslen = tmplen;
  486. else
  487. utmp.ut_syslen = sizeof (utmp.ut_host);
  488. } else {
  489. (void) memset(utmp.ut_host, 0, sizeof (utmp.ut_host));
  490. utmp.ut_syslen = 0;
  491. }
  492. (void) strcpy(utmp.ut_user, user);
  493. /*
  494. * Copy in the name of the tty minus the "/dev/" if a /dev/ is
  495. * in the path name.
  496. */
  497. if (!(flags&__LOGIN))
  498. SCPYN(utmp.ut_line, ttyn);
  499. ttyntail = ttyn;
  500. utmp.ut_type = type;
  501. if (id != NULL)
  502. (void) memcpy(utmp.ut_id, id, sizeof (utmp.ut_id));
  503. if ((flags & __NOLOG) == __NOLOG) {
  504. updwtmpx(WTMPX_FILE, &utmp);
  505. } else {
  506. /*
  507. * Go through each entry one by one, looking only at INIT,
  508. * LOGIN or USER Processes. Use the entry found if flags == 0
  509. * and the line name matches, or if the process ID matches if
  510. * the UPDATE_ENTRY flag is set. The UPDATE_ENTRY flag is
  511. * mainly for login which normally only wants to update an
  512. * entry if the pid fields matches.
  513. */
  514. if (flags & __LOGIN) {
  515. while ((u = getutxent()) != NULL) {
  516. if ((u->ut_type == INIT_PROCESS ||
  517. u->ut_type == LOGIN_PROCESS ||
  518. u->ut_type == USER_PROCESS) &&
  519. ((flags == __LOGIN && ttyn != NULL &&
  520. strncmp(u->ut_line, ttyntail,
  521. sizeof (u->ut_line)) == 0) ||
  522. u->ut_pid == utmp.ut_pid)) {
  523. if (ttyn)
  524. SCPYN(utmp.ut_line,
  525. (ttyn + sizeof ("/dev/") - 1));
  526. if (id == NULL) {
  527. (void) memcpy(utmp.ut_id, u->ut_id,
  528. sizeof (utmp.ut_id));
  529. }
  530. (void) pututxline(&utmp);
  531. break;
  532. }
  533. } /* end while */
  534. endutxent(); /* Close utmp file */
  535. }
  536. if (u == (struct utmpx *)NULL) {
  537. /* audit_login_main11(); */
  538. if (flags & __UPDATE_ENTRY)
  539. err = __NOENTRY;
  540. else
  541. (void) makeutx(&utmp);
  542. }
  543. else
  544. updwtmpx(WTMPX_FILE, &utmp);
  545. }
  546. return (err);
  547. }
  548. /*
  549. * __reset_utmp_mgmt A utility function used to terminate UTMP/WTMP mgmt.
  550. * This function is NOT meant to be part of the official
  551. * PAM API, and only serves as a convenience function.
  552. *
  553. * "user" is the current username.
  554. * "ttyn" is the tty name.
  555. * "rhost" is the remote hostname.
  556. * The following flags may be set in the "flags" field:
  557. *
  558. * __NOLOG Write a wtmp/wtmpx entry only
  559. * __NOOP Ignore utmp/wtmp processing
  560. *
  561. * "status" is the logout process status.
  562. * "id is an optional application-defined 4 byte array that represents
  563. * the /sbin/inittab id (created by the process that puts an entry in
  564. * utmp).
  565. *
  566. * Upon successful completion, PAM_SUCCESS is returned.
  567. * Error values may include:
  568. *
  569. * __NOENTRY An entry for the specified process was not found
  570. * __ENTRYFAIL Could not make/remove entry for specified process
  571. */
  572. int
  573. __reset_utmp_mgmt(
  574. char **user,
  575. char **ttyn,
  576. char **rhost,
  577. int flags,
  578. int status,
  579. char id[])
  580. {
  581. struct utmpx *up;
  582. struct utmpx ut;
  583. int err = 0;
  584. int pid;
  585. if (pam_debug)
  586. syslog(LOG_DEBUG, "pam_close_session()\n");
  587. /*
  588. * do we want to do any utmp processing?
  589. */
  590. if (flags & __NOOP) {
  591. return (PAM_SUCCESS);
  592. }
  593. pid = (int) getpid();
  594. if ((flags & __NOLOG) == __NOLOG) { /* only write to wtmp files */
  595. /* clear utmpx entry */
  596. (void) memset((char *)&ut, 0, sizeof (ut));
  597. if (id != NULL)
  598. (void) memcpy(ut.ut_id, id, sizeof (ut.ut_id));
  599. if (*ttyn != NULL && **ttyn != '\0') {
  600. if (strstr(*ttyn, "/dev/") != NULL)
  601. (void) strncpy(ut.ut_line, (*ttyn+sizeof ("/dev/")-1),
  602. sizeof (ut.ut_line));
  603. else
  604. (void) strncpy(ut.ut_line, *ttyn,
  605. sizeof (ut.ut_line));
  606. }
  607. ut.ut_pid = pid;
  608. ut.ut_type = DEAD_PROCESS;
  609. ut.ut_exit.e_termination = 0;
  610. ut.ut_exit.e_exit = 0;
  611. ut.ut_syslen = 1;
  612. (void) gettimeofday(&ut.ut_tv, NULL);
  613. updwtmpx(WTMPX_FILE, &ut);
  614. return (PAM_SUCCESS);
  615. } else {
  616. setutxent();
  617. while (up = getutxent()) {
  618. if (up->ut_pid == pid) {
  619. if (up->ut_type == DEAD_PROCESS) {
  620. /*
  621. * Cleaned up elsewhere.
  622. */
  623. endutxent();
  624. return (0);
  625. }
  626. if ((*user = (char *) strdup(up->ut_user))
  627. == NULL ||
  628. (*ttyn = (char *) strdup(up->ut_line))
  629. == NULL ||
  630. (*rhost = (char *) strdup(up->ut_host))
  631. == NULL ||)
  632. return (PAM_BUF_ERR);
  633. up->ut_type = DEAD_PROCESS;
  634. up->ut_exit.e_termination = status & 0xff;
  635. up->ut_exit.e_exit = (status >> 8) & 0xff;
  636. if (id != NULL)
  637. (void) memcpy(up->ut_id, id,
  638. sizeof (up->ut_id));
  639. (void) time(&up->ut_tv.tv_sec);
  640. /*
  641. * For init (Process ID 1) we don't write to
  642. * init's pipe, since we are init.
  643. */
  644. if (getpid() == INIT_PROC_PID) {
  645. (void) pututxline(up);
  646. /*
  647. * Now attempt to add to the end of the
  648. * wtmp and wtmpx files. Do not create
  649. * if they don't already exist.
  650. */
  651. updwtmpx("wtmpx", up);
  652. } else {
  653. if (modutx(up) == NULL) {
  654. syslog(LOG_INFO,
  655. "\tmodutx failed");
  656. /*
  657. * Since modutx failed we'll
  658. * write out the new entry
  659. * ourselves.
  660. */
  661. (void) pututxline(up);
  662. updwtmpx("wtmpx", up);
  663. }
  664. }
  665. endutxent();
  666. return (PAM_SUCCESS);
  667. }
  668. }
  669. endutxent();
  670. return (__NOENTRY);
  671. }
  672. }
  673. /*
  674. * __setproc_cred - A utility function used to set the unix credentials of the
  675. * current process. This function is NOT meant to be part of
  676. * the official PAM API, and only serves as a convenience
  677. * function.
  678. *
  679. * "user" is the current username.
  680. * The following flags may be set in the "flags" field:
  681. *
  682. * __INITGROUPS Initialize the supplementary group access list.
  683. * __SETGROUPS Set the supplementary group access list.
  684. * __SETEGID Set the effective group ID only.
  685. * __SETGID Set the real and effective group IDs.
  686. * __SETEUID Set the effective user ID only.
  687. * __SETUID Set the real and effective user IDs.
  688. * __SETEID Set the effective user and group IDs.
  689. * __SETRID Set the real and effective user and group IDs.
  690. *
  691. * "uid" and "gid" are the values of the user ID and group ID respectively.
  692. * "ngroups" is the number of supplementary groups.
  693. * "grouplist" is a pointer to the list of supplementary groups.
  694. *
  695. * Upon successful completion, PAM_SUCCESS is returned.
  696. * Error values may include:
  697. *
  698. * __BAD_GID Invalid group ID
  699. * __INITGROUP_FAIL Initialization of group ID's failed
  700. * __BAD_UID Invalid user ID
  701. * __SETGROUP_FAIL Set of group ID's failed
  702. */
  703. int
  704. __setproc_cred(
  705. char *user,
  706. int flags,
  707. uid_t uid,
  708. gid_t gid,
  709. int ngroups,
  710. gid_t *grouplist)
  711. {
  712. int err = 0;
  713. char messages[PAM_MAX_NUM_MSG][PAM_MAX_MSG_SIZE];
  714. /*
  715. * Set the credentials
  716. */
  717. /* set the effective GID */
  718. if (flags & __SETEGID) {
  719. if (setegid(gid) == -1) {
  720. sprintf(messages[0], PAM_MSG(NULL, 29,
  721. "pam_sm_setcred: %s\n"), strerror(errno));
  722. return (__BAD_GID);
  723. }
  724. }
  725. /* set the real (and effective) GID */
  726. if (flags & __SETGID) {
  727. if (setgid(gid) == -1) {
  728. sprintf(messages[0], PAM_MSG(NULL, 30,
  729. "setproc_cred: %s\n"), strerror(errno));
  730. return (__BAD_GID);
  731. }
  732. }
  733. /*
  734. * Initialize the supplementary group access list.
  735. */
  736. if (!user)
  737. return (__INITGROUP_FAIL);
  738. if (flags & __INITGROUPS) {
  739. if (initgroups(user, gid) == -1) {
  740. sprintf(messages[0], PAM_MSG(NULL, 29,
  741. "pam_sm_setcred: %s\n"), strerror(errno));
  742. return (__INITGROUP_FAIL);
  743. }
  744. }
  745. /*
  746. * Set the supplementary group access list.
  747. */
  748. if (flags & __SETGROUPS) {
  749. if (setgroups(ngroups, (gid_t *)grouplist) == -1) {
  750. sprintf(messages[0], PAM_MSG(NULL, 29,
  751. "pam_sm_setcred: %s\n"), strerror(errno));
  752. return (__SETGROUP_FAIL);
  753. }
  754. }
  755. /*
  756. * Set the user id
  757. */
  758. /* set the effective UID */
  759. if (flags & __SETEUID) {
  760. if (seteuid(uid) == -1) {
  761. sprintf(messages[0], PAM_MSG(NULL, 29
  762. "pam_sm_setcred: %s\n"), strerror(errno));
  763. return (__BAD_UID);
  764. }
  765. }
  766. /* set the real (and effective) UID */
  767. if (flags & __SETUID) {
  768. if (setuid(uid) == -1) {
  769. sprintf(messages[0], PAM_MSG(NULL, 29,
  770. "pam_sm_setcred: %s\n"), strerror(errno));
  771. return (__BAD_UID);
  772. }
  773. }
  774. return (PAM_SUCCESS);
  775. }
  776. #endif