Subject ibsecure source
Author Jim Starkey
The downloads have tapered off, the cat is thoroughly out of the
bag, and our incoming DSL provider doesn't look like they're
gone to start service before out outgoing provider dies (tomorrow).

Attached is the source of ibsecure. Could somebody find a good
place to post it? It is a single file, no header, and should
compile anywhere Interbase has been, excepting Novell or MPE/XL
(yuckola).

We are likely to lose our e-mail for a few days. So until the
the new line lights up, so long and thanks for all the fish.
----------

#ifdef _WIN32
#include <windows.h>
#include <io.h>
#undef va_start
#undef va_end
#endif

#include <string.h>
#include <stdio.h>

#ifdef VMS
#include <stat.h>
#include <file.h>
#define SUCCESS 1
#define FAILURE 0
#else
#include <fcntl.h>
#include <memory.h>
#include <sys/types.h>
#include <sys/stat.h>
#endif

#include <stdlib.h>
#include <varargs.h>
#include <time.h>

#ifndef VMS
#ifndef _WIN32
#include <dirent.h>
#endif
#endif

#ifndef _O_BINARY
#define _O_BINARY 0
#endif

#ifndef NULL
#define NULL 0
#endif

#ifndef SUCCESS
#define SUCCESS 0
#define FAILURE 1
#endif

#define VERSION "V1.0"
#define TRUE 1
#define FALSE 0
#define LOGFILE "ibsecure.log"
#define BUFFER_SIZE 64000
#define INSECURE "-insecure"
#define SECURE "-secure"
#define MAX_WORD 20
#define MAX_FILE_NAME 256

#define VERBOSE 1
#define REPORT_ERRORS 2
#define CHECK_ONLY 4
#define UNDO 8

static char *libNames[] = {
#ifdef _WIN32
"c:\\program files\\interbase\\bin\\ibserver.exe",
"c:\\program files\\borland\\interbase\\bin\\ibserver.exe",
#else
#ifdef VMS
#else
"/opt/interbase/bin/ibserver",
"/usr/interbase/lib/gds.sl", /* hp/ux */
"/usr/interbase/lib/gds_b.a", /* hp/ux */
"/usr/lib/libgds.so",
"/usr/lib/gds.a",
"/usr/lib/libgds.a",
"/usr/lib/libgds_b.a",
"/usr/lib/libgdslib.so.0.1",
"/usr/lib/libgdsflib.so.1.0",
#endif
#endif
0
};

static char *directories[] = {
#ifdef _WIN32
"c:\\program files\\interbase\\bin",
#else
#ifdef VMS
#else
"/opt/interbase/bin",
#endif
#endif
NULL
};

#ifdef _WIN32
#define ROOT_DIR "RootDirectory"
static char *registries [] = {
"SOFTWARE\\Interbase Corp\\Interbase\\CurrentVersion", "\\Bin\\ibserver.exe",
"SOFTWARE\\Borland\\Interbase\\CurrentVersion", "\\Bin\\ibserver.exe",
NULL
};
#endif

typedef struct word {
char *name;
char *word;
char *replacement;
unsigned int length;
} Word;

#define WORD(name,string) name, string, NULL, sizeof (string),
#define ACCOUNT 0
#define PASSWORD 1
#define UDF 2
#define INLINE 3

static Word words [10] = {
WORD ("account", "politically")
WORD ("password", "correct")
WORD ("udf", "XYZZY_PLUGH_PLOVER!")
};

#ifdef INLINE
static unsigned char inline1 [] = { 0xc7, 0x02 };
static unsigned char inline2 [] = { 0xc7, 0x42, 0x04 };
static char *genInline();
static char *genInlinePassword();
#endif

static char *boilerplate =
"This program is licensed from IBPhoenix, Inc. for use at\n\
one site. IBPhoenix has provided this program free of charge\n\
under the license which follows. Please read the license and\n\
usage instructions carefully before running the program.\n\n\
Do not use any copy of this program that you did not download from \n\
IBPhoenix.\n\n\
For additional information, please check:\n\
www.ibphoenix\\sec1.html or contact:\n\n\
(email) aharrison@...\n\
(phone) (USA) 978 526-1376\n\
(fax) (USA) 978 526-7728\n\
copyright (c) 2000, 2001 by IBPhoenix\n\n";

