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