//This program is free software: you can redistribute it and/or modify it under the terms #of the GNU General Public License as published by the Free Software Foundation, either #version 3 of the License, or (at your option) any later version. //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, see /* crypt.c */ /* Main program for cryptography */ /* Copyright 1995 Willis E. Howard, III */ /* Willis E. Howard, III email: WEHoward@aol.com mail: POB 1473 Elkhart, IN 46515 */ /* Under MSDOS, this main module provides the interface to various encryption / decryption schemes. */ #include #include #include #include #include #include #include #include "crypt.h" #include "getopt.h" #include "nextfile.h" #include "tempfile.h" /* Documentation for help */ extern char *documentation[]; /* Program name */ char *prog; /* crypt key file name */ char crypt_key_name[_MAX_PATH]; /* Overwrite number for deleted input files with -G */ int overwrite = 0x55; /* Fate of input file with -o */ int delete_mode = DELETE_NORMAL; /* zero file name structure to initialize new file searches */ struct fnames zero_files = { (struct fnames *) 0, {'\0','\0','\0','\0','\0','\0', '\0','\0','\0','\0','\0','\0','\0'} } ; int main(int argc, char *argv[]) { char sDrive[_MAX_DRIVE]; char sDir[_MAX_DIR]; char sFname[_MAX_FNAME]; char sExt[_MAX_EXT]; char *s; int i; FILE *pfile; /* Make needed file names */ if ( _fullpath( crypt_key_name, argv[0], 128 ) == NULL ) { fprintf( stderr, "Could not create full program path name\n"); usage(); exit( 1 ); } /* Get path components */ _splitpath( crypt_key_name, sDrive, sDir, sFname, sExt ); if ( strrchr( crypt_key_name, '.' ) != NULL ) /* delete extension */ *strrchr( crypt_key_name, '.' ) = '\0'; strcat( crypt_key_name, ".KEY" ); for ( s=crypt_key_name; *s; s++ ) /* make name upper case */ if ( islower( *s ) ) *s = toupper( *s ); prog = sFname; for ( s=prog; *s; s++ ) /* make name lower case */ if ( isupper( *s ) ) *s = tolower( *s ); /* Do usage in case there are no arguments */ if ( argc == 1 ) { usage(); exit( 0 ); } /* give help if requested */ if ( give_help( argc, argv ) ) exit( 0 ); /* process crypt key file name */ (void) crypt_key( KEY_FILE, crypt_key_name ); /* setup defaults */ (void) crypt_select( ENCRYPTION_SELECT ); /* process all the arguments in one line */ nextline( argc, argv ); /* erase key from memory */ crypt_key_erase(); exit( 0 ); } /* nextline: First, process help. Then, process all options. Then, process files for encryption. Finally, process commands from a file is -f given. */ void nextline( int argc, char *argv[] ) { char command_file_name[128]; /* command file name from -f */ char output_file_name[128]; /* output file name from -o */ char temporary[128]; /* temporary storage */ char full_file_name[128]; /* constructed file name */ char full_argv_name[_MAX_PATH]; /* set sizes for _splitpath */ char sDrive[_MAX_DRIVE]; char sDir[_MAX_DIR]; char sFname[_MAX_FNAME]; char sExt[_MAX_EXT]; char buffer[513]; /* input line */ char *next_file_name; /* pointer to next file name */ char *cPointer; int c; FILE *fPointer; struct fnames new_files; struct fnames *fnPointer; if ( argc == 1 ) return; /* give help if requested */ if ( give_help( argc, argv ) ) return; /* initialize the file names */ command_file_name[0] = '\0'; output_file_name[0] = '\0'; /* Process all options */ opterr = 0; optind = 0; while ((c = getopt (argc, argv, "edcgGqQf:k:#:o:")) != EOF) switch (c) { case '?': /* unidentified option */ usage(); exit(1); break; case 'e': (void) crypt_select( ENCRYPTION_SELECT ); break; case 'd': (void) crypt_select( DECRYPTION_SELECT ); break; case 'c': copyright(); break; case 'q': /* normal delete */ delete_mode = DELETE_NORMAL; break; case 'Q': delete_mode = DELETE_ALL_NORMAL; /* quick delete, all input files */ break; case 'g': delete_mode = DELETE_DOD; /* DOD delete mode */ break; case 'G': delete_mode = DELETE_ALL_DOD; /* DOD delete, all input files */ break; case 'f': /* get command input from file */ if (command_file_name[0]) /* do this only once per line */ { fprintf( stderr, "Error: Two -f commands on one line\n"); usage(); exit(1); break; } strcpy( command_file_name, optarg ); break; case 'k': /* get encryption key */ crypt_key( KEY_IMMEDIATE, optarg ); if (!strcmp(optarg, "?")) _clearscreen(_GCLEARSCREEN); break; case '#': /* get overwrite for -d or -D */ if (sscanf( optarg, "%d", &overwrite ) != 1) { fprintf( stderr, "Error: Failure to set overwrite number %d\n", optarg); usage(); exit( 1 ); } overwrite &= 255; break; case 'o': /* get output file name */ if (output_file_name[0]) { fprintf( stderr, "Error: Two -o commands on one line.\n"); usage(); exit(1); break; } strcpy( output_file_name, optarg ); break; default: /* This can't happen. */ fprintf (stderr, "%s: Option parse failure\n", prog); usage(); exit(1); break; } /* Process all input files */ if ( output_file_name[0] ) /* if -o option given, process it */ { if (argc - optind == 1) /* only one input file allowed with -o */ { /* input and output files must have different names */ if (!strcmp (argv[optind], output_file_name)) { fprintf( stderr, "Input and output files must have different names.\n"); usage(); exit( 1 ); } if (crypt_file( argv[optind], output_file_name) != 0) /* encrypt file */ exit( 1 ); if ((delete_mode == DELETE_ALL_NORMAL) || (delete_mode == DELETE_ALL_DOD)) delete( delete_mode, argv[optind]); /* delete input file */ } else /* more than one input file with -o option */ { fprintf( stderr, "Not just one input file with -o option.\n"); usage(); exit( 1 ); } } else /* multiple input files may be given with no -o option */ { if (argc > optind) /* if there is at least one input file */ while (optind < argc) /* process them all */ { /* make the full path name of the input file */ if (_fullpath( full_argv_name, argv[optind], 128 ) == NULL ) { fprintf( stderr, "Could not create full path name\n"); usage(); exit( 1 ); } /* Get path components */ _splitpath( full_argv_name, sDrive, sDir, sFname, sExt ); /* The input file name may contain MSDOS wildcard characters. We now preallocate all file names. We do this because we will be rewriting existing files that match MSDOS patterns. This prevents the MSDOS next file function from becomming confused. This is done by chaining a series of structures that contain the file name and a pointer to the next structure. At the end, malloc()ed memory is free()ed. */ new_files = zero_files; /* initialize base structure */ fnPointer = &new_files; /* initialize current pointer */ while ( (next_file_name = nextfile( full_argv_name )) != NULL ) { /* get a new structure */ if ((fnPointer->next = (struct fnames *) malloc( sizeof(struct fnames) )) == NULL) { fprintf(stderr, "malloc failure\n"); usage(); exit( 1 ); } strcpy( fnPointer->name, next_file_name ); /* fill in file name */ fnPointer = fnPointer->next; /* update pointer */ *fnPointer = zero_files; /* initialize new structure */ } /* process all files names */ fnPointer = &new_files; /* reset base pointer */ while (fnPointer->next != 0) /* process all names */ { next_file_name = fnPointer->name; /* get new file name */ fnPointer = fnPointer->next; /* get next pointer */ /* form full name and initialize temporary file name */ sprintf( full_file_name, "%s%s%s", sDrive, sDir, next_file_name); cPointer = tempfile( full_file_name ); if (cPointer == NULL) { fprintf(stderr, "Could not identify a temporary file\n"); usage(); exit( 1 ); } strcpy(temporary, cPointer); /* rename next file to temporary */ if ( rename( full_file_name, temporary ) != 0 ) { fprintf( stderr, "Could not create temporary file\n"); usage(); exit( 1 ); } /* encrypt back to original file name */ if ( crypt_file( temporary, full_file_name ) != 0 ) { /* Encryption failed. Restore as much as possible */ delete( DELETE_NORMAL, full_file_name ); rename( temporary, full_file_name ); exit( 1 ); } /* required delete of temporary file */ delete( delete_mode, temporary ); } /* free all allocated file names */ if (new_files.next != (struct fnames *) 0) { for (;;) { fnPointer = new_files.next; new_files = *new_files.next; free( fnPointer ); if (new_files.next == (struct fnames *) 0) break; } } optind++; /* next command line input */ } } /* Process commands from file if -f given */ if (command_file_name[0]) { if ((fPointer=fopen(command_file_name, "r")) != NULL) { while ( fgets(buffer, 512, fPointer) != NULL ) { if( (cPointer = strchr( buffer, '\n' )) != NULL) *cPointer = '\0'; if( (cPointer = strchr( buffer, '\r' )) != NULL) *cPointer = '\0'; parseline( buffer ); } fclose( fPointer ); } else { fprintf( stderr, "Could not open command file %s\n", command_file_name ); usage(); exit( 1 ); } } return; } void parseline( char *line ) { int inquote = 0; int argc; char *argv[80], *p; p = line; argc = 1; argv[0] = "CRYPT.EXE"; /* just give some name */ argv[1] = NULL; for (;;) { while (isspace(*p)) p++; if (*p == '\'' || *p == '\"') inquote = *p++; if (*p == '\0') break; argv[argc++] = p++; argv[argc] = NULL; if (argc >= 80) { fprintf(stderr, "Error: too many arguments on line.\n"); usage(); exit( 1 ); } if (inquote) { while ((*p != inquote) && (*p != '\0')) p++; if (*p == '\0') break; *p++ = '\0'; inquote = 0; } else { while( !isspace(*p) && (*p != '\0')) p++; if (*p == '\0') break; *p++ = '\0'; } } nextline( argc, argv ); return; } void delete( int mode, char *file_name ) /* Delete file according to given mode */ { struct _stat buf; int result; long file_size; long i; FILE *fPointer; result = _stat( file_name, &buf ); if (result != 0) { fprintf( stderr, "Delete failure: Can not get size of file %s\n", file_name); usage(); exit( 1 ); } file_size = buf.st_size; if ((fPointer = fopen( file_name, "r+" )) == NULL) { fprintf( stderr, "Delete failure: Can not open %s for read update\n", file_name); usage(); exit( 1 ); } if ((mode == DELETE_NORMAL) || (mode == DELETE_ALL_NORMAL)) { for (i = 0; i < buf.st_size; i++) /* there may be faster routines */ putc( overwrite, fPointer); } else if ((mode == DELETE_DOD) || (mode == DELETE_ALL_DOD)) { for (i = 0; i < buf.st_size; i++) putc( 1, fPointer); fflush( fPointer ); fclose( fPointer ); fPointer = fopen( file_name, "r+" ); for (i = 0; i < buf.st_size; i++) putc( 0, fPointer); fflush( fPointer ); fclose( fPointer ); fPointer = fopen( file_name, "r+" ); for (i = 0; i < buf.st_size; i++) putc( 1, fPointer); fflush( fPointer ); fclose( fPointer ); fPointer = fopen( file_name, "r+" ); for (i = 0; i < buf.st_size; i++) putc( 0, fPointer); fflush( fPointer ); fclose( fPointer ); fPointer = fopen( file_name, "r+" ); for (i = 0; i < buf.st_size; i++) putc( 1, fPointer); fflush( fPointer ); fclose( fPointer ); fPointer = fopen( file_name, "r+" ); for (i = 0; i < buf.st_size; i++) putc( 0, fPointer); fflush( fPointer ); fclose( fPointer ); fPointer = fopen( file_name, "r+" ); for (i = 0; i < buf.st_size; i++) putc( overwrite, fPointer); } fflush( fPointer ); fclose( fPointer ); remove( file_name ); return; } int give_help( int argc, char *argv[] ) { char **help; /* Give help in case it is asked for, then return 0 */ if (argc == 2) if ( !strcmp(argv[1],"-?") || !strcmp(argv[1],"--help") || !strcmp(argv[1],"--HELP") ) { printf ( "NAME\n"); printf ( " %s - perform file encryption and decryption\n\n", prog ); printf ( "SYNOPSIS\n"); printf ( " %s [-edcqQgG] [-k \"key\"] [-f file] [-# number] infile ...\n", prog ); printf ( " %s [-edcqQgG] [-k \"key\"] [-f file] [-# number] infile -o outfile\n\n", prog ); for ( help=documentation; *help; help++ ) printf( "%s\n", *help ); printf( "\n" ); for ( help=crypt_help(); *help; help++ ) printf( "%s\n", *help ); return 1; /* help given */ } return 0; /* no help given */ } void usage( void ) { fprintf (stderr, "Usage: %s [-edcqQgG] [-k \"key\"] [-f file] [-# number] infile ...\n", prog); fprintf( stderr, " %s [-edcqQgG] [-k \"key\"] [-f file] [-# number] infile -o outfile\n", prog); fprintf (stderr, "Help: %s -?\n", prog); return; } void copyright( void ) { printf("%s v1.00 Copyright 1995 Willis E. Howard, III.\n", prog); printf("The source code may contain additional copyright notices.\n"); printf("email: WEHoward@aol.com\n"); return; }