home *** CD-ROM | disk | FTP | other *** search
- /*
- * FolkScan.cc -- An RPC network scanning utility.
- * Copyright (C) 1992 Cory West
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License, version 1, as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- */
-
- #include <std.h>
- #include <utmp.h>
- #include <rpc/rpc.h>
- #include <rpcsvc/rusers.h>
- #include <stdio.h>
- #include <String.h>
- #include <string.h>
- #include <bool.h>
- #include <iostream.h>
- #include <time.h>
- #include <curses.h>
- #include "List.h"
-
- // Don't forget -lcurses, -ltermcap, and -lrpcsvc when compiling
-
- // These have to be externed as C functions because the header
- // file doesn't include the damn prototypes. I wish the entire
- // world were C++!
- extern "C" rnusers(char*);
- extern "C" rusers(char*, utmpidlearr*);
-
-
- main(int argc, char** argv)
- {
- if (argc == 1)
- // Print out a usage message
- {
- cerr << "FolkScan v2.2, Copyright (C) 1992 Cory West <corywest@rice.edu>"
- << "\n\n"
- << "FolkScan comes with ABSOLUTELY NO WARRANTY. FolkScan is free\n"
- << "software and may be distributed under the conditions outlined\n"
- << "in the GNU General Public License, version 1."
- << "\n\n"
- << "You should have received a copy of the GNU General Public\n"
- << "License along with this program; if not, write to the Free\n"
- << "Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139,\n"
- << "USA."
- << "\n\n"
- << "Usage: -u user1 ... (Users to watch.)\n"
- << " -h host1 ... (Registered RPC hosts to watch.)\n"
- << " -p interval (Time between polls in seconds.)\n"
- << " -B (Run in the background. Send messages to stderr.)\n"
- << " -D (Include debugging info. Not available with -B.)\n";
- cerr.flush();
- exit(1);
- }
-
- // A workspace for generating messages
- char ErrorBuffer[COLS];
-
- // Some state variables
- bool RunningInBackground = FALSE;
- bool SeeingUsers = TRUE;
- bool DEBUGMODE = FALSE;
-
- // Default polltime is 60 seconds
- int PollTime = 60;
-
- // Our data holders
- List UserList;
- List HostList;
-
- // Windows if we need them
- WINDOW *w1, *w2, *w3, *w4, *w5, *w6;
-
- // This is kind of a yucky method for digging out the
- // host and user information, but we only do it once,
- // so it's O(1).
-
- for (int i = 1; i < argc; i++)
- {
- // Loop on all the command line arguments
-
- if (argv[i][0] == '-')
- {
- // It's a command line switch
- if (strlen(argv[i]) != 2)
- // We have a bad switch.
- {
- strcpy(ErrorBuffer, "Bad command line switch: ");
- strcat(ErrorBuffer, argv[i]);
- strcat(ErrorBuffer, " ignored.\n");
- cerr << ErrorBuffer;
- }
- else
- {
- switch (argv[i][1])
- {
- case 'u':
- // We're seeing users
- SeeingUsers = TRUE;
- break;
- case 'h':
- // We are seeing hosts
- SeeingUsers = FALSE;
- break;
- case 'p':
- // We have a time coming in; get it
- // and manually skip the next argv entry.
- PollTime = atoi(argv[i+1]);
- if (PollTime < 60)
- {
- cerr << "\007Poll time cannot be less than 60 seconds!\n"
- << "Poll time changed to 60 seconds!\n";
- PollTime = 60;
- }
- i++;
- break;
- case 'D':
- // This is for curious people.
- DEBUGMODE = TRUE;
- break;
- case 'B':
- RunningInBackground = TRUE;
- break;
- default:
- // We got a bad switch.
- strcpy(ErrorBuffer, "Bad command line switch: ");
- strcat(ErrorBuffer, argv[i]);
- strcat(ErrorBuffer, " ignored.\n");
- cerr << ErrorBuffer;
- break;
- }
- }
- }
- else
- // It's a name or host
- {
- if (SeeingUsers)
- UserList.unify(argv[i]);
- else
- HostList.unify(argv[i]);
- }
- }
-
- if (RunningInBackground)
- if (DEBUGMODE)
- {
- cerr << "Debug mode not available when running in background.\n"
- << "Debug mode disabled.\n";
- DEBUGMODE = FALSE;
- }
-
- if (!RunningInBackground)
- // Set up curses windows
- {
- initscr();
- w2=newwin(4,COLS,0,0);
- w1=newwin(LINES-12,COLS,4,0);
- w3=newwin(1,COLS,LINES-10,0);
- w5=newwin(2,COLS,LINES-8,0);
- w6=newwin(1,COLS,LINES-9,0);
- w4=newwin(6,COLS,LINES-6,0);
- wclear(w1); wclear(w2); wclear(w3); wclear(w4); wclear(w5); wclear(w6);
- waddstr(w2, " FolkScan v2.2 \n");
- waddstr(w2, "------------------------------------------------------\n");
- waddstr(w2, "User ID Host Name Time Logged On \n");
- waddstr(w2, "------------------------------------------------------\n");
- wrefresh(w2);
- waddstr(w3, "------------------------------------------------------\n");
- waddstr(w5, " (Please send bug reports to corywest@rice.edu) \n");
- waddstr(w5, "------------------------------------------------------\n");
- wrefresh(w3); wrefresh(w5);
- scrollok(w4, TRUE); scrollok(w1, TRUE);
- waddstr(w6, "\007 *** Another Team Wiess Production *** \n");
- wrefresh(w6);
- }
-
-
- // Ok, now we have entered all this wonderful data, so we need to
- // do something with it.
-
- // Look for users
-
- char reportLineBuffer[54];
- char rNameBuf[9];
-
- utmpidlearr* RemoteUtmpInfo = NULL;
- utmpidle** UtmpIdleArray = NULL;
-
- char host[60];
- int UtmpEntries = 0;
-
- int UserListSize = UserList.GetSize();
- int HostListSize = HostList.GetSize();
- int UsersOnHost = 0;
-
- if (UserListSize == 0)
- {
- if (RunningInBackground)
- cerr << "You did not specify any users to look for.\n";
- else
- {
- waddstr(w4, "You did not specify any users to look for.\n");
- wrefresh(w4);
- }
- }
-
- if (HostListSize == 0)
- {
- if (RunningInBackground)
- cerr << "You did not specify any hosts to check.\n";
- else
- {
- waddstr(w4, "You did not specify any hosts to check.\n");
- wrefresh(w4);
- }
- }
-
- // A cache for unifying names to prevent multiple reports
- // of the same user logged into the same host.
- List cache;
-
- // Make some memory for the rusers call
- int memSize = 40;
- if (DEBUGMODE)
- {
- waddstr(w4, "Setup initial heap size of 40.\n");
- wrefresh(w4);
- }
- RemoteUtmpInfo = new utmpidlearr;
- RemoteUtmpInfo->uia_arr = new utmpidle*[memSize];
- for (int memloop = 0; memloop < memSize; memloop++)
- RemoteUtmpInfo->uia_arr[memloop] = new utmpidle;
-
- while(TRUE)
- {
- HostListSize = HostList.GetSize();
- if (HostListSize == 0)
- {
- if (DEBUGMODE)
- {
- waddstr(w4, "There are currently no hosts to scan for users.\n");
- wrefresh(w4);
- }
- }
-
- for (i = 0; i < HostListSize; i++)
- // For all hosts, do the host check and then update.
- // We want multiple logons to a single host reported
- // only once, but logons to different hosts report once
- // for each host.
- {
- strcpy(host, HostList.GetElement(i));
- UsersOnHost = rnusers(host);
- if (DEBUGMODE)
- {
- sprintf(ErrorBuffer, "There are %i users on ", UsersOnHost);
- strcat(ErrorBuffer, host);
- strcat(ErrorBuffer, ".\n");
- waddstr(w4, ErrorBuffer);
- wrefresh(w4);
- }
-
- if (UsersOnHost == 0)
- // Then there isn't anyone on that host and
- // we shall skip it.
- continue;
- else
- // There are people on the host, so we have to check it.
- {
- // If there are more users than we have space for, we
- // need to size up a bit.
- if (UsersOnHost > memSize)
- {
- if (DEBUGMODE)
- {
- strcpy(ErrorBuffer, "Heap too small for host ");
- strcat(ErrorBuffer, host);
- strcat(ErrorBuffer, ".\n");
- waddstr(w4, ErrorBuffer);
- sprintf(ErrorBuffer,
- "Resizing heap to hold %i entries.\n",
- UsersOnHost);
- waddstr(w4, ErrorBuffer);
- wrefresh(w4);
- }
-
- for (int memloop = 0; memloop < memSize; memloop++)
- delete RemoteUtmpInfo->uia_arr[memloop];
- delete RemoteUtmpInfo->uia_arr;
- delete RemoteUtmpInfo;
- memSize = UsersOnHost + 1;
- RemoteUtmpInfo = new utmpidlearr;
- RemoteUtmpInfo->uia_arr = new utmpidle*[memSize];
- for (memloop = 0; memloop < memSize; memloop++)
- RemoteUtmpInfo->uia_arr[memloop] = new utmpidle;
- }
-
- if (rusers(host, RemoteUtmpInfo) != 0)
- // We had a problem and should report it whether
- // we are in debug mode or not.
- {
- strcpy(ErrorBuffer, "RPC host ");
- strcat(ErrorBuffer, host);
- strcat(ErrorBuffer, " not responding. Still Trying...\n");
- HostList.MarkDead(host);
- if (RunningInBackground)
- cerr << ErrorBuffer;
- else
- {
- waddstr(w4, ErrorBuffer);
- wrefresh(w4);
- }
- continue;
- }
- else
- // We have something in RemoteUtmpInfo.
- // Let's try to get it out.
- {
- // This be how many people are on the machine, including
- // duplicates.
- UtmpEntries = RemoteUtmpInfo->uia_cnt;
- // This is the array of utmpidle structs
- UtmpIdleArray = RemoteUtmpInfo->uia_arr;
-
- // Ok, this is a semi-confusing double loop. The outer
- // loop walks through the entries in the utmp for the
- // current host. The inner loop walks through the static
- // userid data that we are searching for.
-
- for ( int j = 0; j < UtmpEntries; j++)
- {
- // Get the userid out of the utmp entry and
- // cache it.
- strncpy(rNameBuf, (UtmpIdleArray[j]->ui_utmp).ut_name, 8);
- for (int loop = 0; loop < 8; loop++)
- if (rNameBuf[loop] == ' ')
- {
- rNameBuf[loop] = '\000';
- break;
- }
- rNameBuf[8] = '\000';
-
- // We want to make sure that we don't run
- // this loop over duplicate users in the
- // utmp.
-
- if (!cache.unify(rNameBuf))
- continue;
-
- for ( int k = 0; k < UserListSize; k++)
- {
- if (!strcmp(UserList.GetElement(k), rNameBuf))
- // We have a winner! Print him out!
- {
- if (RunningInBackground)
- {
- if(!UserList.Saw(k))
- {
- UserList.Seen(k);
- UserList.MakeDirty(k);
- cerr << "\007User " << rNameBuf << " is on host "
- << host << ".\n";
- }
- else
- UserList.MakeDirty(k);
- }
- else
- {
- strcpy(reportLineBuffer, rNameBuf);
- for ( int l = strlen(rNameBuf); l < 12; l++)
- reportLineBuffer[l] = ' ';
- reportLineBuffer[12] = '\000';
- strcat(reportLineBuffer, host);
- for ( l = strlen(host) + 12; l < 28; l++)
- reportLineBuffer[l] = ' ';
- reportLineBuffer[28] = '\000';
- strcat(reportLineBuffer,
- ctime(&(UtmpIdleArray[j]->ui_utmp).ut_time));
- reportLineBuffer[53] = '\000';
- reportLineBuffer[27] = ' ';
- waddstr(w1, reportLineBuffer);
- }
- }
- }
- }
- }
- }
- // Clean up all of our memory use!
- cache.dump();
- }
- // Remove dead hosts from HostList and
- // update the loop scan size.
- HostList.RemoveDead(w4);
-
- // Update the windows, if appropriate.
- if (!RunningInBackground)
- {
- // Clear the report window
- wrefresh(w1);
- wclear(w1);
- // Move the little blinking indicator amd sleep
- wclear(w6);
- waddstr(w6, " --> Messages <-- \n");
- wmove(w2, 0, 0);
- wrefresh(w6); wrefresh(w2);
- }
- else
- {
- for (int a_loop = 0; a_loop < UserListSize; a_loop++)
- if (UserList.isClean(a_loop) &&
- UserList.Saw(a_loop))
- {
- cerr << "\007User " << UserList.GetElement(a_loop)
- << " has logged off.";
- UserList.UnSee(a_loop);
- }
-
- // Mark everything as clean
- UserList.CleanAll();
- }
-
- // Sleep
- sleep(PollTime);
-
- // Update the windows, if appropriate.
- if (!RunningInBackground)
- {
- wclear(w6);
- waddstr(w6, " *** Checking Systems *** \n");
- wrefresh(w6);
- }
- }
- }
-