source: branches/samba-3.3.x/examples/auth/crackcheck/rules.c

Last change on this file was 374, checked in by Herwig Bauernfeind, 16 years ago

Update Samba 3.3 to 3.3.10 (new files)

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