Home | History | Annotate | Download | only in authtok_check
      1 /*
      2  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
      3  * Use is subject to license terms.
      4  */
      5 
      6 #pragma ident	"%Z%%M%	%I%	%E% SMI"
      7 
      8 /*
      9  * This program is copyright Alec Muffett 1993. The author disclaims all
     10  * responsibility or liability with respect to it's usage or its effect
     11  * upon hardware or computer systems, and maintains copyright as set out
     12  * in the "LICENCE" document which accompanies distributions of Crack v4.0
     13  * and upwards.
     14  */
     15 
     16 #include "packer.h"
     17 
     18 
     19 #define	RULE_NOOP	':'
     20 #define	RULE_PREPEND	'^'
     21 #define	RULE_APPEND	'$'
     22 #define	RULE_REVERSE	'r'
     23 #define	RULE_UPPERCASE	'u'
     24 #define	RULE_LOWERCASE	'l'
     25 #define	RULE_PLURALISE	'p'
     26 #define	RULE_CAPITALISE	'c'
     27 #define	RULE_DUPLICATE	'd'
     28 #define	RULE_REFLECT	'f'
     29 #define	RULE_SUBSTITUTE	's'
     30 #define	RULE_MATCH	'/'
     31 #define	RULE_NOT	'!'
     32 #define	RULE_LT		'<'
     33 #define	RULE_GT		'>'
     34 #define	RULE_EXTRACT	'x'
     35 #define	RULE_OVERSTRIKE	'o'
     36 #define	RULE_INSERT	'i'
     37 #define	RULE_EQUALS	'='
     38 #define	RULE_PURGE	'@'
     39 #define	RULE_CLASS	'?'	/* class rule? socialist ethic in cracker? */
     40 #define	RULE_DFIRST	'['
     41 #define	RULE_DLAST	']'
     42 #define	RULE_MFIRST	'('
     43 #define	RULE_MLAST	')'
     44 
     45 int
     46 Suffix(char *myword, char *suffix)
     47 {
     48 	register int i;
     49 	register int j;
     50 
     51 	i = strlen(myword);
     52 	j = strlen(suffix);
     53 
     54 	if (i > j) {
     55 		return (STRCMP((myword + i - j), suffix));
     56 	} else {
     57 		return (-1);
     58 	}
     59 }
     60 
     61 char *
     62 Reverse(register char *str)		/* return a pointer to a reversal */
     63 {
     64 	register int i;
     65 	register int j;
     66 	static char area[PATH_MAX];
     67 
     68 	j = i = strlen(str);
     69 	while (*str) {
     70 		area[--i] = *str++;
     71 	}
     72 	area[j] = '\0';
     73 	return (area);
     74 }
     75 
     76 char *
     77 Uppercase(register char *str)		/* return a pointer to an uppercase */
     78 {
     79 	register char *ptr;
     80 	static char area[PATH_MAX];
     81 
     82 	ptr = area;
     83 	while (*str) {
     84 		*(ptr++) = CRACK_TOUPPER(*str);
     85 		str++;
     86 	}
     87 	*ptr = '\0';
     88 
     89 	return (area);
     90 }
     91 
     92 char *
     93 Lowercase(register char *str)		/* return a pointer to an lowercase */
     94 {
     95 	register char *ptr;
     96 	static char area[PATH_MAX];
     97 
     98 	ptr = area;
     99 	while (*str) {
    100 		*(ptr++) = CRACK_TOLOWER(*str);
    101 		str++;
    102 	}
    103 	*ptr = '\0';
    104 
    105 	return (area);
    106 }
    107 
    108 char *
    109 Capitalise(register char *str)		/* return a pointer to an capitalised */
    110 {
    111 	register char *ptr;
    112 	static char area[PATH_MAX];
    113 
    114 	ptr = area;
    115 
    116 	while (*str) {
    117 		*(ptr++) = CRACK_TOLOWER(*str);
    118 		str++;
    119 	}
    120 
    121 	*ptr = '\0';
    122 	area[0] = CRACK_TOUPPER(area[0]);
    123 	return (area);
    124 }
    125 
    126 char *
    127 Pluralise(register char *string)	/* returns a pointer to a plural */
    128 {
    129 	register int length;
    130 	static char area[PATH_MAX];
    131 
    132 	length = strlen(string);
    133 	(void) strlcpy(area, string, PATH_MAX);
    134 
    135 	if (!Suffix(string, "ch") ||
    136 	    !Suffix(string, "ex") ||
    137 	    !Suffix(string, "ix") ||
    138 	    !Suffix(string, "sh") ||
    139 	    !Suffix(string, "ss")) {
    140 		/* bench -> benches */
    141 		(void) strcat(area, "es");
    142 	} else if (length > 2 && string[length - 1] == 'y') {
    143 		if (strchr("aeiou", string[length - 2])) {
    144 			/* alloy -> alloys */
    145 			(void) strcat(area, "s");
    146 		} else {
    147 			/* gully -> gullies */
    148 			(void) strcpy(area + length - 1, "ies");
    149 		}
    150 	} else if (string[length - 1] == 's') {
    151 		/* bias -> biases */
    152 		(void) strcat(area, "es");
    153 	} else {
    154 		/* catchall */
    155 		(void) strcat(area, "s");
    156 	}
    157 
    158 	return (area);
    159 }
    160 
    161 char *
    162 Substitute(register char *string, register char old,
    163 	register char new)	/* returns pointer to a swapped about copy */
    164 {
    165 	register char *ptr;
    166 	static char area[PATH_MAX];
    167 
    168 	ptr = area;
    169 	while (*string) {
    170 		*(ptr++) = (*string == old ? new : *string);
    171 		string++;
    172 	}
    173 	*ptr = '\0';
    174 	return (area);
    175 }
    176 
    177 /* returns pointer to a purged copy */
    178 char *
    179 Purge(register char *string, register char target)
    180 {
    181 	register char *ptr;
    182 	static char area[PATH_MAX];
    183 	ptr = area;
    184 	while (*string) {
    185 		if (*string != target) {
    186 			*(ptr++) = *string;
    187 		}
    188 		string++;
    189 	}
    190 	*ptr = '\0';
    191 	return (area);
    192 }
    193 /* -------- CHARACTER CLASSES START HERE -------- */
    194 
    195 /*
    196  * this function takes two inputs, a class identifier and a character, and
    197  * returns non-null if the given character is a member of the class, based
    198  * upon restrictions set out below
    199  */
    200 
    201 int
    202 MatchClass(register char class, register char input)
    203 {
    204 	register char c;
    205 	register int retval;
    206 
    207 	retval = 0;
    208 
    209 	switch (class) {
    210 	/* ESCAPE */
    211 
    212 		case '?':			/* ?? -> ? */
    213 			if (input == '?') {
    214 				retval = 1;
    215 			}
    216 			break;
    217 
    218 	/* ILLOGICAL GROUPINGS (ie: not in ctype.h) */
    219 
    220 		case 'V':
    221 		case 'v':			/* vowels */
    222 			c = CRACK_TOLOWER(input);
    223 			if (strchr("aeiou", c)) {
    224 				retval = 1;
    225 			}
    226 			break;
    227 
    228 		case 'C':
    229 		case 'c':			/* consonants */
    230 			c = CRACK_TOLOWER(input);
    231 			if (strchr("bcdfghjklmnpqrstvwxyz", c)) {
    232 				retval = 1;
    233 			}
    234 			break;
    235 
    236 		case 'W':
    237 		case 'w':			/* whitespace */
    238 			if (strchr("\t ", input)) {
    239 				retval = 1;
    240 			}
    241 			break;
    242 
    243 		case 'P':
    244 		case 'p':			/* punctuation */
    245 			if (strchr(".`,:;'!?\"", input)) {
    246 				retval = 1;
    247 			}
    248 			break;
    249 
    250 		case 'S':
    251 		case 's':			/* symbols */
    252 			if (strchr("$%%^&*()-_+=|\\[]{}#@/~", input)) {
    253 				retval = 1;
    254 			}
    255 			break;
    256 
    257 		/* LOGICAL GROUPINGS */
    258 
    259 		case 'L':
    260 		case 'l':			/* lowercase */
    261 			if (islower(input)) {
    262 				retval = 1;
    263 			}
    264 			break;
    265 
    266 		case 'U':
    267 		case 'u':			/* uppercase */
    268 			if (isupper(input)) {
    269 				retval = 1;
    270 			}
    271 			break;
    272 
    273 		case 'A':
    274 		case 'a':			/* alphabetic */
    275 			if (isalpha(input)) {
    276 				retval = 1;
    277 			}
    278 			break;
    279 
    280 		case 'X':
    281 		case 'x':			/* alphanumeric */
    282 			if (isalnum(input)) {
    283 				retval = 1;
    284 			}
    285 			break;
    286 
    287 		case 'D':
    288 		case 'd':			/* digits */
    289 			if (isdigit(input)) {
    290 				retval = 1;
    291 			}
    292 			break;
    293 	}
    294 
    295 	if (isupper(class)) {
    296 		return (!retval);
    297 	}
    298 	return (retval);
    299 }
    300 
    301 char *
    302 PolyStrchr(register char *string, register char class)
    303 {
    304 	while (*string) {
    305 		if (MatchClass(class, *string)) {
    306 			return (string);
    307 		}
    308 		string++;
    309 	}
    310 	return ((char *)0);
    311 }
    312 
    313 /* returns pointer to a swapped about copy */
    314 char *
    315 PolySubst(register char *string, register char class, register char new)
    316 {
    317 	register char *ptr;
    318 	static char area[PATH_MAX];
    319 
    320 	ptr = area;
    321 	while (*string) {
    322 		*(ptr++) = (MatchClass(class, *string) ? new : *string);
    323 		string++;
    324 	}
    325 	*ptr = '\0';
    326 	return (area);
    327 }
    328 
    329 /* returns pointer to a purged copy */
    330 char *
    331 PolyPurge(register char *string, register char class)
    332 {
    333 	register char *ptr;
    334 	static char area[PATH_MAX];
    335 
    336 	ptr = area;
    337 	while (*string) {
    338 		if (!MatchClass(class, *string)) {
    339 			*(ptr++) = *string;
    340 		}
    341 		string++;
    342 	}
    343 	*ptr = '\0';
    344 	return (area);
    345 }
    346 /* -------- BACK TO NORMALITY -------- */
    347 
    348 int
    349 Char2Int(char character)
    350 {
    351 	if (isdigit(character)) {
    352 		return (character - '0');
    353 	} else if (islower(character)) {
    354 		return (character - 'a' + 10);
    355 	} else if (isupper(character)) {
    356 		return (character - 'A' + 10);
    357 	}
    358 	return (-1);
    359 }
    360 
    361 /* returns a pointer to a controlled Mangle */
    362 char *
    363 Mangle(char *input, char *control)
    364 {
    365 	int limit;
    366 	register char *ptr;
    367 	static char area[PATH_MAX];
    368 	char area2[PATH_MAX];
    369 
    370 	area[0] = '\0';
    371 	(void) strlcpy(area, input, PATH_MAX);
    372 
    373 	for (ptr = control; *ptr; ptr++) {
    374 		switch (*ptr) {
    375 			case RULE_NOOP:
    376 				break;
    377 			case RULE_REVERSE:
    378 				(void) strlcpy(area, Reverse(area), PATH_MAX);
    379 				break;
    380 			case RULE_UPPERCASE:
    381 				(void) strlcpy(area, Uppercase(area), PATH_MAX);
    382 				break;
    383 			case RULE_LOWERCASE:
    384 				(void) strlcpy(area, Lowercase(area), PATH_MAX);
    385 				break;
    386 			case RULE_CAPITALISE:
    387 				(void) strlcpy(area, Capitalise(area),
    388 				    PATH_MAX);
    389 				break;
    390 			case RULE_PLURALISE:
    391 				(void) strlcpy(area, Pluralise(area), PATH_MAX);
    392 				break;
    393 			case RULE_REFLECT:
    394 				(void) strlcat(area, Reverse(area), PATH_MAX);
    395 				break;
    396 			case RULE_DUPLICATE:
    397 				(void) strlcpy(area2, area, PATH_MAX);
    398 				(void) strlcat(area, area2, PATH_MAX);
    399 				break;
    400 			case RULE_GT:
    401 				if (!ptr[1]) {
    402 					return ((char *)0);
    403 				} else {
    404 					limit = Char2Int(*(++ptr));
    405 					if (limit < 0) {
    406 						return ((char *)0);
    407 					}
    408 					if (strlen(area) <= limit) {
    409 						return ((char *)0);
    410 					}
    411 				}
    412 				break;
    413 			case RULE_LT:
    414 				if (!ptr[1]) {
    415 					return ((char *)0);
    416 				} else {
    417 					limit = Char2Int(*(++ptr));
    418 					if (limit < 0) {
    419 						return ((char *)0);
    420 					}
    421 					if (strlen(area) >= limit) {
    422 						return ((char *)0);
    423 					}
    424 				}
    425 				break;
    426 			case RULE_PREPEND:
    427 				if (!ptr[1]) {
    428 					return ((char *)0);
    429 				} else {
    430 					area2[0] = *(++ptr);
    431 					(void) strlcpy(area2 + 1, area,
    432 					    PATH_MAX);
    433 					(void) strlcpy(area, area2, PATH_MAX);
    434 				}
    435 				break;
    436 			case RULE_APPEND:
    437 				if (!ptr[1]) {
    438 					return ((char *)0);
    439 				} else {
    440 					register char *string;
    441 
    442 					string = area;
    443 					while (*(string++));
    444 					string[-1] = *(++ptr);
    445 					*string = '\0';
    446 				}
    447 				break;
    448 			case RULE_EXTRACT:
    449 				if (!ptr[1] || !ptr[2]) {
    450 					return ((char *)0);
    451 				} else {
    452 					register int i;
    453 					int start;
    454 					int length;
    455 
    456 					start = Char2Int(*(++ptr));
    457 					length = Char2Int(*(++ptr));
    458 					if (start < 0 || length < 0) {
    459 						return ((char *)0);
    460 					}
    461 					(void) strlcpy(area2, area, PATH_MAX);
    462 					for (i = 0; length-- &&
    463 					    area2[start + i]; i++) {
    464 						area[i] = area2[start + i];
    465 					}
    466 					/* cant use strncpy()-no trailing NUL */
    467 					area[i] = '\0';
    468 				}
    469 				break;
    470 			case RULE_OVERSTRIKE:
    471 				if (!ptr[1] || !ptr[2]) {
    472 					return ((char *)0);
    473 				} else {
    474 					register int i;
    475 
    476 					i = Char2Int(*(++ptr));
    477 					if (i < 0) {
    478 						return ((char *)0);
    479 					} else {
    480 						++ptr;
    481 						if (area[i]) {
    482 							area[i] = *ptr;
    483 						}
    484 					}
    485 				}
    486 				break;
    487 			case RULE_INSERT:
    488 				if (!ptr[1] || !ptr[2]) {
    489 					return ((char *)0);
    490 				} else {
    491 					register int i;
    492 					register char *p1;
    493 					register char *p2;
    494 
    495 					i = Char2Int(*(++ptr));
    496 					if (i < 0) {
    497 						return ((char *)0);
    498 					}
    499 					p1 = area;
    500 					p2 = area2;
    501 					while (i && *p1) {
    502 						i--;
    503 						*(p2++) = *(p1++);
    504 					}
    505 					*(p2++) = *(++ptr);
    506 					(void) strlcpy(p2, p1, PATH_MAX);
    507 					(void) strlcpy(area, area2, PATH_MAX);
    508 				}
    509 				break;
    510 	    /* THE FOLLOWING RULES REQUIRE CLASS MATCHING */
    511 
    512 			case RULE_PURGE:	/* @x or @?c */
    513 				if (!ptr[1] || (ptr[1] ==
    514 				    RULE_CLASS && !ptr[2])) {
    515 					return ((char *)0);
    516 				} else if (ptr[1] != RULE_CLASS) {
    517 					(void) strlcpy(area, Purge(area,
    518 					    *(++ptr)), PATH_MAX);
    519 				} else {
    520 					(void) strlcpy(area, PolyPurge(area,
    521 					    ptr[2]), PATH_MAX);
    522 					ptr += 2;
    523 				}
    524 				break;
    525 			case RULE_SUBSTITUTE:	/* sxy || s?cy */
    526 				if (!ptr[1] || !ptr[2] ||
    527 				    (ptr[1] == RULE_CLASS && !ptr[3])) {
    528 					return ((char *)0);
    529 				} else if (ptr[1] != RULE_CLASS) {
    530 					ptr += 2;
    531 				} else {
    532 					(void) strlcpy(area, PolySubst(area,
    533 					    ptr[2], ptr[3]), PATH_MAX);
    534 					ptr += 3;
    535 				}
    536 				break;
    537 			case RULE_MATCH:	/* /x || /?c */
    538 				if (!ptr[1] ||
    539 				    (ptr[1] == RULE_CLASS && !ptr[2])) {
    540 					return ((char *)0);
    541 				} else if (ptr[1] != RULE_CLASS) {
    542 					if (!strchr(area, *(++ptr))) {
    543 						return ((char *)0);
    544 					}
    545 				} else {
    546 					if (!PolyStrchr(area, ptr[2])) {
    547 						return ((char *)0);
    548 					}
    549 					ptr += 2;
    550 				}
    551 				break;
    552 			case RULE_NOT:		/* !x || !?c */
    553 				if (!ptr[1] ||
    554 				    (ptr[1] == RULE_CLASS && !ptr[2])) {
    555 					return ((char *)0);
    556 				} else if (ptr[1] != RULE_CLASS) {
    557 					if (strchr(area, *(++ptr))) {
    558 						return ((char *)0);
    559 					}
    560 				} else {
    561 					if (PolyStrchr(area, ptr[2])) {
    562 						return ((char *)0);
    563 					}
    564 					ptr += 2;
    565 				}
    566 				break;
    567 	/*
    568 	 * alternative use for a boomerang, number 1: a standard throwing
    569 	 * boomerang is an ideal thing to use to tuck the sheets under
    570 	 * the mattress when making your bed.  The streamlined shape of
    571 	 * the boomerang allows it to slip easily 'twixt mattress and
    572 	 * bedframe, and it's curve makes it very easy to hook sheets
    573 	 * into the gap.
    574 	 */
    575 
    576 			case RULE_EQUALS:	/* =nx || =n?c */
    577 				if (!ptr[1] || !ptr[2] ||
    578 				    (ptr[2] == RULE_CLASS && !ptr[3])) {
    579 					return ((char *)0);
    580 				} else {
    581 					register int i;
    582 
    583 					if ((i = Char2Int(ptr[1])) < 0) {
    584 						return ((char *)0);
    585 					}
    586 					if (ptr[2] != RULE_CLASS) {
    587 						ptr += 2;
    588 						if (area[i] != *ptr) {
    589 							return ((char *)0);
    590 						}
    591 					} else {
    592 						ptr += 3;
    593 						if (!MatchClass(*ptr,
    594 						    area[i])) {
    595 							return ((char *)0);
    596 						}
    597 					}
    598 				}
    599 				break;
    600 
    601 			case RULE_DFIRST:
    602 				if (area[0]) {
    603 					register int i;
    604 
    605 					for (i = 1; area[i]; i++) {
    606 						area[i - 1] = area[i];
    607 					}
    608 					area[i - 1] = '\0';
    609 				}
    610 				break;
    611 
    612 			case RULE_DLAST:
    613 				if (area[0]) {
    614 					register int i;
    615 
    616 					for (i = 1; area[i]; i++);
    617 					area[i - 1] = '\0';
    618 				}
    619 				break;
    620 
    621 			case RULE_MFIRST:
    622 				if (!ptr[1] ||
    623 				    (ptr[1] == RULE_CLASS && !ptr[2])) {
    624 					return ((char *)0);
    625 				} else {
    626 					if (ptr[1] != RULE_CLASS) {
    627 						ptr++;
    628 						if (area[0] != *ptr) {
    629 							return ((char *)0);
    630 						}
    631 					} else {
    632 						ptr += 2;
    633 						if (!MatchClass(*ptr,
    634 						    area[0])) {
    635 							return ((char *)0);
    636 						}
    637 					}
    638 				}
    639 				break;
    640 			case RULE_MLAST:
    641 				if (!ptr[1] ||
    642 				    (ptr[1] == RULE_CLASS && !ptr[2])) {
    643 					return ((char *)0);
    644 				} else {
    645 					register int i;
    646 
    647 					for (i = 0; area[i]; i++);
    648 
    649 					if (i > 0) {
    650 						i--;
    651 					} else {
    652 						return ((char *)0);
    653 					}
    654 					if (ptr[1] != RULE_CLASS) {
    655 						ptr++;
    656 						if (area[i] != *ptr) {
    657 							return ((char *)0);
    658 						}
    659 					} else {
    660 						ptr += 2;
    661 						if (!MatchClass(*ptr,
    662 						    area[i])) {
    663 							return ((char *)0);
    664 						}
    665 					}
    666 				}
    667 				break;
    668 		}
    669 	}
    670 	if (!area[0]) {		/* have we deweted de poor widdle fing away? */
    671 		return ((char *)0);
    672 	}
    673 	return (area);
    674 }
    675 /*
    676  * int
    677  * PMatch(register char *control, register char *string)
    678  * {
    679  * 	while (*string && *control) {
    680  * 		if (!MatchClass(*control, *string)) {
    681  * 			return (0);
    682  * 		}
    683  *
    684  * 		string++;
    685  * 		control++;
    686  * 	}
    687  *
    688  * 	if (*string || *control) {
    689  * 		return (0);
    690  * 	}
    691  *
    692  * 	return (1);
    693  * }
    694  */
    695