/* $Id: sessions.c,v 1.1 2004/03/14 13:15:31 thivillon Exp $ */
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <utmp.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <arpa/inet.h>
#include <syslog.h>
#include <netdb.h>
#include <time.h>
#include "../config.h"
#ifdef HAVE_SYS_TIME_H
#include <sys/time.h>
#endif
#ifdef HAVE_LIBUTIL_H
#include <libutil.h>
#endif
#ifdef HAVE_SYS_FILE_H
#include <sys/file.h>
#endif
#ifdef HAVE_SYS_FILIO_H
#include <sys/filio.h>
#endif
#include "ssltun.h"
#include "session.h"
int wtmpfd = -1;
extern void initsetproctitle(int argc, char **argv, char **envp);
#ifndef HAVE_SETPROCTITLE
extern void setproctitle(char *fmt, ...);
#endif
void purge_wtmp(char *wtmpname, int pid)
{
ssltunnel_utmp_t mywtmp;
int wtmpfd = -1;
struct flock locks;
if ((wtmpfd = open (wtmpname , O_RDWR|O_CREAT,
S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH )) < 0) {
fprintf (stderr, "Can not open %s : %s\n",
wtmpname, strerror(errno));
return;
}
memset (&locks, 0, sizeof(locks));
locks.l_type = F_WRLCK;
locks.l_whence = SEEK_SET;
if (fcntl ( wtmpfd, F_SETLKW , &locks ) < 0) {
fprintf (stderr, "Unable to lock %s : %s\n",
wtmpname, strerror(errno));
goto catch;
}
if (lseek ( wtmpfd, 0, SEEK_END) == -1) {
fprintf (stderr, "Unable to seek %s : %s\n",
wtmpname, strerror(errno));
close (wtmpfd);
goto catch ;
}
memset (&mywtmp, 0, sizeof (ssltunnel_utmp_t));
sprintf(mywtmp.ut_line, "%d", pid);
time ( &mywtmp.ut_time);
if (write (wtmpfd, &mywtmp, sizeof (ssltunnel_utmp_t)) < 0 ) {
fprintf(stderr, "Unable to write %s : %s\n",
wtmpname, strerror(errno));
}
fsync( wtmpfd );
catch:
locks.l_type = F_UNLCK;
fcntl ( wtmpfd, F_SETLKW , &locks );
close (wtmpfd);
return ;
}
struct pppsession *read_sessions (char *filename)
{
struct pppsession *firstsession = NULL;
struct pppsession *next,*lastrec,*last,*new;
int num;
ssltunnel_utmp_t mywtmp;
int wtmpfd;
if ((wtmpfd = open (filename , O_RDONLY,
S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH )) < 0) {
fprintf (stderr, "Can not open %s : %s\n",
filename, strerror(errno));
return NULL;
}
while ((num = read( wtmpfd, &mywtmp, sizeof (mywtmp))) == sizeof (mywtmp)) {
next = firstsession;
last = NULL;
lastrec = NULL;
for (next = firstsession ; next != NULL ; next = next->next) {
if (!strcmp(next->pid,mywtmp.ut_line)) lastrec = next;
if (next->next == NULL) last = next;
}
/* Stop */
if ((lastrec != NULL) && (lastrec->stop == 0)) lastrec->stop = mywtmp.ut_time;
if (mywtmp.ut_name[0] != 0 || mywtmp.ut_host[0] != 0) {
/* New session */
new = malloc ( sizeof (struct pppsession) );
memset ( new, 0 , sizeof (struct pppsession) );
new->pid = strdup (mywtmp.ut_line);
new->username = strdup (mywtmp.ut_name);
new->host = strdup (mywtmp.ut_host);
new->start = mywtmp.ut_time;
if (last != NULL) last->next = new;
else firstsession = new;
}
}
close (wtmpfd);
return firstsession;
}
void dump_sessions (int all, int resolve, struct pppsession *sessions) {
struct pppsession *next;
char bufftime_stop[80],bufftime_start[80];
char *hostname;
struct hostent *myhost;
struct in_addr pin;
time_t session_time;
char *ptr;
next = sessions;
while (next != NULL) {
if (all || !(next->stop)) {
strftime(bufftime_start, 79, "%m/%d %R", localtime(&next->start));
bufftime_stop[0]= '\0';
if (next->stop) {
ptr = bufftime_stop;
ptr += strftime(bufftime_stop, 79, "%R", localtime(&next->stop));
session_time = difftime(next->stop, next->start);
if (session_time >= 86400) {
snprintf(ptr, 79 - (ptr - bufftime_stop), " (%d+%02d:%02d)",
(int) session_time / 86400, (int) (session_time % 86400)/3600,
(int) (session_time % 3600)/60);
}
else {
snprintf(ptr, 79 - (ptr - bufftime_stop), " (%02d:%02d)",
(int) session_time/3600,
(int) (session_time % 3600)/60);
}
}
hostname = next->host;
if (resolve) {
inet_aton(next->host , &pin);
myhost = gethostbyaddr ( (char *) &pin,
sizeof ( struct in_addr),
PF_INET );
if (myhost && myhost->h_name) hostname = myhost->h_name;
}
else hostname = next->host;
printf ("%-15.15s %8s %-25.25s %12.12s %s\n",
next->username,
next->pid,
hostname,
bufftime_start,
bufftime_stop);
}
next = next->next;
}
return;
}
void clean_sessions(char *filename) {
struct pppsession *next,*curr;
int mypid;
next = read_sessions (filename);
while (next != NULL) {
if (!next->stop) {
/* Crashed */
mypid = atoi(next->pid);
update_wtmp(filename, "", mypid, "");
}
curr = next;
next = next->next;
free(curr);
}
return;
}
void update_wtmp(char *filename, char *user, int pid, char *host)
{
ssltunnel_utmp_t mywtmp;
char buffpid[32];
char *cn=NULL;
char *ptr;
int foundcn = 0;
struct flock locks;
if (wtmpfd == -1) {
if ((wtmpfd = open (filename , O_RDWR|O_CREAT,
S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH )) < 0) {
syslog (LOG_ERR, "Can not open %s : %s",
filename, strerror(errno));
return;
}
}
memset (&locks, 0, sizeof(locks));
locks.l_type = F_WRLCK;
locks.l_whence = SEEK_SET;
if (fcntl ( wtmpfd, F_SETLKW , &locks ) < 0) {
syslog (LOG_ERR, "Unable to lock %s : %s",
filename, strerror(errno));
return ;
}
if (lseek ( wtmpfd, 0, SEEK_END) == -1) {
syslog (LOG_ERR, "Unable to seek %s : %s",
filename, strerror(errno));
goto catch ;
}
memset (&mywtmp, 0, sizeof (ssltunnel_utmp_t));
sprintf(buffpid, "%d", pid);
strncpy ( mywtmp.ut_line, buffpid, UT_LINESIZE -1) ;
strncpy ( mywtmp.ut_host, host, UT_HOSTSIZE -1) ;
cn = strdup(user);
for (ptr = strtok(cn,"/"); ptr; ptr = strtok(NULL,"/")) {
if (!strncasecmp(ptr,"cn=",3)) {
strncpy ( mywtmp.ut_name, ptr+3, UT_NAMESIZE -1) ;
setproctitle("server for %s", mywtmp.ut_name);
foundcn=1;
}
}
if (!foundcn) {
strncpy ( mywtmp.ut_name, user, UT_NAMESIZE -1) ;
setproctitle("server for %s", mywtmp.ut_name);
}
free(cn);
time ( & mywtmp.ut_time);
if (write (wtmpfd, &mywtmp, sizeof (ssltunnel_utmp_t)) < 0 ) {
syslog (LOG_ERR, "Unable to write %s : %s",
filename, strerror(errno));
goto catch ;
}
fsync( wtmpfd );
catch:
/* We unlock the file but keep it open to come back
at end of connection after privilege drop */
locks.l_type = F_UNLCK;
fcntl ( wtmpfd, F_SETLKW , &locks );
return ;
}
/*# vim:set expandtab:set syntax=c:*/
syntax highlighted by Code2HTML, v. 0.9.1