gnome-control-center/capplets/about-me/cracklib/rules.c
Diego González a6352fc137 Lots of changes on the password dialog and a bit of a performance improvement
on the main dialog while instant applying the changes to the EDS database.
2005-06-15 00:25:55 +00:00

824 lines
15 KiB
C

/*
* 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.
*/
static char vers_id[] = "rules.c : v5.0p3 Alec Muffett 20 May 1993";
#include "packer.h"
static void
Debug(val, a, b, c, d, e, f, g)
int val;
char *a, *b, *c, *d, *e, *f, *g;
{
fprintf(stderr, a, b, c, d, e, f);
}
#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(myword, 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(str) /* return a pointer to a reversal */
register char *str;
{
register int i;
register int j;
static char area[STRINGSIZE];
j = i = strlen(str);
while (*str)
{
area[--i] = *str++;
}
area[j] = '\0';
return (area);
}
char *
Uppercase(str) /* return a pointer to an uppercase */
register char *str;
{
register char *ptr;
static char area[STRINGSIZE];
ptr = area;
while (*str)
{
*(ptr++) = CRACK_TOUPPER(*str);
str++;
}
*ptr = '\0';
return (area);
}
char *
Lowercase(str) /* return a pointer to an lowercase */
register char *str;
{
register char *ptr;
static char area[STRINGSIZE];
ptr = area;
while (*str)
{
*(ptr++) = CRACK_TOLOWER(*str);
str++;
}
*ptr = '\0';
return (area);
}
char *
Capitalise(str) /* return a pointer to an capitalised */
register char *str;
{
register char *ptr;
static char area[STRINGSIZE];
ptr = area;
while (*str)
{
*(ptr++) = CRACK_TOLOWER(*str);
str++;
}
*ptr = '\0';
area[0] = CRACK_TOUPPER(area[0]);
return (area);
}
char *
Pluralise(string) /* returns a pointer to a plural */
register char *string;
{
register int length;
static char area[STRINGSIZE];
length = strlen(string);
strcpy(area, string);
if (!Suffix(string, "ch") ||
!Suffix(string, "ex") ||
!Suffix(string, "ix") ||
!Suffix(string, "sh") ||
!Suffix(string, "ss"))
{
/* bench -> benches */
strcat(area, "es");
} else if (length > 2 && string[length - 1] == 'y')
{
if (strchr("aeiou", string[length - 2]))
{
/* alloy -> alloys */
strcat(area, "s");
} else
{
/* gully -> gullies */
strcpy(area + length - 1, "ies");
}
} else if (string[length - 1] == 's')
{
/* bias -> biases */
strcat(area, "es");
} else
{
/* catchall */
strcat(area, "s");
}
return (area);
}
char *
Substitute(string, old, new) /* returns pointer to a swapped about copy */
register char *string;
register char old;
register char new;
{
register char *ptr;
static char area[STRINGSIZE];
ptr = area;
while (*string)
{
*(ptr++) = (*string == old ? new : *string);
string++;
}
*ptr = '\0';
return (area);
}
char *
Purge(string, target) /* returns pointer to a purged copy */
register char *string;
register char target;
{
register char *ptr;
static char area[STRINGSIZE];
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(class, input)
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;
default:
Debug(1, "MatchClass: unknown class %c\n", class);
return (0);
break;
}
if (isupper(class))
{
return (!retval);
}
return (retval);
}
char *
PolyStrchr(string, class)
register char *string;
register char class;
{
while (*string)
{
if (MatchClass(class, *string))
{
return (string);
}
string++;
}
return ((char *) 0);
}
char *
PolySubst(string, class, new) /* returns pointer to a swapped about copy */
register char *string;
register char class;
register char new;
{
register char *ptr;
static char area[STRINGSIZE];
ptr = area;
while (*string)
{
*(ptr++) = (MatchClass(class, *string) ? new : *string);
string++;
}
*ptr = '\0';
return (area);
}
char *
PolyPurge(string, class) /* returns pointer to a purged copy */
register char *string;
register char class;
{
register char *ptr;
static char area[STRINGSIZE];
ptr = area;
while (*string)
{
if (!MatchClass(class, *string))
{
*(ptr++) = *string;
}
string++;
}
*ptr = '\0';
return (area);
}
/* -------- BACK TO NORMALITY -------- */
int
Char2Int(character)
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);
}
char *
Mangle(input, control) /* returns a pointer to a controlled Mangle */
char *input;
char *control;
{
int limit;
register char *ptr;
static char area[STRINGSIZE];
char area2[STRINGSIZE];
area[0] = '\0';
strcpy(area, input);
for (ptr = control; *ptr; ptr++)
{
switch (*ptr)
{
case RULE_NOOP:
break;
case RULE_REVERSE:
strcpy(area, Reverse(area));
break;
case RULE_UPPERCASE:
strcpy(area, Uppercase(area));
break;
case RULE_LOWERCASE:
strcpy(area, Lowercase(area));
break;
case RULE_CAPITALISE:
strcpy(area, Capitalise(area));
break;
case RULE_PLURALISE:
strcpy(area, Pluralise(area));
break;
case RULE_REFLECT:
strcat(area, Reverse(area));
break;
case RULE_DUPLICATE:
strcpy(area2, area);
strcat(area, area2);
break;
case RULE_GT:
if (!ptr[1])
{
Debug(1, "Mangle: '>' missing argument in '%s'\n", control);
return ((char *) 0);
} else
{
limit = Char2Int(*(++ptr));
if (limit < 0)
{
Debug(1, "Mangle: '>' weird argument in '%s'\n", control);
return ((char *) 0);
}
if (strlen(area) <= limit)
{
return ((char *) 0);
}
}
break;
case RULE_LT:
if (!ptr[1])
{
Debug(1, "Mangle: '<' missing argument in '%s'\n", control);
return ((char *) 0);
} else
{
limit = Char2Int(*(++ptr));
if (limit < 0)
{
Debug(1, "Mangle: '<' weird argument in '%s'\n", control);
return ((char *) 0);
}
if (strlen(area) >= limit)
{
return ((char *) 0);
}
}
break;
case RULE_PREPEND:
if (!ptr[1])
{
Debug(1, "Mangle: prepend missing argument in '%s'\n", control);
return ((char *) 0);
} else
{
area2[0] = *(++ptr);
strcpy(area2 + 1, area);
strcpy(area, area2);
}
break;
case RULE_APPEND:
if (!ptr[1])
{
Debug(1, "Mangle: append missing argument in '%s'\n", control);
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])
{
Debug(1, "Mangle: extract missing argument in '%s'\n", control);
return ((char *) 0);
} else
{
register int i;
int start;
int length;
start = Char2Int(*(++ptr));
length = Char2Int(*(++ptr));
if (start < 0 || length < 0)
{
Debug(1, "Mangle: extract: weird argument in '%s'\n", control);
return ((char *) 0);
}
strcpy(area2, area);
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])
{
Debug(1, "Mangle: overstrike missing argument in '%s'\n", control);
return ((char *) 0);
} else
{
register int i;
i = Char2Int(*(++ptr));
if (i < 0)
{
Debug(1, "Mangle: overstrike weird argument in '%s'\n",
control);
return ((char *) 0);
} else
{
++ptr;
if (area[i])
{
area[i] = *ptr;
}
}
}
break;
case RULE_INSERT:
if (!ptr[1] || !ptr[2])
{
Debug(1, "Mangle: insert missing argument in '%s'\n", control);
return ((char *) 0);
} else
{
register int i;
register char *p1;
register char *p2;
i = Char2Int(*(++ptr));
if (i < 0)
{
Debug(1, "Mangle: insert weird argument in '%s'\n",
control);
return ((char *) 0);
}
p1 = area;
p2 = area2;
while (i && *p1)
{
i--;
*(p2++) = *(p1++);
}
*(p2++) = *(++ptr);
strcpy(p2, p1);
strcpy(area, area2);
}
break;
/* THE FOLLOWING RULES REQUIRE CLASS MATCHING */
case RULE_PURGE: /* @x or @?c */
if (!ptr[1] || (ptr[1] == RULE_CLASS && !ptr[2]))
{
Debug(1, "Mangle: delete missing arguments in '%s'\n", control);
return ((char *) 0);
} else if (ptr[1] != RULE_CLASS)
{
strcpy(area, Purge(area, *(++ptr)));
} else
{
strcpy(area, PolyPurge(area, ptr[2]));
ptr += 2;
}
break;
case RULE_SUBSTITUTE: /* sxy || s?cy */
if (!ptr[1] || !ptr[2] || (ptr[1] == RULE_CLASS && !ptr[3]))
{
Debug(1, "Mangle: subst missing argument in '%s'\n", control);
return ((char *) 0);
} else if (ptr[1] != RULE_CLASS)
{
strcpy(area, Substitute(area, ptr[1], ptr[2]));
ptr += 2;
} else
{
strcpy(area, PolySubst(area, ptr[2], ptr[3]));
ptr += 3;
}
break;
case RULE_MATCH: /* /x || /?c */
if (!ptr[1] || (ptr[1] == RULE_CLASS && !ptr[2]))
{
Debug(1, "Mangle: '/' missing argument in '%s'\n", control);
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]))
{
Debug(1, "Mangle: '!' missing argument in '%s'\n", control);
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]))
{
Debug(1, "Mangle: '=' missing argument in '%s'\n", control);
return ((char *) 0);
} else
{
register int i;
if ((i = Char2Int(ptr[1])) < 0)
{
Debug(1, "Mangle: '=' weird argument in '%s'\n", control);
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]))
{
Debug(1, "Mangle: '(' missing argument in '%s'\n", control);
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);
}
}
}
case RULE_MLAST:
if (!ptr[1] || (ptr[1] == RULE_CLASS && !ptr[2]))
{
Debug(1, "Mangle: ')' missing argument in '%s'\n", control);
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);
}
}
}
default:
Debug(1, "Mangle: unknown command %c in %s\n", *ptr, control);
return ((char *) 0);
break;
}
}
if (!area[0]) /* have we deweted de poor widdle fing away? */
{
return ((char *) 0);
}
return (area);
}
int
PMatch(control, string)
register char *control;
register char *string;
{
while (*string && *control)
{
if (!MatchClass(*control, *string))
{
return(0);
}
string++;
control++;
}
if (*string || *control)
{
return(0);
}
return(1);
}