account.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510
  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: account.c /main/6 1996/10/30 11:12:13 drk $ */
  24. /* *
  25. * (c) Copyright 1993, 1994 Hewlett-Packard Company *
  26. * (c) Copyright 1993, 1994 International Business Machines Corp. *
  27. * (c) Copyright 1993, 1994 Sun Microsystems, Inc. *
  28. * (c) Copyright 1993, 1994 Novell, Inc. *
  29. */
  30. /*
  31. * account.c
  32. *
  33. * routines for handling accounting
  34. *
  35. * ex. utmp/wtmp/btmp, user-license restrictions,
  36. *
  37. */
  38. /***************************************************************************
  39. *
  40. * Includes
  41. *
  42. ***************************************************************************/
  43. #include <sys/types.h>
  44. #include <sys/stat.h>
  45. #ifdef AIXV3
  46. #include <usersec.h>
  47. #endif
  48. #include <fcntl.h>
  49. #if defined (__FreeBSD__) || defined(HAS_PAM_LIBRARY)
  50. #include <utmpx.h>
  51. #else
  52. #include <utmp.h>
  53. #endif
  54. #include <time.h>
  55. #include "dm.h"
  56. #ifdef __PASSWD_ETC
  57. #include "rgy_base.h"
  58. #endif
  59. #if defined(HAS_PAM_LIBRARY)
  60. # include <pam_svc.h>
  61. #endif
  62. /***************************************************************************
  63. *
  64. * External declarations
  65. *
  66. ***************************************************************************/
  67. #if defined(AIXV3) && !defined(_POWER)
  68. extern void
  69. GetLoginInfo(struct display *d, int *loginType, char *ttyName, char **hostname);
  70. #endif
  71. /***************************************************************************
  72. *
  73. * Procedure declarations
  74. *
  75. ***************************************************************************/
  76. #if defined(AIXV3) && !defined(_POWER)
  77. void dt_lastlogin ( char * user, struct lastlogin * llogin);
  78. #endif
  79. /***************************************************************************
  80. *
  81. * Global variables
  82. *
  83. ***************************************************************************/
  84. #ifdef __PASSWD_ETC
  85. struct rtmp {
  86. char rt_line[8]; /* tty name */
  87. rgy_$login_name_t rt_name; /* user id (full SID) */
  88. char rt_host[16]; /* hostname, if remote */
  89. long rt_time; /* time on */
  90. };
  91. #endif
  92. #ifdef AIXV3
  93. struct lastlogin {
  94. time_t ftime;
  95. time_t stime;
  96. int fcount;
  97. char user[32];
  98. char *stty;
  99. char *ftty;
  100. char *shost;
  101. char *fhost;
  102. };
  103. static struct lastlogin last_login;
  104. #endif
  105. /***************************************************************************
  106. *
  107. * Account
  108. *
  109. * update utmp/wtmp files.
  110. ***************************************************************************/
  111. void
  112. Account( struct display *d, char *user, char *line, pid_t pid,
  113. #if NeedWidePrototypes
  114. int type,
  115. #else
  116. short type,
  117. #endif /* NeedWidePrototypes */
  118. waitType exitcode )
  119. {
  120. #if !defined(CSRG_BASED) || defined(HAS_PAM_LIBRARY)
  121. #ifdef HAS_PAM_LIBRARY
  122. struct utmpx utmp; /* local struct for new entry */
  123. struct utmpx *u; /* pointer to entry in utmp file */
  124. #else
  125. struct utmp utmp; /* local struct for new entry */
  126. struct utmp *u; /* pointer to entry in utmp file */
  127. #endif
  128. int fd;
  129. char buf[32];
  130. char* user_str = user ? user : "NULL";
  131. char* line_str = line ? line : "NULL";
  132. #ifdef __PASSWD_ETC
  133. struct rtmp rtmp;
  134. struct rtmp *r;
  135. int tty_slot;
  136. int rtmp_fd;
  137. #endif
  138. if (d->utmpId == NULL) return;
  139. switch (type) {
  140. case INIT_PROCESS: strcpy(buf, "INIT_PROCESS"); break;
  141. case LOGIN_PROCESS: strcpy(buf, "LOGIN_PROCESS"); break;
  142. case USER_PROCESS: strcpy(buf, "USER_PROCESS"); break;
  143. case DEAD_PROCESS: strcpy(buf, "DEAD_PROCESS"); break;
  144. default: strcpy(buf, "UNKNOWN"); break;
  145. }
  146. Debug("Account: id=%s, user=%s, line=%s, pid=%d, type=%s\n",
  147. d->utmpId, user_str, line_str, pid, buf);
  148. #ifdef PAM
  149. PamAccounting("dtlogin", d->name, d->utmpId, user,
  150. line, pid, type, exitcode);
  151. #elif defined(HAS_PAM_LIBRARY)
  152. _DtAccounting("dtlogin", d->name, d->utmpId, user,
  153. line, pid, type, exitcode);
  154. #else
  155. # ifdef SUNAUTH
  156. solaris_accounting("dtlogin", d->name, d->utmpId, user,
  157. line, pid, type, exitcode);
  158. # endif
  159. #endif
  160. #ifdef sun
  161. return;
  162. #else
  163. #ifdef HAS_PAM_LIBRARY
  164. bzero(&utmp, sizeof(struct utmpx));
  165. #else
  166. bzero(&utmp, sizeof(struct utmp));
  167. #endif
  168. strncpy(utmp.ut_id, d->utmpId, sizeof(u->ut_id) - 1);
  169. utmp.ut_type = LOGIN_PROCESS;
  170. #ifdef HAS_PAM_LIBRARY
  171. setutxent();
  172. if ( (u = getutxid(&utmp)) == NULL ) u = &utmp;
  173. #else
  174. setutent();
  175. if ( (u = getutid(&utmp)) == NULL ) u = &utmp;
  176. #endif
  177. /*
  178. * make sure process ID's match if this is DEAD_PROCESS...
  179. * don't update an already DEAD_PROCESS...
  180. */
  181. if ((type == DEAD_PROCESS && pid != 0 && u->ut_pid != pid) ||
  182. (type == DEAD_PROCESS && u->ut_type == DEAD_PROCESS) ) {
  183. #ifdef HAS_PAM_LIBRARY
  184. endutxent();
  185. #else
  186. endutent();
  187. #endif
  188. return;
  189. }
  190. /*
  191. * fill in required fields of utmp structure...
  192. *
  193. * Note: for USER_PRCESS the "e_exit" field is overloaded to contain
  194. * the method for counting this user. This is used later to
  195. * determine if restricted user licenses have been exceeded.
  196. * Currently, an unlimited number of foreign displays can log in.
  197. */
  198. if (user) snprintf(u->ut_user, sizeof(u->ut_user), "%s", user);
  199. if (line) {
  200. #ifdef _AIX
  201. /*
  202. For AIX the Init process writes the exact mapped device name for console
  203. to the utmp file (like hft/0), if a getty on /dev/console record exists
  204. in the Inittab file.Hitherto, we need to have a similar logic to make
  205. sure for having the correct entry in the utmp file in order for the correct
  206. operation of the GettyRunning function. It should be noted that by having
  207. the correct value in the d->gettyLine field, the utmp file eventuallly
  208. updated by the Account function in dm.c will have the right value. And
  209. thus the GettyRunning function returns the appropriate value. So, it
  210. is important that the following logic be included here for AIX platform
  211. only.
  212. Raghu Krovvidi 07.06.93
  213. */
  214. if (!strcmp(line,"console")) {
  215. char *ttynm;
  216. int fd=0;
  217. fd = open("/dev/console",O_RDONLY);
  218. ttynm = ttyname(fd);
  219. ttynm += 5;
  220. strcpy(u->ut_line,ttynm);
  221. close(fd);
  222. }
  223. else
  224. snprintf(u->ut_line, sizeof(u->ut_line), "%s", line);
  225. #else
  226. snprintf(u->ut_line, sizeof(u->ut_line), "%s", line);
  227. #endif
  228. }
  229. if (pid ) u->ut_pid = pid;
  230. if (type) {
  231. u->ut_type = type;
  232. if (type == DEAD_PROCESS) {
  233. #ifndef HAS_PAM_LIBRARY
  234. u->ut_exit.e_termination = waitSig(exitcode);
  235. u->ut_exit.e_exit = waitCode(exitcode);
  236. #endif
  237. #ifndef SVR4
  238. (void) memset((char *) u->ut_host, '\0', sizeof(u->ut_host));
  239. #endif
  240. }
  241. if (type == LOGIN_PROCESS && d->displayType.location != Local ) {
  242. #ifndef SVR4
  243. snprintf(u->ut_host, sizeof(u->ut_host), "%s", d->name);
  244. #endif
  245. }
  246. #ifndef HAS_PAM_LIBRARY
  247. if (type == USER_PROCESS)
  248. u->ut_exit.e_exit = (d->displayType.location == Local ? 1 : 0 );
  249. #endif
  250. }
  251. #ifdef HAS_PAM_LIBRARY
  252. {
  253. struct timeval tmp_tv;
  254. (void) gettimeofday(&tmp_tv, NULL);
  255. u->ut_tv.tv_sec = (int32_t)tmp_tv.tv_sec;
  256. u->ut_tv.tv_usec = (int32_t)tmp_tv.tv_usec;
  257. }
  258. #else
  259. (void) time(&u->ut_time);
  260. #endif
  261. /*
  262. * write to utmp...
  263. *
  264. * (Do not close utmp yet. If "u" points to the static structure, it is
  265. * cleared upon close. This does not bode well for the following write
  266. * to wtmp!)
  267. */
  268. #ifdef HAS_PAM_LIBRARY
  269. pututxline(u);
  270. #else
  271. pututline(u);
  272. #endif
  273. #ifndef HAS_PAM_LIBRARY
  274. /*
  275. * write the same entry to wtmp...
  276. */
  277. if ((fd = open(WTMP_FILE, O_WRONLY | O_APPEND)) >= 0) {
  278. if(-1 == write(fd, u, sizeof(utmp))) {
  279. perror(strerror(errno));
  280. }
  281. close(fd);
  282. }
  283. /*
  284. * close utmp...
  285. */
  286. endutent();
  287. #else
  288. endutxent();
  289. #endif
  290. #ifdef __PASSWD_ETC
  291. /* Now fill in the "rgy utmp" struct */
  292. if (line) strncpy(rtmp.rt_line, u->ut_line, sizeof(u->ut_line));
  293. bzero(rtmp.rt_host, sizeof(rtmp.rt_host));
  294. rtmp.rt_time = u->ut_time;
  295. r = &rtmp;
  296. /* Write entry to rtmp */
  297. tty_slot = ttyslot();
  298. if (tty_slot > 0 && (rtmp_fd = open("/etc/rtmp", O_WRONLY|O_CREAT, 0644)) >= 0) {
  299. lseek(rtmp_fd, (long) (tty_slot * sizeof(struct rtmp)), 0);
  300. write(rtmp_fd, (char *) r, sizeof(struct rtmp));
  301. close(rtmp_fd);
  302. }
  303. #endif
  304. #if defined(AIXV3) && !defined(_POWER)
  305. /* Log the lastlogin data .. RK 09.13.93 */
  306. /** in AIX 4.1 this is taken care of during authentication **/
  307. if(type == USER_PROCESS) {
  308. int loginType;
  309. char tempTtyName[128];
  310. char *hostname;
  311. GetLoginInfo(d, &loginType, tempTtyName, &hostname);
  312. time(&last_login.stime);
  313. if(line) {
  314. Debug("tty_last_login is (line=%s)\n",line);
  315. last_login.stty = (char *)malloc(strlen(line) + 1);
  316. strcpy(last_login.stty,line);
  317. } else {
  318. last_login.stty = (char *)malloc(strlen(tempTtyName) + 1);
  319. strcpy(last_login.stty,tempTtyName);
  320. }
  321. last_login.shost = (char *) malloc (MAXHOSTNAMELEN);
  322. if (hostname == NULL) {
  323. gethostname (last_login.shost , MAXHOSTNAMELEN);
  324. } else {
  325. strncpy(last_login.shost, hostname, MAXHOSTNAMELEN);
  326. last_login.shost[MAXHOSTNAMELEN -1] = '\0';
  327. }
  328. Debug("logging lastlogin entry (user=%s)\n",user);
  329. dt_lastlogin(user,&last_login);
  330. free(last_login.stty);
  331. free(last_login.shost);
  332. }
  333. #endif
  334. #endif /* !sun */
  335. #endif /* !CSRG_BASED */
  336. }
  337. /***************************************************************************
  338. *
  339. * UtmpIdOpen
  340. *
  341. * see if a particular utmp ID is available
  342. *
  343. * return codes: 0 = ID is in use
  344. * 1 = ID is open
  345. ***************************************************************************/
  346. int
  347. UtmpIdOpen( char *utmpId )
  348. {
  349. int status = 1; /* return code */
  350. #if !defined(CSRG_BASED) || defined(HAS_PAM_LIBRARY)
  351. #ifdef HAS_PAM_LIBRARY
  352. struct utmpx *u; /* pointer to entry in utmp file */
  353. while ( (u = getutxent()) != NULL ) {
  354. #else
  355. struct utmp *u; /* pointer to entry in utmp file */
  356. while ( (u = getutent()) != NULL ) {
  357. #endif
  358. if ( (strncmp(u->ut_id, utmpId, 4) == 0 ) &&
  359. u->ut_type != DEAD_PROCESS ) {
  360. status = 0;
  361. break;
  362. }
  363. }
  364. #ifdef HAS_PAM_LIBRARY
  365. endutxent();
  366. #else
  367. endutent();
  368. #endif
  369. #endif
  370. return (status);
  371. }
  372. #if defined(AIXV3) && !defined(_POWER)
  373. void dt_lastlogin ( user, llogin)
  374. char * user;
  375. struct lastlogin * llogin;
  376. {
  377. char *tmp_char;
  378. char *tmp_int;
  379. /*
  380. * We are loading all the lastlogin info into a struct and then dealing
  381. * with that so if the technique of storing the values is redone it
  382. * will be easy
  383. */
  384. /* set id back to root */
  385. seteuid(0);
  386. /*
  387. * Open up the user data base
  388. */
  389. setuserdb(S_READ | S_WRITE);
  390. /*
  391. * setting new unsuccessful login attempts times
  392. */
  393. if (llogin->ftime) {
  394. /*
  395. * Get the old Failure count and increment it
  396. */
  397. if (getuserattr(user, S_ULOGCNT, &tmp_int, SEC_INT) != 0)
  398. llogin->fcount = 0;
  399. else
  400. llogin->fcount = (int)tmp_int;
  401. /*
  402. * put all the new data
  403. */
  404. putuserattr(user, S_ULASTTTY, llogin->ftty, SEC_CHAR);
  405. llogin->fcount++;
  406. putuserattr(user, S_ULOGCNT, (void *)llogin->fcount,
  407. SEC_INT);
  408. putuserattr(user, S_ULASTTIME, (void *)llogin->ftime,
  409. SEC_INT);
  410. putuserattr(user, S_ULASTHOST, llogin->fhost, SEC_CHAR);
  411. putuserattr(user, NULL, NULL, SEC_COMMIT);
  412. /*
  413. * Close data base and zero out indicator fields
  414. */
  415. llogin->ftime = 0;
  416. llogin->fcount = 0;
  417. }
  418. /*
  419. * New Successful login data
  420. */
  421. if (llogin->stime) {
  422. putuserattr(user, S_LASTTIME, (void *)llogin->stime,
  423. SEC_INT);
  424. putuserattr(user, S_LASTTTY, llogin->stty, SEC_CHAR);
  425. Debug("hostname logged is %s\n",llogin->shost);
  426. putuserattr(user, S_LASTHOST, llogin->shost, SEC_CHAR);
  427. putuserattr(user, S_ULOGCNT, 0, SEC_INT);
  428. putuserattr(user, NULL, NULL, SEC_COMMIT);
  429. }
  430. enduserdb();
  431. }
  432. #endif