static char *license =
"LICENSE\n\n\
This program is provided without charge by IBPhoenix.\n\
In consideration for its use, you agree: \n\n\
1) that the program is the property of IBPhoenix, which\n\
authorizes you to run it at one site and to maintain archive\n\
copies. \n\n\
2) that decompilation and reverse engineering of this program\n\
are explicitly forbidden. \n\n\
3) that you will not redistribute this program whether with or\n\
without charge. \n\n\
4) that the program is provided without warrantee and subject\n\
to this disclaimer: \n\n\
THIS PROGRAM IS PROVIDED ON AN \"AS IS\" BASIS, WITHOUT WARRANTY\n\
OF ANYKIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT\n\
LIMITATION, WARRANTIES THAT THE PROGRAM IS FREE OF DEFECTS,\n\
MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE OR NON-INFRINGING.\n\
THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL PART OF \n\
THIS LICENSE. NO USE OF THE PROGRAM IS AUTHORIZED HEREUNDER\n\
EXCEPT UNDER THIS DISCLAIMER.\n\n\
5) that violation of any of these conditions invalidates\n\
this license. \n\n";


static char *switchInfo [] = {
"Valid switches are:",
" -a Automatic mode (known files and directories)",
" -v Verbose mode",
" -u Undo previous changes",
" -n Check files for trap doors without replacement",
" -s Replace occurrences of string with randomness",
" -A Specify explicit account name (not recommended)",
" -P Specify explicit password (not recommended)",
" -l Specify explicit log file",
#ifndef VMS
" -d Scan directory",
#endif
"",
NULL
};

static char *replacementWords [3];
static FILE *logFile;
static char *logFileName = LOGFILE;
static unsigned char buffer [BUFFER_SIZE];
static char chars [MAX_FILE_NAME];
static int changedFiles;
static int insecureFiles;
static char commandLine [1024];

static int rewriteFile();
static void logMessage();
static int ioError();
static void mergeFileName ();
static char *randomness();
static int revert();
static void scanDir();

int main (argc, argv)
int argc;
char **argv;
{
char **end = argv + argc;
char temp [MAX_FILE_NAME];
char *p = temp;
int flags = 0;
int all = FALSE;
int n;
Word *word;
printf (boilerplate);
printf (license);
srand( (unsigned)time( NULL ) );

for (word = words; word->word; ++word)
{
chars [word->word [0]] = 1;
word->replacement = p;
p = randomness (p, word->length - 1);
}

#ifdef INLINE
p = genInlinePassword(p, word++);
#endif

p = commandLine;

for (n = 0; n < argc; ++n)
{
char *q = argv [n];
while (*q && p < commandLine + sizeof (commandLine) - 1)
*p++ = *q++;
*p++ = ' ';
}

*p = 0;

for (argv++; argv < end;)
{
char *p = *argv++;
if (p[0] == '-')
switch (p[1])
{
case 'a':
all = TRUE;
break;

case 'u':
flags |= UNDO;
break;

case 'v':
flags |= VERBOSE | REPORT_ERRORS;
break;

case 'n':
flags |= CHECK_ONLY | VERBOSE;
break;

case 'l':
logFileName = *argv++;
break;

case 's':
word->word = *argv++;
word->name = word->word;
word->length = strlen (word->word) + 1;
p = randomness (p, word->length - 1);
word++;
break;

case 'f':
if (!rewriteFile (p, TRUE))
return FAILURE;
break;

case 'A':
word = words + ACCOUNT;
if (strlen (*argv) >= word->length)
{
printf ("replacement password is too long\n");
return FAILURE;
}
word->replacement = *argv++;
break;

case 'P':
word = words + PASSWORD;
if (strlen (*argv) >= word->length)
{
printf ("replacement password is too long\n");
return FAILURE;
}
word->replacement = *argv++;
p = genInlinePassword(p);
break;

#ifndef VMS
case 'd':
scanDir (*argv++, flags);
break;
#endif

default:
printf ("don't understand switch \"%s\"\n", p);
for (n = 0; switchInfo [n]; ++n)
printf ("%s\n", switchInfo [n]);
return FAILURE;
}
else
if (!rewriteFile (p, flags | REPORT_ERRORS))
return FAILURE;
}

if (all)
{
for (argv = libNames; *argv; ++argv)
rewriteFile (*argv, flags);

for (argv = directories; *argv; ++argv)
scanDir (*argv, flags);
#ifdef _WIN32
for (argv = registries; *argv; argv += 2)
{
HKEY key;
LONG result = RegOpenKey (HKEY_LOCAL_MACHINE, *argv, &key);
if (result == ERROR_SUCCESS)
{
char path [MAX_FILE_NAME];
LONG length = sizeof (path);
result = RegQueryValueEx (key, ROOT_DIR, NULL, NULL, path, &length);
if (result == ERROR_SUCCESS)
{
char fileName [MAX_FILE_NAME];
char *relPath = argv [1];
if (strlen (path) + strlen (relPath) < sizeof (fileName))
{
strcpy (fileName, path);
strcat (fileName, relPath);
rewriteFile (fileName, flags);
}
}
RegCloseKey (key);
}
}
#endif
}

if (logFile)
fclose (logFile);

if (changedFiles)
if (changedFiles == 1)
printf ("%d insecure file was rewritten\n", changedFiles);
else
printf ("%d insecure files were rewritten\n", changedFiles);

if (insecureFiles)
{
if (insecureFiles == 1)
printf ("At least %d file with active trap doors was found\n", insecureFiles);
else
printf ("At least %d files with active trap doors were found\n", insecureFiles);
}
else
printf ("No insecure files were found\n");

return SUCCESS;
}

