/* $Id: sessions.c,v 1.1 2004/03/14 13:15:31 thivillon Exp $ */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "../config.h" #ifdef HAVE_SYS_TIME_H #include #endif #ifdef HAVE_LIBUTIL_H #include #endif #ifdef HAVE_SYS_FILE_H #include #endif #ifdef HAVE_SYS_FILIO_H #include #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:*/