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
Suffix(char * myword,char * suffix)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 *
Reverse(register char * str)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 *
Uppercase(register char * str)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 *
Lowercase(register char * str)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 *
Capitalise(register char * str)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 *
Pluralise(register char * string)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 *
Substitute(register char * string,register char old,register char new)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 *
Purge(register char * string,register char target)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
MatchClass(register char class,register char input)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 *
PolyStrchr(register char * string,register char class)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 *
PolySubst(register char * string,register char class,register char new)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 *
PolyPurge(register char * string,register char class)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
Char2Int(char character)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 *
Mangle(char * input,char * control)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