static void logMessage (flags, text, va_alist)
int flags;
char *text;
va_dcl
{
char timestamp [30], *p;
time_t tm = time (0);
va_list args;
va_start (args);

if (!logFile)
{
logFile = fopen (logFileName, "a");
if (!logFile)
{
fprintf (stderr, "can't open logfile\n");
perror (logFileName);
exit (1);
}
logMessage (flags, "ibsecure version %s: %s\n", VERSION, commandLine);
}

strcpy (timestamp, asctime (localtime (&tm)));
for (p = timestamp; *p && *p != '\n'; ++p)
;
*p = 0;
fprintf (logFile, "%s: ", timestamp);
vfprintf (logFile, text, args);

if (flags & VERBOSE)
vprintf (text, args);
}

static int ioError (flags, text, fileName)
char *text;
char *fileName;
{
if (!(flags & VERBOSE))
fprintf (stderr, text, fileName);
perror (fileName);
logMessage (flags, text, fileName);

return FALSE;
}

static int rewriteFile (fileName, flags)
char *fileName;
int flags;
{
int fd;
int outFd = 0;
unsigned char *p;
unsigned char *end;
int eof = FALSE;
int offset = 0;
int hits = 0;
struct stat statBuf;
int length = 0;
char tempFileName [MAX_FILE_NAME];
Word *word;

if (stat (fileName, &statBuf))
{
if (flags & REPORT_ERRORS)
ioError (flags, "can't stat file \"%s\"\n", fileName);
return FALSE;
}

if (statBuf.st_mode & S_IFDIR)
return FALSE;

if (flags & VERBOSE)
printf ("%s:\n", fileName);

if (flags & UNDO)
return revert (fileName, flags);

if ((fd = open (fileName, O_RDONLY | _O_BINARY)) < 0)
{
if (flags & REPORT_ERRORS)
ioError (flags, "can't open file \"%s\n", fileName);
return FALSE;
}

mergeFileName (fileName, SECURE, tempFileName);

if (!(flags & CHECK_ONLY))
{
if ((outFd = open (tempFileName, O_CREAT | O_TRUNC | O_WRONLY | _O_BINARY, statBuf.st_mode | S_IWRITE)) < 0)
{
ioError (flags, "can't create file \"%s\n", tempFileName);
close (fd);
return FALSE;
}
#ifndef VMS
#ifndef _WIN32
if (fchown (outFd, statBuf.st_uid, statBuf.st_gid))
ioError (flags, "can't change owner of \"%s\"\n", tempFileName);
#endif
#endif
}

for (offset = 0;;)
{
if (length > 0 && outFd > 0)
if (write (outFd, buffer, length) != length)
{
ioError (flags, "write failed on \"%s\"\n", tempFileName);
close (fd);
close (outFd);
return FALSE;
}
if (eof)
break;
length = read (fd, buffer, sizeof (buffer));
if (length <= 0)
break;
offset += length;
for (p = buffer, end = p + length; p < end; ++p)
if (chars [*p])
{
char c = *p;
if (!eof && (p + MAX_WORD > end))
{
int l = p - buffer;
if (l > 0 && outFd > 0)
if (write (outFd, buffer, l) != l)
{
ioError (flags, "write failed on \"%s\"\n", tempFileName);
close (fd);
close (outFd);
return FALSE;
}
l = end - p;
memcpy (buffer, p, l);
length = read (fd, buffer + l, sizeof (buffer) - l);
if (length > 0)
offset += length;
else
eof = TRUE;
length += l;
p = buffer;
end = buffer + length;
}

for (word = words; word->word; ++word)
if (!memcmp (word->word, p, word->length))
{
int hit = offset - (end - p);
if (hits == 0)
++insecureFiles;
++hits;
if (flags & VERBOSE)
printf (" trapdoor %s at %d\n", word->name, hit);
if (p [-1])
printf (" *** suspect ***\n");
memcpy (p, word->replacement, word->length);
}
}
}

close (fd);

if (outFd > 0)
close (outFd);

if (!(flags & CHECK_ONLY))
if (hits)
{
char saveFileName [MAX_FILE_NAME];
mergeFileName (fileName, INSECURE, saveFileName);
if (rename (fileName, saveFileName))
{
ioError (flags, "Couldn't rename file \"%s\"\n", fileName);
return FALSE;
}
else
logMessage (flags, "Insecure file %s renamed to %s\n", fileName, saveFileName);
if (rename (tempFileName, fileName))
{
ioError (flags, "Couldn't rename file \"%s\"\n", tempFileName);
return FALSE;
}
else
{
--insecureFiles;
++changedFiles;
logMessage (flags, "Created replacement secure file %s\n", fileName);
}
}
else
unlink (tempFileName);

return TRUE;
}

