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