507 lines
13 KiB
C
507 lines
13 KiB
C
/*
|
|
* CDE - Common Desktop Environment
|
|
*
|
|
* Copyright (c) 1993-2012, The Open Group. All rights reserved.
|
|
*
|
|
* These libraries and programs are free software; you can
|
|
* redistribute them and/or modify them under the terms of the GNU
|
|
* Lesser General Public License as published by the Free Software
|
|
* Foundation; either version 2 of the License, or (at your option)
|
|
* any later version.
|
|
*
|
|
* These libraries and programs are distributed in the hope that
|
|
* they will be useful, but WITHOUT ANY WARRANTY; without even the
|
|
* implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
|
* PURPOSE. See the GNU Lesser General Public License for more
|
|
* details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with these libraries and programs; if not, write
|
|
* to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
|
|
* Floor, Boston, MA 02110-1301 USA
|
|
*/
|
|
/* $XConsortium: account.c /main/6 1996/10/30 11:12:13 drk $ */
|
|
/* *
|
|
* (c) Copyright 1993, 1994 Hewlett-Packard Company *
|
|
* (c) Copyright 1993, 1994 International Business Machines Corp. *
|
|
* (c) Copyright 1993, 1994 Sun Microsystems, Inc. *
|
|
* (c) Copyright 1993, 1994 Novell, Inc. *
|
|
*/
|
|
/*
|
|
* account.c
|
|
*
|
|
* routines for handling accounting
|
|
*
|
|
* ex. utmp/wtmp/btmp, user-license restrictions,
|
|
*
|
|
*/
|
|
|
|
|
|
/***************************************************************************
|
|
*
|
|
* Includes
|
|
*
|
|
***************************************************************************/
|
|
|
|
#include <sys/types.h>
|
|
#include <sys/stat.h>
|
|
|
|
#ifdef AIXV3
|
|
#include <usersec.h>
|
|
#endif
|
|
|
|
#include <fcntl.h>
|
|
#if defined(__FreeBSD__) && OSMAJORVERSION > 8 || defined(HAS_PAM_LIBRARY)
|
|
#include <utmpx.h>
|
|
#else
|
|
#include <utmp.h>
|
|
#endif
|
|
|
|
#include <time.h>
|
|
#include "dm.h"
|
|
|
|
#ifdef __PASSWD_ETC
|
|
#include "rgy_base.h"
|
|
#endif
|
|
|
|
|
|
/***************************************************************************
|
|
*
|
|
* External declarations
|
|
*
|
|
***************************************************************************/
|
|
#if defined(AIXV3) && !defined(_POWER)
|
|
extern void
|
|
GetLoginInfo(struct display *d, int *loginType, char *ttyName, char **hostname);
|
|
#endif
|
|
|
|
|
|
|
|
/***************************************************************************
|
|
*
|
|
* Procedure declarations
|
|
*
|
|
***************************************************************************/
|
|
#if defined(AIXV3) && !defined(_POWER)
|
|
void dt_lastlogin ( char * user, struct lastlogin * llogin);
|
|
#endif
|
|
|
|
|
|
|
|
|
|
/***************************************************************************
|
|
*
|
|
* Global variables
|
|
*
|
|
***************************************************************************/
|
|
|
|
#ifdef __PASSWD_ETC
|
|
struct rtmp {
|
|
char rt_line[8]; /* tty name */
|
|
rgy_$login_name_t rt_name; /* user id (full SID) */
|
|
char rt_host[16]; /* hostname, if remote */
|
|
long rt_time; /* time on */
|
|
};
|
|
#endif
|
|
|
|
#ifdef AIXV3
|
|
struct lastlogin {
|
|
time_t ftime;
|
|
time_t stime;
|
|
int fcount;
|
|
char user[32];
|
|
char *stty;
|
|
char *ftty;
|
|
char *shost;
|
|
char *fhost;
|
|
};
|
|
|
|
|
|
static struct lastlogin last_login;
|
|
#endif
|
|
|
|
|
|
|
|
/***************************************************************************
|
|
*
|
|
* Account
|
|
*
|
|
* update utmp/wtmp files.
|
|
***************************************************************************/
|
|
void
|
|
Account( struct display *d, char *user, char *line, pid_t pid,
|
|
#if NeedWidePrototypes
|
|
int type,
|
|
#else
|
|
short type,
|
|
#endif /* NeedWidePrototypes */
|
|
waitType exitcode )
|
|
{
|
|
#if !defined(CSRG_BASED) || defined(HAS_PAM_LIBRARY)
|
|
#ifdef HAS_PAM_LIBRARY
|
|
struct utmpx utmp; /* local struct for new entry */
|
|
struct utmpx *u; /* pointer to entry in utmp file */
|
|
#else
|
|
struct utmp utmp; /* local struct for new entry */
|
|
struct utmp *u; /* pointer to entry in utmp file */
|
|
#endif
|
|
int fd;
|
|
char buf[32];
|
|
char* user_str = user ? user : "NULL";
|
|
char* line_str = line ? line : "NULL";
|
|
|
|
#ifdef __PASSWD_ETC
|
|
struct rtmp rtmp;
|
|
struct rtmp *r;
|
|
int tty_slot;
|
|
int rtmp_fd;
|
|
#endif
|
|
|
|
if (d->utmpId == NULL) return;
|
|
|
|
switch (type) {
|
|
|
|
case INIT_PROCESS: strcpy(buf, "INIT_PROCESS"); break;
|
|
case LOGIN_PROCESS: strcpy(buf, "LOGIN_PROCESS"); break;
|
|
case USER_PROCESS: strcpy(buf, "USER_PROCESS"); break;
|
|
case DEAD_PROCESS: strcpy(buf, "DEAD_PROCESS"); break;
|
|
default: strcpy(buf, "UNKNOWN"); break;
|
|
}
|
|
|
|
Debug("Account: id=%s, user=%s, line=%s, pid=%d, type=%s\n",
|
|
d->utmpId, user_str, line_str, pid, buf);
|
|
|
|
#ifdef PAM
|
|
PamAccounting("dtlogin", d->name, d->utmpId, user,
|
|
line, pid, type, exitcode);
|
|
#elif defined(HAS_PAM_LIBRARY)
|
|
_DtAccounting("dtlogin", d->name, d->utmpId, user,
|
|
line, pid, type, exitcode);
|
|
#else
|
|
# ifdef SUNAUTH
|
|
solaris_accounting("dtlogin", d->name, d->utmpId, user,
|
|
line, pid, type, exitcode);
|
|
# endif
|
|
#endif
|
|
|
|
#ifdef sun
|
|
return;
|
|
#else
|
|
#ifdef HAS_PAM_LIBRARY
|
|
bzero(&utmp, sizeof(struct utmpx));
|
|
#else
|
|
bzero(&utmp, sizeof(struct utmp));
|
|
#endif
|
|
|
|
strncpy(utmp.ut_id, d->utmpId, sizeof(u->ut_id) - 1);
|
|
utmp.ut_type = LOGIN_PROCESS;
|
|
|
|
#ifdef HAS_PAM_LIBRARY
|
|
setutxent();
|
|
if ( (u = getutxid(&utmp)) == NULL ) u = &utmp;
|
|
#else
|
|
setutent();
|
|
if ( (u = getutid(&utmp)) == NULL ) u = &utmp;
|
|
#endif
|
|
|
|
/*
|
|
* make sure process ID's match if this is DEAD_PROCESS...
|
|
* don't update an already DEAD_PROCESS...
|
|
*/
|
|
|
|
if ((type == DEAD_PROCESS && pid != 0 && u->ut_pid != pid) ||
|
|
(type == DEAD_PROCESS && u->ut_type == DEAD_PROCESS) ) {
|
|
|
|
#ifdef HAS_PAM_LIBRARY
|
|
endutxent();
|
|
#else
|
|
endutent();
|
|
#endif
|
|
return;
|
|
}
|
|
|
|
|
|
/*
|
|
* fill in required fields of utmp structure...
|
|
*
|
|
* Note: for USER_PRCESS the "e_exit" field is overloaded to contain
|
|
* the method for counting this user. This is used later to
|
|
* determine if restricted user licenses have been exceeded.
|
|
* Currently, an unlimited number of foreign displays can log in.
|
|
*/
|
|
|
|
if (user) snprintf(u->ut_user, sizeof(u->ut_user), "%s", user);
|
|
if (line) {
|
|
#ifdef _AIX
|
|
/*
|
|
For AIX the Init process writes the exact mapped device name for console
|
|
to the utmp file (like hft/0), if a getty on /dev/console record exists
|
|
in the Inittab file.Hitherto, we need to have a similar logic to make
|
|
sure for having the correct entry in the utmp file in order for the correct
|
|
operation of the GettyRunning function. It should be noted that by having
|
|
the correct value in the d->gettyLine field, the utmp file eventuallly
|
|
updated by the Account function in dm.c will have the right value. And
|
|
thus the GettyRunning function returns the appropriate value. So, it
|
|
is important that the following logic be included here for AIX platform
|
|
only.
|
|
Raghu Krovvidi 07.06.93
|
|
*/
|
|
|
|
if (!strcmp(line,"console")) {
|
|
char *ttynm;
|
|
int fd=0;
|
|
|
|
fd = open("/dev/console",O_RDONLY);
|
|
ttynm = ttyname(fd);
|
|
ttynm += 5;
|
|
strcpy(u->ut_line,ttynm);
|
|
close(fd);
|
|
}
|
|
else
|
|
snprintf(u->ut_line, sizeof(u->ut_line), "%s", line);
|
|
|
|
#else
|
|
snprintf(u->ut_line, sizeof(u->ut_line), "%s", line);
|
|
#endif
|
|
}
|
|
if (pid ) u->ut_pid = pid;
|
|
if (type) {
|
|
u->ut_type = type;
|
|
if (type == DEAD_PROCESS) {
|
|
#ifndef HAS_PAM_LIBRARY
|
|
u->ut_exit.e_termination = waitSig(exitcode);
|
|
u->ut_exit.e_exit = waitCode(exitcode);
|
|
#endif
|
|
#ifndef SVR4
|
|
(void) memset((char *) u->ut_host, '\0', sizeof(u->ut_host));
|
|
#endif
|
|
}
|
|
|
|
if (type == LOGIN_PROCESS && d->displayType.location != Local ) {
|
|
#ifndef SVR4
|
|
snprintf(u->ut_host, sizeof(u->ut_host), "%s", d->name);
|
|
#endif
|
|
#ifdef __hpux
|
|
u->ut_addr = 0;
|
|
#endif
|
|
}
|
|
|
|
#ifndef HAS_PAM_LIBRARY
|
|
if (type == USER_PROCESS)
|
|
u->ut_exit.e_exit = (d->displayType.location == Local ? 1 : 0 );
|
|
#endif
|
|
}
|
|
|
|
#ifdef HAS_PAM_LIBRARY
|
|
(void) time(&u->ut_tv);
|
|
#else
|
|
(void) time(&u->ut_time);
|
|
#endif
|
|
|
|
/*
|
|
* write to utmp...
|
|
*
|
|
* (Do not close utmp yet. If "u" points to the static structure, it is
|
|
* cleared upon close. This does not bode well for the following write
|
|
* to wtmp!)
|
|
*/
|
|
|
|
#ifdef HAS_PAM_LIBRARY
|
|
pututxline(u);
|
|
#else
|
|
pututline(u);
|
|
#endif
|
|
|
|
|
|
#ifndef HAS_PAM_LIBRARY
|
|
/*
|
|
* write the same entry to wtmp...
|
|
*/
|
|
|
|
if ((fd = open(WTMP_FILE, O_WRONLY | O_APPEND)) >= 0) {
|
|
if(-1 == write(fd, u, sizeof(utmp))) {
|
|
perror(strerror(errno));
|
|
}
|
|
close(fd);
|
|
}
|
|
|
|
|
|
/*
|
|
* close utmp...
|
|
*/
|
|
|
|
endutent();
|
|
#else
|
|
endutxent();
|
|
#endif
|
|
|
|
#ifdef __PASSWD_ETC
|
|
/* Now fill in the "rgy utmp" struct */
|
|
if (line) strncpy(rtmp.rt_line, u->ut_line, sizeof(u->ut_line));
|
|
bzero(rtmp.rt_host, sizeof(rtmp.rt_host));
|
|
rtmp.rt_time = u->ut_time;
|
|
r = &rtmp;
|
|
|
|
/* Write entry to rtmp */
|
|
tty_slot = ttyslot();
|
|
|
|
if (tty_slot > 0 && (rtmp_fd = open("/etc/rtmp", O_WRONLY|O_CREAT, 0644)) >= 0) {
|
|
lseek(rtmp_fd, (long) (tty_slot * sizeof(struct rtmp)), 0);
|
|
write(rtmp_fd, (char *) r, sizeof(struct rtmp));
|
|
close(rtmp_fd);
|
|
}
|
|
#endif
|
|
#if defined(AIXV3) && !defined(_POWER)
|
|
/* Log the lastlogin data .. RK 09.13.93 */
|
|
/** in AIX 4.1 this is taken care of during authentication **/
|
|
if(type == USER_PROCESS) {
|
|
int loginType;
|
|
char tempTtyName[128];
|
|
char *hostname;
|
|
|
|
GetLoginInfo(d, &loginType, tempTtyName, &hostname);
|
|
time(&last_login.stime);
|
|
|
|
if(line) {
|
|
Debug("tty_last_login is (line=%s)\n",line);
|
|
last_login.stty = (char *)malloc(strlen(line) + 1);
|
|
strcpy(last_login.stty,line);
|
|
} else {
|
|
last_login.stty = (char *)malloc(strlen(tempTtyName) + 1);
|
|
strcpy(last_login.stty,tempTtyName);
|
|
}
|
|
|
|
last_login.shost = (char *) malloc (MAXHOSTNAMELEN);
|
|
if (hostname == NULL) {
|
|
gethostname (last_login.shost , MAXHOSTNAMELEN);
|
|
} else {
|
|
strncpy(last_login.shost, hostname, MAXHOSTNAMELEN);
|
|
last_login.shost[MAXHOSTNAMELEN -1] = '\0';
|
|
}
|
|
|
|
Debug("logging lastlogin entry (user=%s)\n",user);
|
|
dt_lastlogin(user,&last_login);
|
|
free(last_login.stty);
|
|
free(last_login.shost);
|
|
}
|
|
#endif
|
|
|
|
#endif /* !sun */
|
|
#endif /* !CSRG_BASED */
|
|
}
|
|
|
|
|
|
|
|
|
|
/***************************************************************************
|
|
*
|
|
* UtmpIdOpen
|
|
*
|
|
* see if a particular utmp ID is available
|
|
*
|
|
* return codes: 0 = ID is in use
|
|
* 1 = ID is open
|
|
***************************************************************************/
|
|
|
|
int
|
|
UtmpIdOpen( char *utmpId )
|
|
{
|
|
int status = 1; /* return code */
|
|
|
|
#if !defined(CSRG_BASED) || defined(HAS_PAM_LIBRARY)
|
|
#ifdef HAS_PAM_LIBRARY
|
|
struct utmpx *u; /* pointer to entry in utmp file */
|
|
|
|
while ( (u = getutxent()) != NULL ) {
|
|
#else
|
|
struct utmp *u; /* pointer to entry in utmp file */
|
|
|
|
while ( (u = getutent()) != NULL ) {
|
|
#endif
|
|
|
|
if ( (strncmp(u->ut_id, utmpId, 4) == 0 ) &&
|
|
u->ut_type != DEAD_PROCESS ) {
|
|
|
|
status = 0;
|
|
break;
|
|
}
|
|
}
|
|
|
|
#ifdef HAS_PAM_LIBRARY
|
|
endutxent();
|
|
#else
|
|
endutent();
|
|
#endif
|
|
#endif
|
|
return (status);
|
|
}
|
|
|
|
|
|
|
|
#if defined(AIXV3) && !defined(_POWER)
|
|
void dt_lastlogin ( user, llogin)
|
|
char * user;
|
|
struct lastlogin * llogin;
|
|
{
|
|
char *tmp_char;
|
|
char *tmp_int;
|
|
/*
|
|
* We are loading all the lastlogin info into a struct and then dealing
|
|
* with that so if the technique of storing the values is redone it
|
|
* will be easy
|
|
*/
|
|
/* set id back to root */
|
|
seteuid(0);
|
|
/*
|
|
* Open up the user data base
|
|
*/
|
|
setuserdb(S_READ | S_WRITE);
|
|
|
|
/*
|
|
* setting new unsuccessful login attempts times
|
|
*/
|
|
if (llogin->ftime) {
|
|
/*
|
|
* Get the old Failure count and increment it
|
|
*/
|
|
if (getuserattr(user, S_ULOGCNT, &tmp_int, SEC_INT) != 0)
|
|
llogin->fcount = 0;
|
|
else
|
|
llogin->fcount = (int)tmp_int;
|
|
|
|
/*
|
|
* put all the new data
|
|
*/
|
|
putuserattr(user, S_ULASTTTY, llogin->ftty, SEC_CHAR);
|
|
llogin->fcount++;
|
|
putuserattr(user, S_ULOGCNT, (void *)llogin->fcount,
|
|
SEC_INT);
|
|
putuserattr(user, S_ULASTTIME, (void *)llogin->ftime,
|
|
SEC_INT);
|
|
putuserattr(user, S_ULASTHOST, llogin->fhost, SEC_CHAR);
|
|
putuserattr(user, NULL, NULL, SEC_COMMIT);
|
|
|
|
/*
|
|
* Close data base and zero out indicator fields
|
|
*/
|
|
llogin->ftime = 0;
|
|
llogin->fcount = 0;
|
|
}
|
|
|
|
/*
|
|
* New Successful login data
|
|
*/
|
|
if (llogin->stime) {
|
|
putuserattr(user, S_LASTTIME, (void *)llogin->stime,
|
|
SEC_INT);
|
|
putuserattr(user, S_LASTTTY, llogin->stty, SEC_CHAR);
|
|
Debug("hostname logged is %s\n",llogin->shost);
|
|
putuserattr(user, S_LASTHOST, llogin->shost, SEC_CHAR);
|
|
putuserattr(user, S_ULOGCNT, 0, SEC_INT);
|
|
putuserattr(user, NULL, NULL, SEC_COMMIT);
|
|
}
|
|
enduserdb();
|
|
}
|
|
#endif
|
|
|