static void mergeFileName (fileName, modifier, buffer)
char *fileName;
char *modifier;
char *buffer;
{
char *b = buffer;
char *f, *m;

for (f = fileName; *f && *f != '.';)
*b++ = *f++;

for (m = modifier; *m;)
*b++ = *m++;

while (*f)
*b++ = *f++;

*b = 0;
}

static char *randomness (ptr, length)
char *ptr;
int length;
{
char *p = ptr;
char *end = ptr + length;

while (p < end)
{
int n = rand() % 256;
if (n)
*p++ = n;
/***
int n = rand() % 26;
*p++ = 'A' + n;
***/
}

*p++ = 0;

return p;
}

static int revert (fileName, flags)
char *fileName;
int flags;
{
char secure [MAX_FILE_NAME];
char insecure [MAX_FILE_NAME];
int fd;

mergeFileName (fileName, SECURE, secure);
mergeFileName (fileName, INSECURE, insecure);

if ((fd = open (insecure, O_RDONLY | _O_BINARY)) < 0)
return FALSE;

close (fd);

if (!rename (fileName, secure))
logMessage (flags, "Undo: file %s renamed to %s\n", fileName, secure);

if (!rename (insecure, fileName))
logMessage (flags, "Undo: file %s renamed to %s\n", insecure, fileName);

++insecureFiles;

return TRUE;
}


static void scanDir (directory, flags)
char *directory;
int flags;
{
#ifdef _WIN32
HANDLE handle;
WIN32_FIND_DATA data;
char wildCard [MAX_FILE_NAME];
int entry = TRUE;

if (strlen (directory) + 2 >= sizeof (wildCard))
return;

strcpy (wildCard, directory);
strcat (wildCard, "\\*");

for (handle = FindFirstFile (wildCard, &data);
(handle != INVALID_HANDLE_VALUE) && entry;
entry = FindNextFile (handle, &data))
if (!(data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
{
char fileName [MAX_FILE_NAME];
if (strlen (directory) + 1 + strlen (data.cFileName) < sizeof (fileName))
{
strcpy (fileName, directory);
strcat (fileName, "\\");
strcat (fileName, data.cFileName);
if (!strstr (fileName, INSECURE))
rewriteFile (fileName, flags);
}
}

FindClose (handle);
#else
#ifndef VMS
struct dirent *dir;
DIR *handle = opendir (directory);

if (handle)
{
while (dir = readdir (handle))
{
char fileName [MAX_FILE_NAME];
if (strlen (directory) + 1 + strlen (dir->d_name) < sizeof (fileName))
{
strcpy (fileName, directory);
strcat (fileName, "/");
strcat (fileName, dir->d_name);
if (fileName [0] != '.' && !strstr (fileName, INSECURE))
rewriteFile (fileName, flags);
}
}
closedir (handle);
}
#endif
#endif
}

#ifdef INLINE
static char *genInline (ptr, len1, inline1, string, len2, inline2)
char *ptr;
int len1;
unsigned char *inline1;
char *string;
int len2;
unsigned char *inline2;
{
int n;
char *p = ptr;
chars [inline1[0]] = 1;

for (n = 0; n < len1; ++n)
*p++ = inline1 [n];

for (n = 0; n < 4; ++n)
*p++ = string [n];

for (n = 0; n < len2; ++n)
*p++ = inline2 [n];

for (n = 4; n < 8; ++n)
*p++ = string [n];

return p;
}

static char* genInlinePassword(ptr, word)
char *ptr;
Word *word;
{
char *p = ptr;
word->name = "inline password";
word->word = p;
p = genInline (p, sizeof (inline1), inline1,
words [PASSWORD].word,
sizeof (inline2), inline2);
word->length = p - word->word;
word->replacement = p;
p = genInline (p, sizeof (inline1), inline1,
words [PASSWORD].replacement,
sizeof (inline2), inline2);

return p;
}
#endif

----------



Jim Starkey

[Non-text portions of this message have been removed]