1N/A/*
1N/A * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
1N/A * Use is subject to license terms.
1N/A */
1N/A
1N/A#pragma ident "%Z%%M% %I% %E% SMI"
1N/A
1N/A/*
1N/A * This program is copyright Alec Muffett 1993. The author disclaims all
1N/A * responsibility or liability with respect to it's usage or its effect
1N/A * upon hardware or computer systems, and maintains copyright as set out
1N/A * in the "LICENCE" document which accompanies distributions of Crack v4.0
1N/A * and upwards.
1N/A */
1N/A
1N/A#include "packer.h"
1N/A
1N/A
1N/A#define RULE_NOOP ':'
1N/A#define RULE_PREPEND '^'
1N/A#define RULE_APPEND '$'
1N/A#define RULE_REVERSE 'r'
1N/A#define RULE_UPPERCASE 'u'
1N/A#define RULE_LOWERCASE 'l'
1N/A#define RULE_PLURALISE 'p'
1N/A#define RULE_CAPITALISE 'c'
1N/A#define RULE_DUPLICATE 'd'
1N/A#define RULE_REFLECT 'f'
1N/A#define RULE_SUBSTITUTE 's'
1N/A#define RULE_MATCH '/'
1N/A#define RULE_NOT '!'
1N/A#define RULE_LT '<'
1N/A#define RULE_GT '>'
1N/A#define RULE_EXTRACT 'x'
1N/A#define RULE_OVERSTRIKE 'o'
1N/A#define RULE_INSERT 'i'
1N/A#define RULE_EQUALS '='
1N/A#define RULE_PURGE '@'
1N/A#define RULE_CLASS '?' /* class rule? socialist ethic in cracker? */
1N/A#define RULE_DFIRST '['
1N/A#define RULE_DLAST ']'
1N/A#define RULE_MFIRST '('
1N/A#define RULE_MLAST ')'
1N/A
1N/Aint
1N/ASuffix(char *myword, char *suffix)
1N/A{
1N/A register int i;
1N/A register int j;
1N/A
1N/A i = strlen(myword);
1N/A j = strlen(suffix);
1N/A
1N/A if (i > j) {
1N/A return (STRCMP((myword + i - j), suffix));
1N/A } else {
1N/A return (-1);
1N/A }
1N/A}
1N/A
1N/Achar *
1N/AReverse(register char *str) /* return a pointer to a reversal */
1N/A{
1N/A register int i;
1N/A register int j;
1N/A static char area[PATH_MAX];
1N/A
1N/A j = i = strlen(str);
1N/A while (*str) {
1N/A area[--i] = *str++;
1N/A }
1N/A area[j] = '\0';
1N/A return (area);
1N/A}
1N/A
1N/Achar *
1N/AUppercase(register char *str) /* return a pointer to an uppercase */
1N/A{
1N/A register char *ptr;
1N/A static char area[PATH_MAX];
1N/A
1N/A ptr = area;
1N/A while (*str) {
1N/A *(ptr++) = CRACK_TOUPPER(*str);
1N/A str++;
1N/A }
1N/A *ptr = '\0';
1N/A
1N/A return (area);
1N/A}
1N/A
1N/Achar *
1N/ALowercase(register char *str) /* return a pointer to an lowercase */
1N/A{
1N/A register char *ptr;
1N/A static char area[PATH_MAX];
1N/A
1N/A ptr = area;
1N/A while (*str) {
1N/A *(ptr++) = CRACK_TOLOWER(*str);
1N/A str++;
1N/A }
1N/A *ptr = '\0';
1N/A
1N/A return (area);
1N/A}
1N/A
1N/Achar *
1N/ACapitalise(register char *str) /* return a pointer to an capitalised */
1N/A{
1N/A register char *ptr;
1N/A static char area[PATH_MAX];
1N/A
1N/A ptr = area;
1N/A
1N/A while (*str) {
1N/A *(ptr++) = CRACK_TOLOWER(*str);
1N/A str++;
1N/A }
1N/A
1N/A *ptr = '\0';
1N/A area[0] = CRACK_TOUPPER(area[0]);
1N/A return (area);
1N/A}
1N/A
1N/Achar *
1N/APluralise(register char *string) /* returns a pointer to a plural */
1N/A{
1N/A register int length;
1N/A static char area[PATH_MAX];
1N/A
1N/A length = strlen(string);
1N/A (void) strlcpy(area, string, PATH_MAX);
1N/A
1N/A if (!Suffix(string, "ch") ||
1N/A !Suffix(string, "ex") ||
1N/A !Suffix(string, "ix") ||
1N/A !Suffix(string, "sh") ||
1N/A !Suffix(string, "ss")) {
1N/A /* bench -> benches */
1N/A (void) strcat(area, "es");
1N/A } else if (length > 2 && string[length - 1] == 'y') {
1N/A if (strchr("aeiou", string[length - 2])) {
1N/A /* alloy -> alloys */
1N/A (void) strcat(area, "s");
1N/A } else {
1N/A /* gully -> gullies */
1N/A (void) strcpy(area + length - 1, "ies");
1N/A }
1N/A } else if (string[length - 1] == 's') {
1N/A /* bias -> biases */
1N/A (void) strcat(area, "es");
1N/A } else {
1N/A /* catchall */
1N/A (void) strcat(area, "s");
1N/A }
1N/A
1N/A return (area);
1N/A}
1N/A
1N/Achar *
1N/ASubstitute(register char *string, register char old,
1N/A register char new) /* returns pointer to a swapped about copy */
1N/A{
1N/A register char *ptr;
1N/A static char area[PATH_MAX];
1N/A
1N/A ptr = area;
1N/A while (*string) {
1N/A *(ptr++) = (*string == old ? new : *string);
1N/A string++;
1N/A }
1N/A *ptr = '\0';
1N/A return (area);
1N/A}
1N/A
1N/A/* returns pointer to a purged copy */
1N/Achar *
1N/APurge(register char *string, register char target)
1N/A{
1N/A register char *ptr;
1N/A static char area[PATH_MAX];
1N/A ptr = area;
1N/A while (*string) {
1N/A if (*string != target) {
1N/A *(ptr++) = *string;
1N/A }
1N/A string++;
1N/A }
1N/A *ptr = '\0';
1N/A return (area);
1N/A}
1N/A/* -------- CHARACTER CLASSES START HERE -------- */
1N/A
1N/A/*
1N/A * this function takes two inputs, a class identifier and a character, and
1N/A * returns non-null if the given character is a member of the class, based
1N/A * upon restrictions set out below
1N/A */
1N/A
1N/Aint
1N/AMatchClass(register char class, register char input)
1N/A{
1N/A register char c;
1N/A register int retval;
1N/A
1N/A retval = 0;
1N/A
1N/A switch (class) {
1N/A /* ESCAPE */
1N/A
1N/A case '?': /* ?? -> ? */
1N/A if (input == '?') {
1N/A retval = 1;
1N/A }
1N/A break;
1N/A
1N/A /* ILLOGICAL GROUPINGS (ie: not in ctype.h) */
1N/A
1N/A case 'V':
1N/A case 'v': /* vowels */
1N/A c = CRACK_TOLOWER(input);
1N/A if (strchr("aeiou", c)) {
1N/A retval = 1;
1N/A }
1N/A break;
1N/A
1N/A case 'C':
1N/A case 'c': /* consonants */
1N/A c = CRACK_TOLOWER(input);
1N/A if (strchr("bcdfghjklmnpqrstvwxyz", c)) {
1N/A retval = 1;
1N/A }
1N/A break;
1N/A
1N/A case 'W':
1N/A case 'w': /* whitespace */
1N/A if (strchr("\t ", input)) {
1N/A retval = 1;
1N/A }
1N/A break;
1N/A
1N/A case 'P':
1N/A case 'p': /* punctuation */
1N/A if (strchr(".`,:;'!?\"", input)) {
1N/A retval = 1;
1N/A }
1N/A break;
1N/A
1N/A case 'S':
1N/A case 's': /* symbols */
1N/A if (strchr("$%%^&*()-_+=|\\[]{}#@/~", input)) {
1N/A retval = 1;
1N/A }
1N/A break;
1N/A
1N/A /* LOGICAL GROUPINGS */
1N/A
1N/A case 'L':
1N/A case 'l': /* lowercase */
1N/A if (islower(input)) {
1N/A retval = 1;
1N/A }
1N/A break;
1N/A
1N/A case 'U':
1N/A case 'u': /* uppercase */
1N/A if (isupper(input)) {
1N/A retval = 1;
1N/A }
1N/A break;
1N/A
1N/A case 'A':
1N/A case 'a': /* alphabetic */
1N/A if (isalpha(input)) {
1N/A retval = 1;
1N/A }
1N/A break;
1N/A
1N/A case 'X':
1N/A case 'x': /* alphanumeric */
1N/A if (isalnum(input)) {
1N/A retval = 1;
1N/A }
1N/A break;
1N/A
1N/A case 'D':
1N/A case 'd': /* digits */
1N/A if (isdigit(input)) {
1N/A retval = 1;
1N/A }
1N/A break;
1N/A }
1N/A
1N/A if (isupper(class)) {
1N/A return (!retval);
1N/A }
1N/A return (retval);
1N/A}
1N/A
1N/Achar *
1N/APolyStrchr(register char *string, register char class)
1N/A{
1N/A while (*string) {
1N/A if (MatchClass(class, *string)) {
1N/A return (string);
1N/A }
1N/A string++;
1N/A }
1N/A return ((char *)0);
1N/A}
1N/A
1N/A/* returns pointer to a swapped about copy */
1N/Achar *
1N/APolySubst(register char *string, register char class, register char new)
1N/A{
1N/A register char *ptr;
1N/A static char area[PATH_MAX];
1N/A
1N/A ptr = area;
1N/A while (*string) {
1N/A *(ptr++) = (MatchClass(class, *string) ? new : *string);
1N/A string++;
1N/A }
1N/A *ptr = '\0';
1N/A return (area);
1N/A}
1N/A
1N/A/* returns pointer to a purged copy */
1N/Achar *
1N/APolyPurge(register char *string, register char class)
1N/A{
1N/A register char *ptr;
1N/A static char area[PATH_MAX];
1N/A
1N/A ptr = area;
1N/A while (*string) {
1N/A if (!MatchClass(class, *string)) {
1N/A *(ptr++) = *string;
1N/A }
1N/A string++;
1N/A }
1N/A *ptr = '\0';
1N/A return (area);
1N/A}
1N/A/* -------- BACK TO NORMALITY -------- */
1N/A
1N/Aint
1N/AChar2Int(char character)
1N/A{
1N/A if (isdigit(character)) {
1N/A return (character - '0');
1N/A } else if (islower(character)) {
1N/A return (character - 'a' + 10);
1N/A } else if (isupper(character)) {
1N/A return (character - 'A' + 10);
1N/A }
1N/A return (-1);
1N/A}
1N/A
1N/A/* returns a pointer to a controlled Mangle */
1N/Achar *
1N/AMangle(char *input, char *control)
1N/A{
1N/A int limit;
1N/A register char *ptr;
1N/A static char area[PATH_MAX];
1N/A char area2[PATH_MAX];
1N/A
1N/A area[0] = '\0';
1N/A (void) strlcpy(area, input, PATH_MAX);
1N/A
1N/A for (ptr = control; *ptr; ptr++) {
1N/A switch (*ptr) {
1N/A case RULE_NOOP:
1N/A break;
1N/A case RULE_REVERSE:
1N/A (void) strlcpy(area, Reverse(area), PATH_MAX);
1N/A break;
1N/A case RULE_UPPERCASE:
1N/A (void) strlcpy(area, Uppercase(area), PATH_MAX);
1N/A break;
1N/A case RULE_LOWERCASE:
1N/A (void) strlcpy(area, Lowercase(area), PATH_MAX);
1N/A break;
1N/A case RULE_CAPITALISE:
1N/A (void) strlcpy(area, Capitalise(area),
1N/A PATH_MAX);
1N/A break;
1N/A case RULE_PLURALISE:
1N/A (void) strlcpy(area, Pluralise(area), PATH_MAX);
1N/A break;
1N/A case RULE_REFLECT:
1N/A (void) strlcat(area, Reverse(area), PATH_MAX);
1N/A break;
1N/A case RULE_DUPLICATE:
1N/A (void) strlcpy(area2, area, PATH_MAX);
1N/A (void) strlcat(area, area2, PATH_MAX);
1N/A break;
1N/A case RULE_GT:
1N/A if (!ptr[1]) {
1N/A return ((char *)0);
1N/A } else {
1N/A limit = Char2Int(*(++ptr));
1N/A if (limit < 0) {
1N/A return ((char *)0);
1N/A }
1N/A if (strlen(area) <= limit) {
1N/A return ((char *)0);
1N/A }
1N/A }
1N/A break;
1N/A case RULE_LT:
1N/A if (!ptr[1]) {
1N/A return ((char *)0);
1N/A } else {
1N/A limit = Char2Int(*(++ptr));
1N/A if (limit < 0) {
1N/A return ((char *)0);
1N/A }
1N/A if (strlen(area) >= limit) {
1N/A return ((char *)0);
1N/A }
1N/A }
1N/A break;
1N/A case RULE_PREPEND:
1N/A if (!ptr[1]) {
1N/A return ((char *)0);
1N/A } else {
1N/A area2[0] = *(++ptr);
1N/A (void) strlcpy(area2 + 1, area,
1N/A PATH_MAX);
1N/A (void) strlcpy(area, area2, PATH_MAX);
1N/A }
1N/A break;
1N/A case RULE_APPEND:
1N/A if (!ptr[1]) {
1N/A return ((char *)0);
1N/A } else {
1N/A register char *string;
1N/A
1N/A string = area;
1N/A while (*(string++));
1N/A string[-1] = *(++ptr);
1N/A *string = '\0';
1N/A }
1N/A break;
1N/A case RULE_EXTRACT:
1N/A if (!ptr[1] || !ptr[2]) {
1N/A return ((char *)0);
1N/A } else {
1N/A register int i;
1N/A int start;
1N/A int length;
1N/A
1N/A start = Char2Int(*(++ptr));
1N/A length = Char2Int(*(++ptr));
1N/A if (start < 0 || length < 0) {
1N/A return ((char *)0);
1N/A }
1N/A (void) strlcpy(area2, area, PATH_MAX);
1N/A for (i = 0; length-- &&
1N/A area2[start + i]; i++) {
1N/A area[i] = area2[start + i];
1N/A }
1N/A /* cant use strncpy()-no trailing NUL */
1N/A area[i] = '\0';
1N/A }
1N/A break;
1N/A case RULE_OVERSTRIKE:
1N/A if (!ptr[1] || !ptr[2]) {
1N/A return ((char *)0);
1N/A } else {
1N/A register int i;
1N/A
1N/A i = Char2Int(*(++ptr));
1N/A if (i < 0) {
1N/A return ((char *)0);
1N/A } else {
1N/A ++ptr;
1N/A if (area[i]) {
1N/A area[i] = *ptr;
1N/A }
1N/A }
1N/A }
1N/A break;
1N/A case RULE_INSERT:
1N/A if (!ptr[1] || !ptr[2]) {
1N/A return ((char *)0);
1N/A } else {
1N/A register int i;
1N/A register char *p1;
1N/A register char *p2;
1N/A
1N/A i = Char2Int(*(++ptr));
1N/A if (i < 0) {
1N/A return ((char *)0);
1N/A }
1N/A p1 = area;
1N/A p2 = area2;
1N/A while (i && *p1) {
1N/A i--;
1N/A *(p2++) = *(p1++);
1N/A }
1N/A *(p2++) = *(++ptr);
1N/A (void) strlcpy(p2, p1, PATH_MAX);
1N/A (void) strlcpy(area, area2, PATH_MAX);
1N/A }
1N/A break;
1N/A /* THE FOLLOWING RULES REQUIRE CLASS MATCHING */
1N/A
1N/A case RULE_PURGE: /* @x or @?c */
1N/A if (!ptr[1] || (ptr[1] ==
1N/A RULE_CLASS && !ptr[2])) {
1N/A return ((char *)0);
1N/A } else if (ptr[1] != RULE_CLASS) {
1N/A (void) strlcpy(area, Purge(area,
1N/A *(++ptr)), PATH_MAX);
1N/A } else {
1N/A (void) strlcpy(area, PolyPurge(area,
1N/A ptr[2]), PATH_MAX);
1N/A ptr += 2;
1N/A }
1N/A break;
1N/A case RULE_SUBSTITUTE: /* sxy || s?cy */
1N/A if (!ptr[1] || !ptr[2] ||
1N/A (ptr[1] == RULE_CLASS && !ptr[3])) {
1N/A return ((char *)0);
1N/A } else if (ptr[1] != RULE_CLASS) {
1N/A ptr += 2;
1N/A } else {
1N/A (void) strlcpy(area, PolySubst(area,
1N/A ptr[2], ptr[3]), PATH_MAX);
1N/A ptr += 3;
1N/A }
1N/A break;
1N/A case RULE_MATCH: /* /x || /?c */
1N/A if (!ptr[1] ||
1N/A (ptr[1] == RULE_CLASS && !ptr[2])) {
1N/A return ((char *)0);
1N/A } else if (ptr[1] != RULE_CLASS) {
1N/A if (!strchr(area, *(++ptr))) {
1N/A return ((char *)0);
1N/A }
1N/A } else {
1N/A if (!PolyStrchr(area, ptr[2])) {
1N/A return ((char *)0);
1N/A }
1N/A ptr += 2;
1N/A }
1N/A break;
1N/A case RULE_NOT: /* !x || !?c */
1N/A if (!ptr[1] ||
1N/A (ptr[1] == RULE_CLASS && !ptr[2])) {
1N/A return ((char *)0);
1N/A } else if (ptr[1] != RULE_CLASS) {
1N/A if (strchr(area, *(++ptr))) {
1N/A return ((char *)0);
1N/A }
1N/A } else {
1N/A if (PolyStrchr(area, ptr[2])) {
1N/A return ((char *)0);
1N/A }
1N/A ptr += 2;
1N/A }
1N/A break;
1N/A /*
1N/A * alternative use for a boomerang, number 1: a standard throwing
1N/A * boomerang is an ideal thing to use to tuck the sheets under
1N/A * the mattress when making your bed. The streamlined shape of
1N/A * the boomerang allows it to slip easily 'twixt mattress and
1N/A * bedframe, and it's curve makes it very easy to hook sheets
1N/A * into the gap.
1N/A */
1N/A
1N/A case RULE_EQUALS: /* =nx || =n?c */
1N/A if (!ptr[1] || !ptr[2] ||
1N/A (ptr[2] == RULE_CLASS && !ptr[3])) {
1N/A return ((char *)0);
1N/A } else {
1N/A register int i;
1N/A
1N/A if ((i = Char2Int(ptr[1])) < 0) {
1N/A return ((char *)0);
1N/A }
1N/A if (ptr[2] != RULE_CLASS) {
1N/A ptr += 2;
1N/A if (area[i] != *ptr) {
1N/A return ((char *)0);
1N/A }
1N/A } else {
1N/A ptr += 3;
1N/A if (!MatchClass(*ptr,
1N/A area[i])) {
1N/A return ((char *)0);
1N/A }
1N/A }
1N/A }
1N/A break;
1N/A
1N/A case RULE_DFIRST:
1N/A if (area[0]) {
1N/A register int i;
1N/A
1N/A for (i = 1; area[i]; i++) {
1N/A area[i - 1] = area[i];
1N/A }
1N/A area[i - 1] = '\0';
1N/A }
1N/A break;
1N/A
1N/A case RULE_DLAST:
1N/A if (area[0]) {
1N/A register int i;
1N/A
1N/A for (i = 1; area[i]; i++);
1N/A area[i - 1] = '\0';
1N/A }
1N/A break;
1N/A
1N/A case RULE_MFIRST:
1N/A if (!ptr[1] ||
1N/A (ptr[1] == RULE_CLASS && !ptr[2])) {
1N/A return ((char *)0);
1N/A } else {
1N/A if (ptr[1] != RULE_CLASS) {
1N/A ptr++;
1N/A if (area[0] != *ptr) {
1N/A return ((char *)0);
1N/A }
1N/A } else {
1N/A ptr += 2;
1N/A if (!MatchClass(*ptr,
1N/A area[0])) {
1N/A return ((char *)0);
1N/A }
1N/A }
1N/A }
1N/A break;
1N/A case RULE_MLAST:
1N/A if (!ptr[1] ||
1N/A (ptr[1] == RULE_CLASS && !ptr[2])) {
1N/A return ((char *)0);
1N/A } else {
1N/A register int i;
1N/A
1N/A for (i = 0; area[i]; i++);
1N/A
1N/A if (i > 0) {
1N/A i--;
1N/A } else {
1N/A return ((char *)0);
1N/A }
1N/A if (ptr[1] != RULE_CLASS) {
1N/A ptr++;
1N/A if (area[i] != *ptr) {
1N/A return ((char *)0);
1N/A }
1N/A } else {
1N/A ptr += 2;
1N/A if (!MatchClass(*ptr,
1N/A area[i])) {
1N/A return ((char *)0);
1N/A }
1N/A }
1N/A }
1N/A break;
1N/A }
1N/A }
1N/A if (!area[0]) { /* have we deweted de poor widdle fing away? */
1N/A return ((char *)0);
1N/A }
1N/A return (area);
1N/A}
1N/A/*
1N/A * int
1N/A * PMatch(register char *control, register char *string)
1N/A * {
1N/A * while (*string && *control) {
1N/A * if (!MatchClass(*control, *string)) {
1N/A * return (0);
1N/A * }
1N/A *
1N/A * string++;
1N/A * control++;
1N/A * }
1N/A *
1N/A * if (*string || *control) {
1N/A * return (0);
1N/A * }
1N/A *
1N/A * return (1);
1N/A * }
1N/A */