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