build: remove map.noexstk and map.noexdata (now default)
[unleashed.git] / usr / src / lib / pam_modules / authtok_check / rules.c
blob55fdf40070bbf11625f1632230fb0e49f9e0dcba
1 /*
2 * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
3 * Use is subject to license terms.
4 */
6 #pragma ident "%Z%%M% %I% %E% SMI"
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.
16 #include "packer.h"
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 ')'
45 int
46 Suffix(char *myword, char *suffix)
48 register int i;
49 register int j;
51 i = strlen(myword);
52 j = strlen(suffix);
54 if (i > j) {
55 return (STRCMP((myword + i - j), suffix));
56 } else {
57 return (-1);
61 char *
62 Reverse(register char *str) /* return a pointer to a reversal */
64 register int i;
65 register int j;
66 static char area[PATH_MAX];
68 j = i = strlen(str);
69 while (*str) {
70 area[--i] = *str++;
72 area[j] = '\0';
73 return (area);
76 char *
77 Uppercase(register char *str) /* return a pointer to an uppercase */
79 register char *ptr;
80 static char area[PATH_MAX];
82 ptr = area;
83 while (*str) {
84 *(ptr++) = CRACK_TOUPPER(*str);
85 str++;
87 *ptr = '\0';
89 return (area);
92 char *
93 Lowercase(register char *str) /* return a pointer to an lowercase */
95 register char *ptr;
96 static char area[PATH_MAX];
98 ptr = area;
99 while (*str) {
100 *(ptr++) = CRACK_TOLOWER(*str);
101 str++;
103 *ptr = '\0';
105 return (area);
108 char *
109 Capitalise(register char *str) /* return a pointer to an capitalised */
111 register char *ptr;
112 static char area[PATH_MAX];
114 ptr = area;
116 while (*str) {
117 *(ptr++) = CRACK_TOLOWER(*str);
118 str++;
121 *ptr = '\0';
122 area[0] = CRACK_TOUPPER(area[0]);
123 return (area);
126 char *
127 Pluralise(register char *string) /* returns a pointer to a plural */
129 register int length;
130 static char area[PATH_MAX];
132 length = strlen(string);
133 (void) strlcpy(area, string, PATH_MAX);
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");
150 } else if (string[length - 1] == 's') {
151 /* bias -> biases */
152 (void) strcat(area, "es");
153 } else {
154 /* catchall */
155 (void) strcat(area, "s");
158 return (area);
161 char *
162 Substitute(register char *string, register char old,
163 register char new) /* returns pointer to a swapped about copy */
165 register char *ptr;
166 static char area[PATH_MAX];
168 ptr = area;
169 while (*string) {
170 *(ptr++) = (*string == old ? new : *string);
171 string++;
173 *ptr = '\0';
174 return (area);
177 /* returns pointer to a purged copy */
178 char *
179 Purge(register char *string, register char target)
181 register char *ptr;
182 static char area[PATH_MAX];
183 ptr = area;
184 while (*string) {
185 if (*string != target) {
186 *(ptr++) = *string;
188 string++;
190 *ptr = '\0';
191 return (area);
193 /* -------- CHARACTER CLASSES START HERE -------- */
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
202 MatchClass(register char class, register char input)
204 register char c;
205 register int retval;
207 retval = 0;
209 switch (class) {
210 /* ESCAPE */
212 case '?': /* ?? -> ? */
213 if (input == '?') {
214 retval = 1;
216 break;
218 /* ILLOGICAL GROUPINGS (ie: not in ctype.h) */
220 case 'V':
221 case 'v': /* vowels */
222 c = CRACK_TOLOWER(input);
223 if (strchr("aeiou", c)) {
224 retval = 1;
226 break;
228 case 'C':
229 case 'c': /* consonants */
230 c = CRACK_TOLOWER(input);
231 if (strchr("bcdfghjklmnpqrstvwxyz", c)) {
232 retval = 1;
234 break;
236 case 'W':
237 case 'w': /* whitespace */
238 if (strchr("\t ", input)) {
239 retval = 1;
241 break;
243 case 'P':
244 case 'p': /* punctuation */
245 if (strchr(".`,:;'!?\"", input)) {
246 retval = 1;
248 break;
250 case 'S':
251 case 's': /* symbols */
252 if (strchr("$%%^&*()-_+=|\\[]{}#@/~", input)) {
253 retval = 1;
255 break;
257 /* LOGICAL GROUPINGS */
259 case 'L':
260 case 'l': /* lowercase */
261 if (islower(input)) {
262 retval = 1;
264 break;
266 case 'U':
267 case 'u': /* uppercase */
268 if (isupper(input)) {
269 retval = 1;
271 break;
273 case 'A':
274 case 'a': /* alphabetic */
275 if (isalpha(input)) {
276 retval = 1;
278 break;
280 case 'X':
281 case 'x': /* alphanumeric */
282 if (isalnum(input)) {
283 retval = 1;
285 break;
287 case 'D':
288 case 'd': /* digits */
289 if (isdigit(input)) {
290 retval = 1;
292 break;
295 if (isupper(class)) {
296 return (!retval);
298 return (retval);
301 char *
302 PolyStrchr(register char *string, register char class)
304 while (*string) {
305 if (MatchClass(class, *string)) {
306 return (string);
308 string++;
310 return ((char *)0);
313 /* returns pointer to a swapped about copy */
314 char *
315 PolySubst(register char *string, register char class, register char new)
317 register char *ptr;
318 static char area[PATH_MAX];
320 ptr = area;
321 while (*string) {
322 *(ptr++) = (MatchClass(class, *string) ? new : *string);
323 string++;
325 *ptr = '\0';
326 return (area);
329 /* returns pointer to a purged copy */
330 char *
331 PolyPurge(register char *string, register char class)
333 register char *ptr;
334 static char area[PATH_MAX];
336 ptr = area;
337 while (*string) {
338 if (!MatchClass(class, *string)) {
339 *(ptr++) = *string;
341 string++;
343 *ptr = '\0';
344 return (area);
346 /* -------- BACK TO NORMALITY -------- */
349 Char2Int(char character)
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);
358 return (-1);
361 /* returns a pointer to a controlled Mangle */
362 char *
363 Mangle(char *input, char *control)
365 int limit;
366 register char *ptr;
367 static char area[PATH_MAX];
368 char area2[PATH_MAX];
370 area[0] = '\0';
371 (void) strlcpy(area, input, PATH_MAX);
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);
408 if (strlen(area) <= limit) {
409 return ((char *)0);
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);
421 if (strlen(area) >= limit) {
422 return ((char *)0);
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);
435 break;
436 case RULE_APPEND:
437 if (!ptr[1]) {
438 return ((char *)0);
439 } else {
440 register char *string;
442 string = area;
443 while (*(string++));
444 string[-1] = *(++ptr);
445 *string = '\0';
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;
456 start = Char2Int(*(++ptr));
457 length = Char2Int(*(++ptr));
458 if (start < 0 || length < 0) {
459 return ((char *)0);
461 (void) strlcpy(area2, area, PATH_MAX);
462 for (i = 0; length-- &&
463 area2[start + i]; i++) {
464 area[i] = area2[start + i];
466 /* cant use strncpy()-no trailing NUL */
467 area[i] = '\0';
469 break;
470 case RULE_OVERSTRIKE:
471 if (!ptr[1] || !ptr[2]) {
472 return ((char *)0);
473 } else {
474 register int i;
476 i = Char2Int(*(++ptr));
477 if (i < 0) {
478 return ((char *)0);
479 } else {
480 ++ptr;
481 if (area[i]) {
482 area[i] = *ptr;
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;
495 i = Char2Int(*(++ptr));
496 if (i < 0) {
497 return ((char *)0);
499 p1 = area;
500 p2 = area2;
501 while (i && *p1) {
502 i--;
503 *(p2++) = *(p1++);
505 *(p2++) = *(++ptr);
506 (void) strlcpy(p2, p1, PATH_MAX);
507 (void) strlcpy(area, area2, PATH_MAX);
509 break;
510 /* THE FOLLOWING RULES REQUIRE CLASS MATCHING */
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;
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;
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);
545 } else {
546 if (!PolyStrchr(area, ptr[2])) {
547 return ((char *)0);
549 ptr += 2;
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);
560 } else {
561 if (PolyStrchr(area, ptr[2])) {
562 return ((char *)0);
564 ptr += 2;
566 break;
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.
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;
583 if ((i = Char2Int(ptr[1])) < 0) {
584 return ((char *)0);
586 if (ptr[2] != RULE_CLASS) {
587 ptr += 2;
588 if (area[i] != *ptr) {
589 return ((char *)0);
591 } else {
592 ptr += 3;
593 if (!MatchClass(*ptr,
594 area[i])) {
595 return ((char *)0);
599 break;
601 case RULE_DFIRST:
602 if (area[0]) {
603 register int i;
605 for (i = 1; area[i]; i++) {
606 area[i - 1] = area[i];
608 area[i - 1] = '\0';
610 break;
612 case RULE_DLAST:
613 if (area[0]) {
614 register int i;
616 for (i = 1; area[i]; i++);
617 area[i - 1] = '\0';
619 break;
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);
631 } else {
632 ptr += 2;
633 if (!MatchClass(*ptr,
634 area[0])) {
635 return ((char *)0);
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;
647 for (i = 0; area[i]; i++);
649 if (i > 0) {
650 i--;
651 } else {
652 return ((char *)0);
654 if (ptr[1] != RULE_CLASS) {
655 ptr++;
656 if (area[i] != *ptr) {
657 return ((char *)0);
659 } else {
660 ptr += 2;
661 if (!MatchClass(*ptr,
662 area[i])) {
663 return ((char *)0);
667 break;
670 if (!area[0]) { /* have we deweted de poor widdle fing away? */
671 return ((char *)0);
673 return (area);
676 * int
677 * PMatch(register char *control, register char *string)
679 * while (*string && *control) {
680 * if (!MatchClass(*control, *string)) {
681 * return (0);
684 * string++;
685 * control++;
688 * if (*string || *control) {
689 * return (0);
692 * return (1);